r/wg21
P3724R3 - Integer division WG21
Posted by u/div_quot_realist · 5 hr. ago

Document: P3724R3
Author: Jan Schultke
Date: 2026-02-20
Audience: LEWG

C++ only gives you truncating / and a remainder whose sign follows the dividend. That combo is fine until you want ceiling buckets, Python-style floor division, or nearest-with-ties rules - then the Stack Overflow answers start lying, overflowing, or invoking UB on INT_MIN. Schultke proposes a full family of std::div_* and std::div_rem_* plus a dedicated std::mod for the divisor-sign remainder you want in real modular arithmetic.

R3 rebases the wording on N5032, expands the language survey (including Julia-style rounding modes), and spells out tie-breaking motivation. SG6 already voted out div_to_even style top-level modes and sent an R2-shaped paper toward LEWG. The painful bit the paper hammers home: for any rounding mode except toward zero, computing remainder = x - q*y naively can multiply back into overflow even when the division itself is defined.

▲ 56 points (86% upvoted) · 25 comments
sorted by: best
u/AutoModerator 1 point 5 hr. ago pinned comment

Paper: P3724R3 · Authors: Jan Schultke · Target: LEWG · Date: 2026-02-20

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

u/daily_overflow_hunter 42 points 4 hr. ago

The paper is worth reading for section 3.2 alone. Everyone "knows" remainder = x - quotient * divisor. For truncating division that is the identity you expect. For ceiling-style quotients it is not - the worked INT_MAX example is the kind of thing that passes code review because the intermediate q looks obviously right.

That is why killing off paired div_rem_* would be malpractice. The wording even puts the note in Returns so people stop cargo-culting the subtraction.

u/constexpr_godbolt_monkey 18 points 3 hr. ago

I duplicated the example on Godbolt with -ftrapv once and the compiler basically laughed at me. The scary part is how silent it is in normal builds.

u/yet_another_rust_evangelist 31 points 4 hr. ago

Rust / on integers truncates toward zero, same trap as C++. At least the paper's language table owns that instead of pretending the problem is unique to C++. Different languages, identical footgun.

u/axiom_first_casualty 28 points 4 hr. ago

From the paper, on the classic "ceil division" snippet:

The quotient q would be 1, not 0 for inputs x = -1 and y = 2, which is obviously wrong because it rounds -0.5 up to 1, skipping zero.

That is the comment thread in a microcosm - dozens of upvotes, subtle sign bug, nobody updates the disclaimer for ten years.

u/pedagogy_and_parentheses 22 points 3 hr. ago

Teaching lens: students hit % and think they got mathematical modulo. Then they port Python mental models and wonder why (a / b) * b + (a % b) stopped being the identity they memorized. Having spelled-out div_to_neg_inf and mod in the standard library is the kind of thing that stops a whole week of office hours.

u/api_surface_karen 19 points 3 hr. ago

LEWG is going to look at the synopsis and twitch. That is a lot of identifiers. I get why a runtime rounding parameter lost - the paper shows the switch exploding into totally different micro-kernels - but emotionally I still want one entry point and a short enum.

u/branch_predictor_gore 31 points 3 hr. ago

The whole point is the mode is almost always compile-time fixed. You want div_to_pos_inf(x, y) to inline into the happy path for "how many buckets" without feeding a dead enum through the frontend so the optimizer has to prove the switch collapses.

u/api_surface_karen 8 points 2 hr. ago

Fair. I will still whine about autocomplete noise on principle.

u/third_rail_modulo 17 points 3 hr. ago

std::mod is the one that will confuse people who only read the name. The paper basically admits mod is a loaded word, then argues it is still the least bad label because it matches Haskell and friends for "remainder when you floor toward negative infinity". Worth reading §4.2.4 before bikeshedding on Reddit.

u/sg6_minutes_cryptid 16 points 2 hr. ago

Process note: SG6 took a consensus poll to drop div_to_even / div_to_odd because nobody could name a real workload. The author even argues the names were easy to confuse with tie-breaking variants. If you miss them, you are officially on the wrong side of a unanimous-ish room.

u/numeric_folk_wisdom 14 points 2 hr. ago

The ISO/IEC 60559 alignment table is clever politics. You can point at the floating-point rounding attributes and say "we are not inventing a zoo, we are mirroring the zoo that already ate numerical analysis."

u/embedded_buckets_only_positive 12 points 2 hr. ago

Embedded angle: a lot of firmware code never sees negative indices, so the scary examples look academic - until the day someone feeds a backwards iterator into your ring-buffer math and your hand-rolled ceil macro goes nonlinear. I will take boring library names over another copy of the three-branch hack from 2004.

u/namespace_std_enthusiast 11 points 2 hr. ago

div_result with operator<=> is the quiet modernization win - comparable pairs without dragging div_t weirdness into generics. P3161 energy, except division-shaped.

u/simd_patience_zero 9 points 1 hr. ago

§4.6 punts SIMD overloads to a follow-up. Smart - div_rem returning something comparable with masks opens a second paper's worth of design questions. Still, game-math Twitter is going to ask anyway.

u/boost_safe_numeric_passing_by 8 points 1 hr. ago

Boost.SafeNumerics solves a different problem (policy-checked arithmetic). Nice complement if you need both rounding discipline and "no surprises on overflow" at the type level. github.com/boostorg/safe_numerics

u/previous_paper_witness 7 points 1 hr. ago

P0105 got huge and stalled. P1889 carried pieces until it did not. This paper is basically "what if we shipped the division slice without reuniting the entire Crowl agenda." Historical baggage is half the discussion.

u/noexcept_is_a_lie_lol 19 points 1 hr. ago

"Not noexcept because it inherits division's UB contract" is the correct call. People will still file issues asking for expected overloads. Prepare emotionally.

u/julia_escapee_drunkposting 25 points 1 hr. ago

R3 adds Julia rounding modes to the survey table and half of you will still comment "lol just use Python //" without reading the signed case. Sir this is a Wendy's with defined wrap semantics.

u/eisenwave_github_tourist 6 points 52 min. ago

Reference implementation lives at github.com/Eisenwave/integer-division if you want to diff against your favorite macro soup.

u/naming_masochist 5 points 41 min. ago

I hated div_to_pos_inf until I tried explaining floor vs toward negative infinity to a intern on a whiteboard. Self-documenting wins even if it is verbose.

u/feature_macro_hound 4 points 33 min. ago

__cpp_lib_integer_division placeholder in the draft wording - nice that they remembered the macro story alongside saturating arithmetic neighbors.

u/committee_gonna_committee_lmao 38 points 28 min. ago

great, another paper that will take 10 years to get through LEWG

u/div_t_was_always_weird 4 points 19 min. ago

Honestly std::div from C89 is the awkward ancestor everyone pretends not to know at parties. These new names at least tell you which ring you are working in.

u/probably_not_a_committee_member 3 points 8 min. ago

P3724 on GitHub: wg21.link/P3724/github - issue bot already has the revision chain if you want the tick-tock.