<!DOCTYPE html>
<html>
<head>
  <meta charset=UTF-8 /><meta name=viewport content="width=device-width, initial-scale=1"/><link rel=preconnent href=https://fonts%2egoogleapis%2ecom />
  <link rel=preconnent href=https://fonts%2egstatic%2ecom crossorigin/>
  <link rel=stylesheet href="https://fonts%2egoogleapis%2ecom/css2?family=Fira+Code:wght@300%2e%2e700&family=Noto+Sans:ital,wght@0,100%2e%2e900;1,100%2e%2e900&family=Noto+Serif:ital,wght@0,100%2e%2e900;1,100%2e%2e900&display=swap"/>
  <style>
html {
    --sans-serif-family: "Noto Sans", sans-serif;
    --serif-family: "Noto Serif", serif;
    --monospace-family: "Fira Code", monospace;

    --light-background-color: white;
    --light-deep-background-color: #fafafa;
    --light-text-color: black;
    --light-border-color: #aaa;
    --light-table-border-color: #777;
    --light-del-color: #be1621;
    --light-del-background-color: #fbe6e8;
    --light-ins-color: #17752d;
    --light-ins-background-color: #e4faea;
    --light-para-color: rgb(10, 73, 136);
    --light-a-color: rgb(10, 73, 136);
    --light-a-visited-color: rgb(44, 10, 136);
    --light-a-hover-color: rgb(15, 93, 170);
    --light-mark-color: black;
    --light-mark-background-color: #ffff85;
    --light-abstract-border-color: #707070;
    --light-abstract-background-color: #f0f0f0;
    --light-abstract-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M660-160h40v-160h-40v160Zm20-200q8 0 14-6t6-14q0-8-6-14t-14-6q-8 0-14 6t-6 14q0 8 6 14t14 6ZM200-800v640-640 200-200Zm80 400h147q11-23 25.5-43t32.5-37H280v80Zm0 160h123q-3-20-3-40t3-40H280v80ZM200-80q-33 0-56.5-23.5T120-160v-640q0-33 23.5-56.5T200-880h320l240 240v92q-19-6-39-9t-41-3v-40H480v-200H200v640h227q11 23 25.5 43T485-80H200Zm480-400q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480Z"/></svg>');
    --light-blockquote-border-color: #707070;
    --light-blockquote-background-color: #f0f0f0;
    --light-blockquote-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="%23707070"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7.17 17c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94zm10 0c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94z"/></svg>');
    --light-bug-block-border-color: #9f7b5d;
    --light-bug-block-background-color: #f0e2d9;
    --light-bug-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%239f7b5d"><path d="M480-120q-64 0-114.5-33T283-240l-95 54-40-69 103-60q-3-11-5-22.5t-4-22.5H120v-80h122q2-12 4-23.5t5-22.5l-103-60 40-69 94 55q8-14 18.5-27.5T322-612q-2-7-2-14v-14q0-24 7-46t19-41l-66-66 56-57 70 68q17-9 35.5-13.5T480-800q20 0 39 5t36 14l69-69 56 57-66 66q12 19 18.5 41t6.5 46v13.5q0 6.5-2 13.5 11 11 21.5 25t18.5 28l95-54 40 69-104 59q3 11 5.5 22.5T718-440h122v80H718q-2 12-4 23.5t-5 22.5l103 60-40 69-95-55q-32 54-82.5 87T480-120Zm-76-546q17-7 36.5-10.5T480-680q20 0 38.5 3t35.5 10q-8-23-28-38t-46-15q-26 0-47 15.5T404-666Zm76 466q73 0 116.5-61T640-400q0-70-40.5-135T480-600q-78 0-119 64.5T320-400q0 78 43.5 139T480-200Zm-40-80v-240h80v240h-80Z"/></svg>');
    --light-decision-block-border-color: #ab6fa2;
    --light-decision-block-background-color: #f4e6f4;
    --light-decision-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6fa2"><path d="M160-120v-80h480v80H160Zm226-194L160-540l84-86 228 226-86 86Zm254-254L414-796l86-84 226 226-86 86Zm184 408L302-682l56-56 522 522-56 56Z"/></svg>');
    --light-del-block-border-color: #be1621;
    --light-del-block-background-color: #fbe6e8;
    --light-del-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23be1621"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>');
    --light-details-border-color: #707070;
    --light-details-background-color: #f0f0f0;
    --light-details-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --light-diff-block-border-color: #707070;
    --light-diff-block-background-color: #f0f0f0;
    --light-diff-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M500-520h80v-80h80v-80h-80v-80h-80v80h-80v80h80v80Zm-80 160h240v-80H420v80ZM320-200q-33 0-56.5-23.5T240-280v-560q0-33 23.5-56.5T320-920h280l240 240v400q0 33-23.5 56.5T760-200H320Zm0-80h440v-360L560-840H320v560ZM160-40q-33 0-56.5-23.5T80-120v-560h80v560h440v80H160Zm160-240v-560 560Z"/></svg>');
    --light-example-block-border-color: #6f8aab;
    --light-example-block-background-color: #e6e9f4;
    --light-example-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236f8aab"><path d="M300-80q-58 0-99-41t-41-99v-520q0-58 41-99t99-41h500v600q-25 0-42.5 17.5T740-220q0 25 17.5 42.5T800-160v80H300Zm-60-267q14-7 29-10t31-3h20v-440h-20q-25 0-42.5 17.5T240-740v393Zm160-13h320v-440H400v440Zm-160 13v-453 453Zm60 187h373q-6-14-9.5-28.5T660-220q0-16 3-31t10-29H300q-26 0-43 17.5T240-220q0 26 17 43t43 17Z"/></svg>');
    --light-important-block-border-color: #b05252;
    --light-important-block-background-color: #f4e6e6;
    --light-important-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6f6f"><path d="M480-120q-33 0-56.5-23.5T400-200q0-33 23.5-56.5T480-280q33 0 56.5 23.5T560-200q0 33-23.5 56.5T480-120Zm-80-240v-480h160v480H400Z"/></svg>');
    --light-ins-block-border-color: #17752d;
    --light-ins-block-background-color: #e4faea;
    --light-ins-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%2317752d"><path d="M440-240h80v-120h120v-80H520v-120h-80v120H320v80h120v120ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/></svg>');
    --light-note-block-border-color: #6fab6f;
    --light-note-block-background-color: #e6f4e9;
    --light-note-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab6f"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --light-tip-block-border-color: #b0a029;
    --light-tip-block-background-color: #f4f4e6;
    --light-tip-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23b0a029"><path d="M480-80q-33 0-56.5-23.5T400-160h160q0 33-23.5 56.5T480-80ZM320-200v-80h320v80H320Zm10-120q-69-41-109.5-110T180-580q0-125 87.5-212.5T480-880q125 0 212.5 87.5T780-580q0 81-40.5 150T630-320H330Zm24-80h252q45-32 69.5-79T700-580q0-92-64-156t-156-64q-92 0-156 64t-64 156q0 54 24.5 101t69.5 79Zm126 0Z"/></svg>');
    --light-todo-block-border-color: #6faba0;
    --light-todo-block-background-color: #e6f4f3;
    --light-todo-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236faba0"><path d="M680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80Zm67-105 28-28-75-75v-112h-40v128l87 87Zm-547 65q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h167q11-35 43-57.5t70-22.5q40 0 71.5 22.5T594-840h166q33 0 56.5 23.5T840-760v250q-18-13-38-22t-42-16v-212h-80v120H280v-120h-80v560h212q7 22 16 42t22 38H200Zm280-640q17 0 28.5-11.5T520-800q0-17-11.5-28.5T480-840q-17 0-28.5 11.5T440-800q0 17 11.5 28.5T480-760Z"/></svg>');
    --light-warning-block-border-color: #af8141;
    --light-warning-block-background-color: #f4eee6;
    --light-warning-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23af8141"><path d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"/></svg>');
    --light-theme-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="black"><path d="M480-360q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35Zm0 80q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Zm326-268Z"/></svg>');

    --dark-background-color: #202020;
    --dark-deep-background-color: #1a1a1a;
    --dark-text-color: #f0f0f0;
    --dark-border-color: #505050;
    --dark-table-border-color: #777;
    --dark-del-background-color: #67060c;
    --dark-del-color: #ffdcd7;
    --dark-ins-background-color: #033a16;
    --dark-ins-color: #aff5b4;
    --dark-para-color: #5bc0ff;
    --dark-a-color: #5bc0ff;
    --dark-a-visited-color: #c6a8ff;
    --dark-a-hover-color: #afd7ff;
    --dark-mark-color: #ededa8;
    --dark-mark-background-color: #525230;
    --dark-abstract-border-color: #999999;
    --dark-abstract-background-color: #2c2c2c;
    --dark-abstract-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23999999"><path d="M660-160h40v-160h-40v160Zm20-200q8 0 14-6t6-14q0-8-6-14t-14-6q-8 0-14 6t-6 14q0 8 6 14t14 6ZM200-800v640-640 200-200Zm80 400h147q11-23 25.5-43t32.5-37H280v80Zm0 160h123q-3-20-3-40t3-40H280v80ZM200-80q-33 0-56.5-23.5T120-160v-640q0-33 23.5-56.5T200-880h320l240 240v92q-19-6-39-9t-41-3v-40H480v-200H200v640h227q11 23 25.5 43T485-80H200Zm480-400q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480Z"/></svg>');
    --dark-blockquote-border-color: #707070;
    --dark-blockquote-background-color: #2c2c2c;
    --dark-blockquote-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="%23707070"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7.17 17c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94zm10 0c.51 0 .98-.29 1.2-.74l1.42-2.84c.14-.28.21-.58.21-.89V8c0-.55-.45-1-1-1h-4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h2l-1.03 2.06c-.45.89.2 1.94 1.2 1.94z"/></svg>');
    --dark-bug-block-border-color: #ab866f;
    --dark-bug-block-background-color: #373028;
    --dark-bug-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab866f"><path d="M480-120q-64 0-114.5-33T283-240l-95 54-40-69 103-60q-3-11-5-22.5t-4-22.5H120v-80h122q2-12 4-23.5t5-22.5l-103-60 40-69 94 55q8-14 18.5-27.5T322-612q-2-7-2-14v-14q0-24 7-46t19-41l-66-66 56-57 70 68q17-9 35.5-13.5T480-800q20 0 39 5t36 14l69-69 56 57-66 66q12 19 18.5 41t6.5 46v13.5q0 6.5-2 13.5 11 11 21.5 25t18.5 28l95-54 40 69-104 59q3 11 5.5 22.5T718-440h122v80H718q-2 12-4 23.5t-5 22.5l103 60-40 69-95-55q-32 54-82.5 87T480-120Zm-76-546q17-7 36.5-10.5T480-680q20 0 38.5 3t35.5 10q-8-23-28-38t-46-15q-26 0-47 15.5T404-666Zm76 466q73 0 116.5-61T640-400q0-70-40.5-135T480-600q-78 0-119 64.5T320-400q0 78 43.5 139T480-200Zm-40-80v-240h80v240h-80Z"/></svg>');
    --dark-details-border-color: #707070;
    --dark-details-background-color: #2c2c2c;
    --dark-details-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --dark-decision-block-border-color: #ab6fa2;
    --dark-decision-block-background-color: #30232d;
    --dark-decision-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab6fa2"><path d="M160-120v-80h480v80H160Zm226-194L160-540l84-86 228 226-86 86Zm254-254L414-796l86-84 226 226-86 86Zm184 408L302-682l56-56 522 522-56 56Z"/></svg>');
    --dark-del-block-border-color: #be5e64;
    --dark-del-block-background-color: #302323;
    --dark-del-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23be5e64"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>');
    --dark-diff-block-border-color: #707070;
    --dark-diff-block-background-color: #2c2c2c;
    --dark-diff-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23707070"><path d="M500-520h80v-80h80v-80h-80v-80h-80v80h-80v80h80v80Zm-80 160h240v-80H420v80ZM320-200q-33 0-56.5-23.5T240-280v-560q0-33 23.5-56.5T320-920h280l240 240v400q0 33-23.5 56.5T760-200H320Zm0-80h440v-360L560-840H320v560ZM160-40q-33 0-56.5-23.5T80-120v-560h80v560h440v80H160Zm160-240v-560 560Z"/></svg>');
    --dark-example-block-border-color: #6f81ab;
    --dark-example-block-background-color: #232630;
    --dark-example-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236f81ab"><path d="M300-80q-58 0-99-41t-41-99v-520q0-58 41-99t99-41h500v600q-25 0-42.5 17.5T740-220q0 25 17.5 42.5T800-160v80H300Zm-60-267q14-7 29-10t31-3h20v-440h-20q-25 0-42.5 17.5T240-740v393Zm160-13h320v-440H400v440Zm-160 13v-453 453Zm60 187h373q-6-14-9.5-28.5T660-220q0-16 3-31t10-29H300q-26 0-43 17.5T240-220q0 26 17 43t43 17Z"/></svg>');
    --dark-important-block-border-color: #b06262;
    --dark-important-block-background-color: #302323;
    --dark-important-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23b06262"><path d="M480-120q-33 0-56.5-23.5T400-200q0-33 23.5-56.5T480-280q33 0 56.5 23.5T560-200q0 33-23.5 56.5T480-120Zm-80-240v-480h160v480H400Z"/></svg>');
    --dark-ins-block-border-color: #5bab6d;
    --dark-ins-block-background-color: #233023;
    --dark-ins-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%235bab6d"><path d="M440-240h80v-120h120v-80H520v-120h-80v120H320v80h120v120ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z"/></svg>');
    --dark-note-block-border-color: #6fab76;
    --dark-note-block-background-color: #233025;
    --dark-note-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab76"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>');
    --dark-tip-block-border-color: #a2ab6f;
    --dark-tip-block-background-color: #2f3023;
    --dark-tip-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23a2ab6f"><path d="M480-80q-33 0-56.5-23.5T400-160h160q0 33-23.5 56.5T480-80ZM320-200v-80h320v80H320Zm10-120q-69-41-109.5-110T180-580q0-125 87.5-212.5T480-880q125 0 212.5 87.5T780-580q0 81-40.5 150T630-320H330Zm24-80h252q45-32 69.5-79T700-580q0-92-64-156t-156-64q-92 0-156 64t-64 156q0 54 24.5 101t69.5 79Zm126 0Z"/></svg>');
    --dark-todo-block-border-color: #6fab98;
    --dark-todo-block-background-color: #23302e;
    --dark-todo-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%236fab98"><path d="M680-80q-83 0-141.5-58.5T480-280q0-83 58.5-141.5T680-480q83 0 141.5 58.5T880-280q0 83-58.5 141.5T680-80Zm67-105 28-28-75-75v-112h-40v128l87 87Zm-547 65q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h167q11-35 43-57.5t70-22.5q40 0 71.5 22.5T594-840h166q33 0 56.5 23.5T840-760v250q-18-13-38-22t-42-16v-212h-80v120H280v-120h-80v560h212q7 22 16 42t22 38H200Zm280-640q17 0 28.5-11.5T520-800q0-17-11.5-28.5T480-840q-17 0-28.5 11.5T440-800q0 17 11.5 28.5T480-760Z"/></svg>');
    --dark-warning-block-border-color: #ab9c6f;
    --dark-warning-block-background-color: #302b23;
    --dark-warning-block-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ab9c6f"><path d="M109-120q-11 0-20-5.5T75-140q-5-9-5.5-19.5T75-180l370-640q6-10 15.5-15t19.5-5q10 0 19.5 5t15.5 15l370 640q6 10 5.5 20.5T885-140q-5 9-14 14.5t-20 5.5H109Zm69-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm0-120q17 0 28.5-11.5T520-400v-120q0-17-11.5-28.5T480-560q-17 0-28.5 11.5T440-520v120q0 17 11.5 28.5T480-360Zm0-100Z"/></svg>');
    --dark-theme-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23f0f0f0"><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Zm0-80q88 0 158-48.5T740-375q-20 5-40 8t-40 3q-123 0-209.5-86.5T364-660q0-20 3-40t8-40q-78 32-126.5 102T200-480q0 116 82 198t198 82Zm-10-270Z"/></svg>');

    --indent: 2.5em;
    --border-radius: 0.25em;
}

/* BEGIN LIGHT AND DARK THEME */

@media (prefers-color-scheme: light) {
    html {
        --background-color: var(--light-background-color);
        --deep-background-color: var(--light-deep-background-color);
        --text-color: var(--light-text-color);
        --border-color: var(--light-border-color);
        --table-border-color: var(--light-table-border-color);
        --del-color: var(--light-del-color);
        --del-background-color: var(--light-del-background-color);
        --ins-color: var(--light-ins-color);
        --ins-background-color: var(--light-ins-background-color);
        --para-color: var(--light-para-color);
        --a-color: var(--light-a-color);
        --a-visited-color: var(--light-a-visited-color);
        --a-hover-color: var(--light-a-hover-color);
        --mark-color: var(--light-mark-color);
        --mark-background-color: var(--light-mark-background-color);
        --abstract-border-color: var(--light-abstract-border-color);
        --abstract-background-color: var(--light-abstract-background-color);
        --abstract-image: var(--light-abstract-image);
        --blockquote-border-color: var(--light-blockquote-border-color);
        --blockquote-background-color: var(--light-blockquote-background-color);
        --blockquote-image: var(--light-blockquote-image);
        --bug-block-border-color: var(--light-bug-block-border-color);
        --bug-block-background-color: var(--light-bug-block-background-color);
        --bug-block-image: var(--light-bug-block-image);
        --decision-block-border-color: var(--light-decision-block-border-color);
        --decision-block-background-color: var(--light-decision-block-background-color);
        --decision-block-image: var(--light-decision-block-image);
        --del-block-border-color: var(--light-del-block-border-color);
        --del-block-background-color: var(--light-del-block-background-color);
        --del-block-image: var(--light-del-block-image);
        --details-border-color: var(--light-details-border-color);
        --details-background-color: var(--light-details-background-color);
        --details-image: var(--light-details-image);
        --diff-block-border-color: var(--light-diff-block-border-color);
        --diff-block-background-color: var(--light-diff-block-background-color);
        --diff-block-image: var(--light-diff-block-image);
        --example-block-border-color: var(--light-example-block-border-color);
        --example-block-background-color: var(--light-example-block-background-color);
        --example-block-image: var(--light-example-block-image);
        --important-block-border-color: var(--light-important-block-border-color);
        --important-block-background-color: var(--light-important-block-background-color);
        --important-block-image: var(--light-important-block-image);
        --ins-block-border-color: var(--light-ins-block-border-color);
        --ins-block-background-color: var(--light-ins-block-background-color);
        --ins-block-image: var(--light-ins-block-image);
        --note-block-border-color: var(--light-note-block-border-color);
        --note-block-background-color: var(--light-note-block-background-color);
        --note-block-image: var(--light-note-block-image);
        --tip-block-border-color: var(--light-tip-block-border-color);
        --tip-block-background-color: var(--light-tip-block-background-color);
        --tip-block-image: var(--light-tip-block-image);
        --todo-block-border-color: var(--light-todo-block-border-color);
        --todo-block-background-color: var(--light-todo-block-background-color);
        --todo-block-image: var(--light-todo-block-image);
        --warning-block-border-color: var(--light-warning-block-border-color);
        --warning-block-background-color: var(--light-warning-block-background-color);
        --warning-block-image: var(--light-warning-block-image);
        --theme-icon: var(--light-theme-icon);
    }
}

@media (prefers-color-scheme: dark) {
    html {
        --background-color: var(--dark-background-color);
        --deep-background-color: var(--dark-deep-background-color);
        --text-color: var(--dark-text-color);
        --border-color: var(--dark-border-color);
        --table-border-color: var(--dark-table-border-color);
        --del-color: var(--dark-del-color);
        --del-background-color: var(--dark-del-background-color);
        --ins-color: var(--dark-ins-color);
        --ins-background-color: var(--dark-ins-background-color);
        --para-color: var(--dark-para-color);
        --a-color: var(--dark-a-color);
        --a-visited-color: var(--dark-a-visited-color);
        --a-hover-color: var(--dark-a-hover-color);
        --mark-color: var(--dark-mark-color);
        --mark-background-color: var(--dark-mark-background-color);
        --abstract-border-color: var(--dark-abstract-border-color);
        --abstract-background-color: var(--dark-abstract-background-color);
        --abstract-image: var(--dark-abstract-image);
        --blockquote-border-color: var(--dark-blockquote-border-color);
        --blockquote-background-color: var(--dark-blockquote-background-color);
        --blockquote-image: var(--dark-blockquote-image);
        --bug-block-border-color: var(--dark-bug-block-border-color);
        --bug-block-background-color: var(--dark-bug-block-background-color);
        --bug-block-image: var(--dark-bug-block-image);
        --decision-block-border-color: var(--dark-decision-block-border-color);
        --decision-block-background-color: var(--dark-decision-block-background-color);
        --decision-block-image: var(--dark-decision-block-image);
        --del-block-border-color: var(--dark-del-block-border-color);
        --del-block-background-color: var(--dark-del-block-background-color);
        --del-block-image: var(--dark-del-block-image);
        --details-border-color: var(--dark-details-border-color);
        --details-background-color: var(--dark-details-background-color);
        --details-image: var(--dark-details-image);
        --diff-block-border-color: var(--dark-diff-block-border-color);
        --diff-block-background-color: var(--dark-diff-block-background-color);
        --diff-block-image: var(--dark-diff-block-image);
        --example-block-border-color: var(--dark-example-block-border-color);
        --example-block-background-color: var(--dark-example-block-background-color);
        --example-block-image: var(--dark-example-block-image);
        --important-block-border-color: var(--dark-important-block-border-color);
        --important-block-background-color: var(--dark-important-block-background-color);
        --important-block-image: var(--dark-important-block-image);
        --ins-block-border-color: var(--dark-ins-block-border-color);
        --ins-block-background-color: var(--dark-ins-block-background-color);
        --ins-block-image: var(--dark-ins-block-image);
        --note-block-border-color: var(--dark-note-block-border-color);
        --note-block-background-color: var(--dark-note-block-background-color);
        --note-block-image: var(--dark-note-block-image);
        --tip-block-border-color: var(--dark-tip-block-border-color);
        --tip-block-background-color: var(--dark-tip-block-background-color);
        --tip-block-image: var(--dark-tip-block-image);
        --todo-block-border-color: var(--dark-todo-block-border-color);
        --todo-block-background-color: var(--dark-todo-block-background-color);
        --todo-block-image: var(--dark-todo-block-image);
        --warning-block-border-color: var(--dark-warning-block-border-color);
        --warning-block-background-color: var(--dark-warning-block-background-color);
        --warning-block-image: var(--dark-warning-block-image);
        --theme-icon: var(--dark-theme-icon);
    }
}

html.light {
    --background-color: var(--light-background-color);
    --deep-background-color: var(--light-deep-background-color);
    --text-color: var(--light-text-color);
    --border-color: var(--light-border-color);
    --table-border-color: var(--light-table-border-color);
    --del-color: var(--light-del-color);
    --del-background-color: var(--light-del-background-color);
    --ins-color: var(--light-ins-color);
    --ins-background-color: var(--light-ins-background-color);
    --para-color: var(--light-para-color);
    --a-color: var(--light-a-color);
    --a-visited-color: var(--light-a-visited-color);
    --a-hover-color: var(--light-a-hover-color);
    --mark-color: var(--light-mark-color);
    --mark-background-color: var(--light-mark-background-color);
    --abstract-border-color: var(--light-abstract-border-color);
    --abstract-background-color: var(--light-abstract-background-color);
    --abstract-image: var(--light-abstract-image);
    --blockquote-border-color: var(--light-blockquote-border-color);
    --blockquote-background-color: var(--light-blockquote-background-color);
    --blockquote-image: var(--light-blockquote-image);
    --bug-block-border-color: var(--light-bug-block-border-color);
    --bug-block-background-color: var(--light-bug-block-background-color);
    --bug-block-image: var(--light-bug-block-image);
    --decision-block-border-color: var(--light-decision-block-border-color);
    --decision-block-background-color: var(--light-decision-block-background-color);
    --decision-block-image: var(--light-decision-block-image);
    --del-block-border-color: var(--light-del-block-border-color);
    --del-block-background-color: var(--light-del-block-background-color);
    --del-block-image: var(--light-del-block-image);
    --details-border-color: var(--light-details-border-color);
    --details-background-color: var(--light-details-background-color);
    --details-image: var(--light-details-image);
    --diff-block-border-color: var(--light-diff-block-border-color);
    --diff-block-background-color: var(--light-diff-block-background-color);
    --diff-block-image: var(--light-diff-block-image);
    --example-block-border-color: var(--light-example-block-border-color);
    --example-block-background-color: var(--light-example-block-background-color);
    --example-block-image: var(--light-example-block-image);
    --important-block-border-color: var(--light-important-block-border-color);
    --important-block-background-color: var(--light-important-block-background-color);
    --important-block-image: var(--light-important-block-image);
    --ins-block-border-color: var(--light-ins-block-border-color);
    --ins-block-background-color: var(--light-ins-block-background-color);
    --ins-block-image: var(--light-ins-block-image);
    --note-block-border-color: var(--light-note-block-border-color);
    --note-block-background-color: var(--light-note-block-background-color);
    --note-block-image: var(--light-note-block-image);
    --tip-block-border-color: var(--light-tip-block-border-color);
    --tip-block-background-color: var(--light-tip-block-background-color);
    --tip-block-image: var(--light-tip-block-image);
    --todo-block-border-color: var(--light-todo-block-border-color);
    --todo-block-background-color: var(--light-todo-block-background-color);
    --todo-block-image: var(--light-todo-block-image);
    --warning-block-border-color: var(--light-warning-block-border-color);
    --warning-block-background-color: var(--light-warning-block-background-color);
    --warning-block-image: var(--light-warning-block-image);
    --theme-icon: var(--light-theme-icon);
}

html.dark {
    --background-color: var(--dark-background-color);
    --deep-background-color: var(--dark-deep-background-color);
    --text-color: var(--dark-text-color);
    --border-color: var(--dark-border-color);
    --table-border-color: var(--dark-table-border-color);
    --del-color: var(--dark-del-color);
    --del-background-color: var(--dark-del-background-color);
    --ins-color: var(--dark-ins-color);
    --ins-background-color: var(--dark-ins-background-color);
    --para-color: var(--dark-para-color);
    --a-color: var(--dark-a-color);
    --a-visited-color: var(--dark-a-visited-color);
    --a-hover-color: var(--dark-a-hover-color);
    --mark-color: var(--dark-mark-color);
    --mark-background-color: var(--dark-mark-background-color);
    --abstract-border-color: var(--dark-abstract-border-color);
    --abstract-background-color: var(--dark-abstract-background-color);
    --abstract-image: var(--dark-abstract-image);
    --blockquote-border-color: var(--dark-blockquote-border-color);
    --blockquote-background-color: var(--dark-blockquote-background-color);
    --blockquote-image: var(--dark-blockquote-image);
    --bug-block-border-color: var(--dark-bug-block-border-color);
    --bug-block-background-color: var(--dark-bug-block-background-color);
    --bug-block-image: var(--dark-bug-block-image);
    --decision-block-border-color: var(--dark-decision-block-border-color);
    --decision-block-background-color: var(--dark-decision-block-background-color);
    --decision-block-image: var(--dark-decision-block-image);
    --del-block-border-color: var(--dark-del-block-border-color);
    --del-block-background-color: var(--dark-del-block-background-color);
    --del-block-image: var(--dark-del-block-image);
    --details-border-color: var(--dark-details-border-color);
    --details-background-color: var(--dark-details-background-color);
    --details-image: var(--dark-details-image);
    --diff-block-border-color: var(--dark-diff-block-border-color);
    --diff-block-background-color: var(--dark-diff-block-background-color);
    --diff-block-image: var(--dark-diff-block-image);
    --example-block-border-color: var(--dark-example-block-border-color);
    --example-block-background-color: var(--dark-example-block-background-color);
    --example-block-image: var(--dark-example-block-image);
    --important-block-border-color: var(--dark-important-block-border-color);
    --important-block-background-color: var(--dark-important-block-background-color);
    --important-block-image: var(--dark-important-block-image);
    --ins-block-border-color: var(--dark-ins-block-border-color);
    --ins-block-background-color: var(--dark-ins-block-background-color);
    --ins-block-image: var(--dark-ins-block-image);
    --note-block-border-color: var(--dark-note-block-border-color);
    --note-block-background-color: var(--dark-note-block-background-color);
    --note-block-image: var(--dark-note-block-image);
    --tip-block-border-color: var(--dark-tip-block-border-color);
    --tip-block-background-color: var(--dark-tip-block-background-color);
    --tip-block-image: var(--dark-tip-block-image);
    --todo-block-border-color: var(--dark-todo-block-border-color);
    --todo-block-background-color: var(--dark-todo-block-background-color);
    --todo-block-image: var(--dark-todo-block-image);
    --warning-block-border-color: var(--dark-warning-block-border-color);
    --warning-block-background-color: var(--dark-warning-block-background-color);
    --warning-block-image: var(--dark-warning-block-image);
    --theme-icon: var(--dark-theme-icon);
}

/* END LIGHT AND DARK THEME */

html {
    margin: 0;
    width: 100%;
    font-family: var(--serif-family);
    font-size: 11pt;

    border-left: var(--border-thickness) solid var(--border-color);
    color: var(--text-color);
    background-color: var(--background-color);
}

body {
    --vertical-margin: 2rem;
    --margin-left: 3rem;
    --margin-right: 2rem;

    margin: var(--vertical-margin) var(--margin-right) var(--vertical-margin) var(--margin-left);
    width: calc(100% - var(--margin-left) - var(--margin-right));
    box-sizing: border-box;
}

main {
    max-width: 60rem;
    margin-left: auto;
    margin-right: auto;
}

p {
    text-align: justify;
}

abstract-block,
blockquote,
bug-block,
code-block,
decision-block,
del-block,
details,
dl,
diff-block,
example-block,
hr,
ol,
important-block,
ins-block,
math[display=block],
note-block,
p,
pre,
tip-block,
todo-block,
ul,
warning-block,
.indent {
    display: block;
    margin-top: 1em;
    margin-bottom: 1em;
}

a {
    color: var(--a-color);
    text-decoration: unset;
}

a:visited {
    color: var(--a-visited-color);
}

a:hover,
a:focus {
    color: var(--a-hover-color);
}

a:hover {
    text-decoration: underline;
}

ol,
ul {
    padding-left: var(--indent);
}

li {
    margin: 0.5em 0;
}

dt {
    margin-top: 0.25em;
    font-style: italic;
    font-weight: bold;
}

dd {
    margin-bottom: 0.25em;
    margin-left: var(--indent);
}

abstract-block,
blockquote,
bug-block,
del-block,
details,
decision-block,
diff-block,
example-block,
important-block,
ins-block,
note-block,
tip-block,
todo-block,
warning-block {
    --border-thickness: 0.25em;
    --padding: 0.5em;

    position: relative;
    width: calc(100% - var(--indent));
    box-sizing: border-box;
    padding: var(--padding);
    margin-left: var(--indent);

    border-top-right-radius: var(--border-radius);
    border-bottom-right-radius: var(--border-radius);
}

abstract-block>:first-child,
blockquote>:first-child,
bug-block>:first-child,
del-block>:first-child,
details>:first-child,
decision-block>:first-child,
diff-block>:first-child,
example-block>:first-child,
important-block>:first-child,
ins-block>:first-child,
note-block>:first-child,
tip-block>:first-child,
todo-block>:first-child,
warning-block>:first-child {
    margin-top: 0;
}

abstract-block>:last-child,
blockquote>:last-child,
bug-block>:last-child,
del-block>:last-child,
details>:last-child,
decision-block>:last-child,
diff-block>:last-child,
example-block>:last-child,
important-block>:last-child,
ins-block>:last-child,
note-block>:last-child,
todo-block>:last-child,
tip-block>:last-child,
warning-block>:last-child {
    margin-bottom: 0;
}

abstract-block::before,
blockquote::before,
bug-block::before,
del-block::before,
details::before,
decision-block::before,
diff-block::before,
example-block::before,
important-block::before,
ins-block::before,
note-block::before,
todo-block::before,
tip-block::before,
warning-block::before {
    position: absolute;
    left: -2.5em;
    top: 0.25em;
    width: 2em;
    height: 2em;

    content: "";
    display: inline-block;
    background-size: contain;
    background-repeat: no-repeat;

}

code,
code-block,
pre,
samp,
tt,
tt-,
.mono {
    font-family: var(--monospace-family);
    font-style: normal;
    font-variant-ligatures: none;
}

code-block:not(.borderless),
pre {
    padding: 0.5em;
    border-radius: var(--border-radius);
    box-sizing: border-box;

    background-color: var(--deep-background-color);
    border: 1px solid var(--border-color);
}

code-block,
pre {
    font-size: 95%;
    width: 100%;
}

code-block,
pre {
    white-space: pre;
    overflow-x: auto;
}

/* INSERTIONS AND DELETIONS */

ins,
ins-lines {
    text-decoration: underline;
    font-weight: 600;
    color: var(--ins-color);
    background-color: var(--ins-background-color);
}

code-block ins,
code-block ins-lines {
    text-decoration: inherit;
}

del {
    text-decoration: line-through;
}

del,
del-lines {
    color: var(--del-color);
    background-color: var(--del-background-color);
}

ins-lines,
del-lines {
    display: inline-block;
    width: 100%;
}

ins h-,
ins-lines h-,
del h-,
del-lines h- {
    color: inherit !important;
    background-color: inherit !important;
}

kbd {
    font-family: var(--sans-serif-family);

    display: inline-block;
    padding: 0 0.25em 0.15em 0.25em;
    border-radius: 0.25em;
    white-space: nowrap;

    background-color: var(--deep-background-color);
    border: 1px solid var(--border-color);
    box-shadow: inset 0 -0.1em 0 var(--border-color);
}

mark {
    color: var(--mark-color);
    background-color: var(--mark-background-color);
}

math:not([display=block]) {
    font-size: 120%;
}

math[display=block] {
    width: fit-content;
    margin-left: var(--indent);

    font-size: 110%;
}

g-term,
f-sans,
f-serif,
wg21-block {
    display: inline;
}

f-sans,
.sans {
    font-family: var(--sans-serif-family);
}

f-serif,
.serif {
    font-family: var(--serif-family);
}

.grammar dd,
g-term {
    font-family: var(--sans-serif-family);
    font-style: oblique;
}

.grammar {
    margin-left: var(--indent);
}

.grammar dt {
    font-weight: normal;
    font-style: normal;
}

.oblique {
    font-style: oblique;
}

.word {
    white-space: nowrap;
}

.wg21-head {
    margin-bottom: 4em;
}

.wg21-head dl {
    font-family: var(--sans-serif-family);
}

.wg21-head dt {
    font-style: normal;
}

/* HEADINGS */

h1,
h2,
h3,
h4,
h5,
h6 {
    position: relative;
    margin: 1rem 0;
}

h1 {
    margin: 2rem 0 1.5rem 0;
    font-size: 250%;
}

h2 {
    margin: 2.5rem 0 1.5rem 0;
    font-size: 166%;
}

h3 {
    margin: 2rem 0 1rem 0;
    font-size: 133%;
}

h4 {
    margin: 1.5rem 0 0.5rem 0;
    font-size: 100%;
}

h5 {
    margin: 1rem 0 0.5rem 0;
    font-size: 100%;
    font-weight: normal;
}

h6 {
    margin: 1rem 0 0.5rem 0;
    font-size: 90%;
    font-weight: normal;
}

table {
    --border: 1px solid var(--table-border-color);

    margin-top: 1em;
    margin-bottom: 1em;
    border-collapse: collapse;
}

table,
tbody,
thead,
th {
    border: var(--border);
}

td {
    border-left: var(--border);
    border-right: var(--border);
}

td,
th {
    padding: 0.1em 0.5em;
}

.para {
    cursor: pointer;
    font-weight: normal;
    font-family: var(--monospace-family);
    text-decoration: none;
    opacity: 0.25;

    position: absolute;
    top: 0.05em;
    left: calc(-1rem - 0.5ch);
}

.para,
.para::before {
    color: var(--para-color);
}

.para:hover,
.para:focus,
:target .para {
    opacity: 1;
}

.para::before {
    content: "§";
}

/* TABLE OF CONTENTS */

.toc {
    --h-indent: 0.75em;

    display: grid;
    grid-template-columns: min-content auto;
}

.toc-num {
    display: inline-block;
    align-self: end;
    padding-right: 3em;

    letter-spacing: 0em;
}

.toc h1,
.toc h2,
.toc h3,
.toc h4,
.toc h5,
.toc h6 {
    display: inline-block;

    font-weight: 500;
    font-size: 12pt;

    margin-top: 0;
    margin-bottom: 0;
}

.toc a,
.toc-num {
    border-bottom: 1px solid rgba(0, 0, 0, 0);
    color: var(--text-color);
}

.toc h1,
.toc-num[data-level="1"] {
    font-size: 125%;
    font-weight: 900;
}

.toc h2,
.toc-num[data-level="2"] {
    font-weight: 700;
}

.toc h3,
.toc-num[data-level="3"] {
    font-weight: 500;
}

.toc h4,
.toc-num[data-level="4"] {
    font-size: 95%;
    font-weight: 400;
}

.toc h5,
.toc-num[data-level="5"] {
    font-size: 90%;
    font-weight: 300;
}

.toc h6,
.toc-num[data-level="6"] {
    font-size: 90%;
    font-weight: 100;
}

.toc a:hover {
    display: inline-block;
    width: 100%;

    color: var(--a-hover-color);
    border-bottom: 1px dashed var(--a-hover-color);
}

.toc h1:not(:nth-child(2)>h1) {
    margin-top: 1.5em;
}

.toc h2:not(:nth-child(2)>h2) {
    margin-top: 0.75em;
}

/** BIBLIOGRAPHY */

.bib {
    display: block;
    margin: 1em 0;
}

.bib-item {
    display: inline-block;
    width: 100%;
    margin: 0.25em 0;
}

.bib-item>* {
    padding: 0 0.125em;
}

.bib-author {
    font-style: italic;
}

.bib-title {
    font-weight: 500;
}

.bib-date {
    font-family: var(--monospace-family);
}

.bib-date::before {
    font-family: var(--serif-family);
    content: "(";
}

.bib-date::after {
    font-family: var(--serif-family);
    content: ")";
}

.bib-link {
    display: block;
    margin-left: var(--indent);

    font-family: var(--sans-serif-family);
    font-style: normal;
}

/* SPECIAL BLOCKS */

intro- {
    display: inline-block;

    font-weight: 600;
    text-transform: uppercase;
    font-family: var(--sans-serif-family);
}

abstract-block {
    background-color: var(--abstract-background-color);
    border-left: var(--border-thickness) solid var(--abstract-border-color);
}

abstract-block::before {
    background-image: var(--abstract-image);
}

abstract-block intro-::before {
    content: "Abstract:";
    color: var(--abstract-border-color);
}

blockquote {
    background-color: var(--blockquote-background-color);
    border-left: var(--border-thickness) solid var(--blockquote-border-color);
}

blockquote::before {
    background-image: var(--blockquote-image);
    top: -0.25em;
}

blockquote intro-::before {
    content: "Quote:";
    color: var(--blockquote-border-color);
}

bug-block {
    background-color: var(--bug-block-background-color);
    border-left: var(--border-thickness) solid var(--bug-block-border-color);
}

bug-block::before {
    background-image: var(--bug-block-image);
}

bug-block intro-::before {
    content: "Bug:";
    color: var(--bug-block-border-color);
}

del-block {
    background-color: var(--del-block-background-color);
    border-left: var(--border-thickness) solid var(--del-block-border-color);
    color: var(--del-color);
}

del-block::before {
    background-image: var(--del-block-image);
}

del-block intro-::before {
    content: "Deleted:";
    color: var(--del-block-border-color);
}

del-block code,
del-block code-block {
    color: var(--text-color);
}

details {
    background-color: var(--details-background-color);
    border-left: var(--border-thickness) solid var(--details-border-color);
}

details::before {
    background-image: var(--details-image);
}

summary {
    font-family: var(--sans-serif-family);
    color: var(--details-border-color);
    user-select: none;
    cursor: pointer;
}

details[open]>summary {
    margin-bottom: 0.5em;
}

decision-block {
    background-color: var(--decision-block-background-color);
    border-left: var(--border-thickness) solid var(--decision-block-border-color);
}

decision-block::before {
    background-image: var(--decision-block-image);
}

decision-block intro-::before {
    content: "Decision:";
    color: var(--decision-block-border-color);
}

diff-block {
    background-color: var(--diff-block-background-color);
    border-left: var(--border-thickness) solid var(--diff-block-border-color);
}

diff-block::before {
    background-image: var(--diff-block-image);
}

diff-block intro-::before {
    content: "Difference:";
    color: var(--diff-block-border-color);
}

example-block {
    background-color: var(--example-block-background-color);
    border-left: var(--border-thickness) solid var(--example-block-border-color);
}

example-block::before {
    background-image: var(--example-block-image);
}

example-block intro-::before {
    content: "Example:";
    color: var(--example-block-border-color);
}

important-block {
    background-color: var(--important-block-background-color);
    border-left: var(--border-thickness) solid var(--important-block-border-color);
}

important-block::before {
    background-image: var(--important-block-image);
}

important-block intro-::before {
    content: "Important:";
    color: var(--important-block-border-color);
}

ins-block {
    background-color: var(--ins-block-background-color);
    border-left: var(--border-thickness) solid var(--ins-block-border-color);
    color: var(--ins-color);
}

ins-block code,
ins-block code-block {
    color: var(--text-color);
}

ins-block::before {
    background-image: var(--ins-block-image);
}

ins-block intro-::before {
    content: "Inserted:";
    color: var(--ins-block-border-color);
}

note-block {
    background-color: var(--note-block-background-color);
    border-left: var(--border-thickness) solid var(--note-block-border-color);
}

note-block::before {
    background-image: var(--note-block-image);
}

note-block intro-::before {
    content: "Note:";
    color: var(--note-block-border-color);
}

tip-block {
    background-color: var(--tip-block-background-color);
    border-left: var(--border-thickness) solid var(--tip-block-border-color);
}

tip-block::before {
    background-image: var(--tip-block-image);
}

tip-block intro-::before {
    content: "Tip:";
    color: var(--tip-block-border-color);
}

todo-block {
    background-color: var(--todo-block-background-color);
    border-left: var(--border-thickness) solid var(--todo-block-border-color);
}

todo-block::before {
    background-image: var(--todo-block-image);
}

todo-block intro-::before {
    content: "Todo:";
    color: var(--todo-block-border-color);
}

warning-block {
    background-color: var(--warning-block-background-color);
    border-left: var(--border-thickness) solid var(--warning-block-border-color);
}

warning-block::before {
    background-image: var(--warning-block-image);
}

warning-block intro-::before {
    content: "Warning:";
    color: var(--warning-block-border-color);
}

.indent {
    margin-left: var(--indent);
}

/* SETTINGS MENU */

#settings:not(.js) {
    display: none;
}

#settings {
    z-index: 999;
    position: fixed;
    display: inline-block;
    top: 1em;
    right: 1em;
}

#theme-icon {
    display: block;
    width: 2.5em;
    height: 2.5em;
    cursor: pointer;
    background-image: var(--theme-icon);
    background-size: contain;
    opacity: 0.25;
}

#theme-icon:hover,
#theme-icon:focus {
    opacity: 1;
}
  </style>
  <style>
@media (prefers-color-scheme: light) {
h-[data-h^=err] { color:#ff0000; }
h-[data-h^=cmt] { color:green; font-style:italic; }
h-[data-h^=cmt_dlim] { font-style:normal; }
h-[data-h^=val] { color:#9f6807; }
h-[data-h^=num] { color:#9f6807; }
h-[data-h^=str] { color:#9f6807; }
h-[data-h^=esc] { color:#9f6807; }
h-[data-h^=null] { color:#00607c; }
h-[data-h^=bool] { color:#9f6807; }
h-[data-h^=this] { color:#00607c; }
h-[data-h^=mac] { color:#6f4e37; }
h-[data-h^=id] { color:#000000; }
h-[data-h^=id_labl] { color:#517a0b; }
h-[data-h^=kw] { color:#00607c; }
h-[data-h^=sym] { color:#570057; }
h-[data-h^=sym_punc] { color:#000000; }
h-[data-h^=sym_par] { color:#af1915; }
h-[data-h^=sym_sqr] { color:#af1915; }
h-[data-h^=sym_brac] { color:#af1915; }
h-[data-h^=diff_head] { color:#777777; }
h-[data-h^=diff_head_hunk] { color:#5c477e; }
h-[data-h^=diff_eq] { color:#000000; }
h-[data-h^=diff_del] { color:#b31d28; background-color:#ffeef0; }
h-[data-h^=diff_ins] { color:#22863a; background-color:#f0fff4; }
h-[data-h^=diff_mod] { color:#7a680d; background-color:#fffdee; }
h-[data-h^=mk_tag] { color:#00607c; }
h-[data-h^=mk_attr] { color:#5c477e; }
h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
h-[data-h^=mk_emph] { font-style:italic; }
h-[data-h^=mk_stro] { font-weight:bold; }
h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
h-[data-h^=mk_ulin] { text-decoration:underline; }
h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
h-[data-h^=mk_strk] { text-decoration:line-through; }
h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
h-[data-h^=sh_cmd] { color:#00607c; }
h-[data-h^=sh-opt] { color:#000000; }
h-[data-h^=asm_ins] { color:#00607c; }
h-[data-h^=asm_ins_psu] { color:#9f6807; }
}
@media (prefers-color-scheme: dark) {
h-[data-h^=err] { color:#ff0000; }
h-[data-h^=cmt] { color:#a2e08d; font-style:italic; }
h-[data-h^=cmt_dlim] { font-style:normal; }
h-[data-h^=val] { color:#f2d18d; }
h-[data-h^=num] { color:#f2d18d; }
h-[data-h^=num_dlim] { color:#e6b191; }
h-[data-h^=num_deco] { color:#e6b191; }
h-[data-h^=str] { color:#f2d18d; }
h-[data-h^=str_dlim] { color:#e6b191; }
h-[data-h^=str_deco] { color:#e6b191; }
h-[data-h^=esc] { color:#e6aee6; }
h-[data-h^=null] { color:#62ded6; }
h-[data-h^=bool] { color:#f2d18d; }
h-[data-h^=this] { color:#62ded6; }
h-[data-h^=mac] { color:#cc946e; }
h-[data-h^=id] { color:#f0f0f0; }
h-[data-h^=id_labl] { color:#d8eda6; }
h-[data-h^=kw] { color:#62ded6; }
h-[data-h^=sym] { color:#baa6b9; }
h-[data-h^=sym_punc] { color:#d0d0d0; }
h-[data-h^=sym_par] { color:#fa7878; }
h-[data-h^=sym_sqr] { color:#fa7878; }
h-[data-h^=sym_brac] { color:#fa7878; }
h-[data-h^=diff_head] { color:#777777; }
h-[data-h^=diff_head_hunk] { color:#edc385; }
h-[data-h^=diff_eq] { color:#e7e7e7; }
h-[data-h^=diff_del] { color:#ffdcd7; background-color:#67060c; }
h-[data-h^=diff_ins] { color:#aff5b4; background-color:#033a16; }
h-[data-h^=diff_mod] { color:#fff4d7; background-color:#674d06; }
h-[data-h^=mk_tag] { color:#62ded6; }
h-[data-h^=mk_attr] { color:#a4c4de; }
h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
h-[data-h^=mk_emph] { font-style:italic; }
h-[data-h^=mk_stro] { font-weight:bold; }
h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
h-[data-h^=mk_ulin] { text-decoration:underline; }
h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
h-[data-h^=mk_strk] { text-decoration:line-through; }
h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
h-[data-h^=sh_cmd] { color:#62ded6; }
h-[data-h^=sh-opt] { color:#f0f0f0; }
h-[data-h^=asm_ins] { color:#62ded6; }
h-[data-h^=asm_ins_psu] { color:#e6aee6; }
}

html.light h-[data-h^=err] { color:#ff0000; }
html.light h-[data-h^=cmt] { color:green; font-style:italic; }
html.light h-[data-h^=cmt_dlim] { font-style:normal; }
html.light h-[data-h^=val] { color:#9f6807; }
html.light h-[data-h^=num] { color:#9f6807; }
html.light h-[data-h^=str] { color:#9f6807; }
html.light h-[data-h^=esc] { color:#9f6807; }
html.light h-[data-h^=null] { color:#00607c; }
html.light h-[data-h^=bool] { color:#9f6807; }
html.light h-[data-h^=this] { color:#00607c; }
html.light h-[data-h^=mac] { color:#6f4e37; }
html.light h-[data-h^=id] { color:#000000; }
html.light h-[data-h^=id_labl] { color:#517a0b; }
html.light h-[data-h^=kw] { color:#00607c; }
html.light h-[data-h^=sym] { color:#570057; }
html.light h-[data-h^=sym_punc] { color:#000000; }
html.light h-[data-h^=sym_par] { color:#af1915; }
html.light h-[data-h^=sym_sqr] { color:#af1915; }
html.light h-[data-h^=sym_brac] { color:#af1915; }
html.light h-[data-h^=diff_head] { color:#777777; }
html.light h-[data-h^=diff_head_hunk] { color:#5c477e; }
html.light h-[data-h^=diff_eq] { color:#000000; }
html.light h-[data-h^=diff_del] { color:#b31d28; background-color:#ffeef0; }
html.light h-[data-h^=diff_ins] { color:#22863a; background-color:#f0fff4; }
html.light h-[data-h^=diff_mod] { color:#7a680d; background-color:#fffdee; }
html.light h-[data-h^=mk_tag] { color:#00607c; }
html.light h-[data-h^=mk_attr] { color:#5c477e; }
html.light h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
html.light h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
html.light h-[data-h^=mk_emph] { font-style:italic; }
html.light h-[data-h^=mk_stro] { font-weight:bold; }
html.light h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
html.light h-[data-h^=mk_ulin] { text-decoration:underline; }
html.light h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
html.light h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
html.light h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
html.light h-[data-h^=mk_strk] { text-decoration:line-through; }
html.light h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
html.light h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
html.light h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
html.light h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
html.light h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
html.light h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
html.light h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
html.light h-[data-h^=sh_cmd] { color:#00607c; }
html.light h-[data-h^=sh-opt] { color:#000000; }
html.light h-[data-h^=asm_ins] { color:#00607c; }
html.light h-[data-h^=asm_ins_psu] { color:#9f6807; }

html.dark h-[data-h^=err] { color:#ff0000; }
html.dark h-[data-h^=cmt] { color:#a2e08d; font-style:italic; }
html.dark h-[data-h^=cmt_dlim] { font-style:normal; }
html.dark h-[data-h^=val] { color:#f2d18d; }
html.dark h-[data-h^=num] { color:#f2d18d; }
html.dark h-[data-h^=num_dlim] { color:#e6b191; }
html.dark h-[data-h^=num_deco] { color:#e6b191; }
html.dark h-[data-h^=str] { color:#f2d18d; }
html.dark h-[data-h^=str_dlim] { color:#e6b191; }
html.dark h-[data-h^=str_deco] { color:#e6b191; }
html.dark h-[data-h^=esc] { color:#e6aee6; }
html.dark h-[data-h^=null] { color:#62ded6; }
html.dark h-[data-h^=bool] { color:#f2d18d; }
html.dark h-[data-h^=this] { color:#62ded6; }
html.dark h-[data-h^=mac] { color:#cc946e; }
html.dark h-[data-h^=id] { color:#f0f0f0; }
html.dark h-[data-h^=id_labl] { color:#d8eda6; }
html.dark h-[data-h^=kw] { color:#62ded6; }
html.dark h-[data-h^=sym] { color:#baa6b9; }
html.dark h-[data-h^=sym_punc] { color:#d0d0d0; }
html.dark h-[data-h^=sym_par] { color:#fa7878; }
html.dark h-[data-h^=sym_sqr] { color:#fa7878; }
html.dark h-[data-h^=sym_brac] { color:#fa7878; }
html.dark h-[data-h^=diff_head] { color:#777777; }
html.dark h-[data-h^=diff_head_hunk] { color:#edc385; }
html.dark h-[data-h^=diff_eq] { color:#e7e7e7; }
html.dark h-[data-h^=diff_del] { color:#ffdcd7; background-color:#67060c; }
html.dark h-[data-h^=diff_ins] { color:#aff5b4; background-color:#033a16; }
html.dark h-[data-h^=diff_mod] { color:#fff4d7; background-color:#674d06; }
html.dark h-[data-h^=mk_tag] { color:#62ded6; }
html.dark h-[data-h^=mk_attr] { color:#a4c4de; }
html.dark h-[data-h^=mk_del] { color:#ce9178; text-decoration:line-through; }
html.dark h-[data-h^=mk_ins] { color:#b5cea8; text-decoration:underline; }
html.dark h-[data-h^=mk_emph] { font-style:italic; }
html.dark h-[data-h^=mk_stro] { font-weight:bold; }
html.dark h-[data-h^=mk_emph_stro] { font-style:italic; font-weight:bold; }
html.dark h-[data-h^=mk_ulin] { text-decoration:underline; }
html.dark h-[data-h^=mk_emph_ulin] { font-style:italic; text-decoration:underline; }
html.dark h-[data-h^=mk_stro_ulin] { font-weight:bold; text-decoration:underline; }
html.dark h-[data-h^=mk_emph_stro_ulin] { font-weight:bold; font-style:italic; text-decoration:underline; }
html.dark h-[data-h^=mk_strk] { text-decoration:line-through; }
html.dark h-[data-h^=mk_emph_strk] { font-style:italic; text-decoration:line-through; }
html.dark h-[data-h^=mk_stro_strk] { font-weight:bold; text-decoration:line-through; }
html.dark h-[data-h^=mk_emph_stro_strk] { font-weight:bold; font-style:italic; text-decoration:line-through; }
html.dark h-[data-h^=mk_ulin_strk] { text-decoration:underline line-through; }
html.dark h-[data-h^=mk_emph_ulin_strk] { font-style:italic; text-decoration:underline line-through; }
html.dark h-[data-h^=mk_stro_ulin_strk] { font-weight:bold; text-decoration:underline line-through; }
html.dark h-[data-h^=mk_emph_stro_ulin_strk] { font-weight:bold; font-style:italic; text-decoration:underline line-through; }
html.dark h-[data-h^=sh_cmd] { color:#62ded6; }
html.dark h-[data-h^=sh-opt] { color:#f0f0f0; }
html.dark h-[data-h^=asm_ins] { color:#62ded6; }
html.dark h-[data-h^=asm_ins_psu] { color:#e6aee6; }
  </style>
  <script>
const theme = localStorage.getItem("cowel-theme");
if (theme !== null) {
    document.documentElement.className = theme;
}
  </script>
<title>Integer division</title></head>
<body>
<div id=settings tabindex=0>
    <div id=theme-icon></div>
    <script>
        const settings = document.getElementById("settings");
        const htmlClasses = document.documentElement.classList;
        const themeIcon = document.getElementById("theme-icon");

        settings.classList.add("js");
        themeIcon.onclick = () => {
            const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
            const overrideClass = prefersDark.matches ? "light" : "dark";
            if (htmlClasses.contains("light")) {
                htmlClasses.remove("light");
                localStorage.removeItem("cowel-theme");
            } else if (htmlClasses.contains("dark")) {
                htmlClasses.remove("dark");
                localStorage.removeItem("cowel-theme");
            } else {
                htmlClasses.add(overrideClass);
                // to avoid legal issues or controversy in general,
                // we don't mess with local storage when the page is hosted in arbitrary places
                if (window.location.protocol === "file:") {
                    localStorage.setItem("cowel-theme", overrideClass);
                }
            }
        };
        settings.onkeydown = (e) => {
            if (e.key === "Enter" || e.key === " ") {
                event.preventDefault();
                themeIcon.onclick();
            }
        };
    </script>
</div>
<main>







































<style>
ins-block .para::before {
    display: none;
}

.stable-ref {
    float: right;
}
</style>





<p><div class=wg21-head><h1>Integer division</h1>

<dl>
    <dt>Document number:</dt> <dd><a href=https://wg21%2elink/P3724R0>P3724R0</a></dd>
    <dt>Date:</dt>            <dd><tt->2025-06-04</tt-></dd>
    <dt>Audience:</dt>        <dd>LEWG, SG6</dd>
    <dt>Project:</dt>         <dd>ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21</dd>
    <dt>Reply-To:</dt>        <dd>Jan Schultke &lt;<a href=mailto:janschultke@gmail%2ecom class=sans>janschultke@gmail.com</a>&gt;</dd>
    <dt>GitHub Issue:</dt>    <dd><a href=https://wg21%2elink/P3724/github class=sans>wg21.link/P3724/github</a></dd>
    <dt>Source:</dt>          <dd><a href=https://github%2ecom/Eisenwave/cpp-proposals/blob/master/src/intdiv%2ecow class=sans>github.com/Eisenwave/cpp-proposals/blob/master/src/intdiv.cow</a></dd>
</dl>
<hr/>
</div></p>

<abstract-block><p><intro-></intro-> 
C++ currently only offers truncating integer division in the form of the <code><h- data-h=sym_op>/</h-></code> operator.
I propose standard library functions for computing quotients and remainders
with other rounding modes.
</p></abstract-block>

<h2 id=contents><a class=para href=#contents></a>Contents</h2>

<div class=toc><div class=toc-num data-level=2>1</div>
<a href=#introduction><h2>Introduction</h2></a>
<div class=toc-num data-level=3>1.1</div>
<a href=#existing-practice><h3>Existing practice</h3></a>
<div class=toc-num data-level=4>1.1.1</div>
<a href=#language-support><h4>Language support for integer division</h4></a>
<div class=toc-num data-level=4>1.1.2</div>
<a href=#hardware-support-for-integer-division><h4>Hardware support for integer division</h4></a>
<div class=toc-num data-level=2>2</div>
<a href=#motivation><h2>Motivation</h2></a>
<div class=toc-num data-level=3>2.1</div>
<a href=#trivial-for-user><h3>Is this not trivial for the user to do?</h3></a>
<div class=toc-num data-level=3>2.2</div>
<a href=#computing-remainders-is-hard><h3>Computing remainders is hard, actually</h3></a>
<div class=toc-num data-level=2>3</div>
<a href=#design><h2>Design</h2></a>
<div class=toc-num data-level=3>3.1</div>
<a href=#relation-to-p0105r1><h3>Relation to P0105R1</h3></a>
<div class=toc-num data-level=3>3.2</div>
<a href=#naming><h3>Naming</h3></a>
<div class=toc-num data-level=4>3.2.1</div>
<a href="#isn%27t--inconsistent-with-the-existing-?"><h4>Isn't <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_</h-><h- data-h=sym_op>*</h-></code> inconsistent with the existing <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div</h-></code>?</h4></a>
<div class=toc-num data-level=4>3.2.2</div>
<a href=#should-it-be--and-?><h4>Should it be <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_floor</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ceil</h-></code>?</h4></a>
<div class=toc-num data-level=4>3.2.3</div>
<a href=#should-it-be-?><h4>Should it be <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_pos_inf</h-></code>?</h4></a>
<div class=toc-num data-level=4>3.2.4</div>
<a href=#naming-mod><h4>Why is it <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code>?</h4></a>
<div class=toc-num data-level=3>3.3</div>
<a href=#interface><h3>Interface</h3></a>
<div class=toc-num data-level=4>3.3.1</div>
<a href=#error-handling-noexcept><h4>Error handling and <code><h- data-h=kw>noexcept</h-></code></h4></a>
<div class=toc-num data-level=4>3.3.2</div>
<a href=#why-no--parameter?><h4>Why no <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>rounding</h-></code> parameter?</h4></a>
<div class=toc-num data-level=4>3.3.3</div>
<a href=#div-result><h4><code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-></code></h4></a>
<div class=toc-num data-level=4>3.3.4</div>
<a href=#div-rem-combined><h4>Do we really need the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_rem_</h-><h- data-h=sym_op>*</h-></code> functions?</h4></a>
<div class=toc-num data-level=3>3.4</div>
<a href=#supported-rounding-modes><h3>Supported rounding modes</h3></a>
<div class=toc-num data-level=4>3.4.1</div>
<a href=#rounding-to-zero><h4>Rounding to zero</h4></a>
<div class=toc-num data-level=4>3.4.2</div>
<a href=#rounding-to-even/odd><h4>Rounding to even/odd</h4></a>
<div class=toc-num data-level=4>3.4.3</div>
<a href=#to-nearest-rounding-division-and-tie-breaking><h4>To-nearest-rounding division and tie breaking</h4></a>
<div class=toc-num data-level=3>3.5</div>
<a href=#mod><h3><code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code></h3></a>
<div class=toc-num data-level=2>4</div>
<a href=#implementation-experience><h2>Implementation experience</h2></a>
<div class=toc-num data-level=2>5</div>
<a href=#try-it-yourself><h2>Try it yourself</h2></a>
<div class=toc-num data-level=2>6</div>
<a href=#wording><h2>Wording</h2></a>
<div class=toc-num data-level=3>6.1</div>
<a href=#[structure%2especifications]><h3>[structure.specifications]</h3></a>
<div class=toc-num data-level=3>6.2</div>
<a href=#[version%2esyn]><h3>[version.syn]</h3></a>
<div class=toc-num data-level=3>6.3</div>
<a href=#[bit%2epow%2etwo]><h3>[bit.pow.two]</h3></a>
<div class=toc-num data-level=3>6.4</div>
<a href=#[numeric%2eops%2eoverview]><h3>[numeric.ops.overview]</h3></a>
<div class=toc-num data-level=3>6.5</div>
<a href=#[numeric%2esat%2efunc]><h3>[numeric.sat.func]</h3></a>
<div class=toc-num data-level=3>6.6</div>
<a href=#new-subclause><h3>[numeric.int.div]</h3></a>
<div class=toc-num data-level=3>6.7</div>
<a href=#[simd%2ebit]><h3>[simd.bit]</h3></a>
<div class=toc-num data-level=2>7</div>
<a href=#acknowledgements><h2>Acknowledgements</h2></a>
<div class=toc-num data-level=2>8</div>
<a href=#references><h2>References</h2></a>
<div class=toc-num data-level=2>9</div>
<a href=#implementation><h2>Appendix A — Reference implementation</h2></a>
</div>

<h2 id=introduction><a class=para href=#introduction></a>1. Introduction</h2>

<p>C++ currently only offers truncating integer division in the form of the <code><h- data-h=sym_op>/</h-></code> operator.
However, other rounding modes have various use cases too,
and implementing these as the user can be surprisingly hard,
especially when integer overflow needs to be avoided,
and negative inputs are accepted.
</p>
<p>Furthermore, since the <code><h- data-h=sym_op>/</h-></code> operator rounds towards zero,
the <code><h- data-h=sym_op>%</h-></code> (remainder) operator may yield negative results
(specifically, when the dividend is negative).
In modular arithmetic and various other use cases,
this is undesirable,
and a negative remainder may be surprising in general.
</p>
<p>Therefore, I propose a set of standard library functions
which implement a variety of rounding modes when computing quotients and remainders.
Such a feature was previously part of <a href="https://wg21%2elink/p0105r1">[P0105R1]</a> and the Numerics TS <a href="https://wg21%2elink/p1889r1">[P1889R1]</a>,
but was eventually abandoned by the author.
</p>
<note-block><p><intro-></intro-> 
Terminology refresher for division, where
<math display=inline><mi style=font-style:italic>round</mi></math>
is some rounding function:
</p><math display=block><mrow>
    <mi>quotient</mi>
    <mo>=</mo>
    <mi style=font-style:italic>round</mi>
    <mo>(</mo>
    <mfrac><mi>dividend</mi><mi>divisor</mi></mfrac>
    <mo>)</mo>
    <mo>+</mo>
    <mi>remainder</mi>
</mrow></math>
<p>Your browser requires MathML support to view the equation above.
</p></note-block>

<h3 id=existing-practice><a class=para href=#existing-practice></a>1.1. Existing practice</h3>

<p>To better put this proposal into context,
it is relevant to know what rounding modes are usually supported by programming languages
and hardware.
</p>
<style>
.center {
    margin-left: auto;
    margin-right: auto;
}

td ul, td ul>li {
    margin: 0;
}

#lang-comparison td:nth-child(2),
#lang-comparison td:nth-child(3) {
    text-align: center;
}

#hw-comparison td:nth-child(2),
#hw-comparison td:nth-child(3),
#hw-comparison td:nth-child(4) {
    text-align: center;
}

#lang-comparison, #hw-comparison {
    min-width: 75%;
}

.striped tr:nth-child(even) td {
    background-color: var(--deep-background-color);
}
</style>




<h4 id=language-support><a class=para href=#language-support></a>1.1.1. Language support for integer division</h4>

<table id=lang-comparison class="center striped">
<tr>
    <th>Language</th> <th>Quotient</th> <th>Remainder</th> <th>Rounding</th>
</tr>
<tr>
    <td>C and C++</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>D</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Objective-C</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>C#</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Java</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Rust</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Go</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Swift</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Scala</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>OCaml</td>
    <td><tt->/</tt-></td>
    <td><tt->mod</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Perl</td>
    <td><tt->int($a/$b)</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>GLSL</td>
    <td><tt->/</tt-></td>
    <td>N/A</td>
    <td>to zero</td>
</tr>
<tr>
    <td>JavaScript</td>
    <td><tt->/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to zero (for <tt->BigInt</tt-> operands)</td>
</tr>
<tr>
    <td>Python</td>
    <td><tt->//</tt-></td>
    <td><tt->%</tt-></td>
    <td>to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></td>
</tr>
<tr>
    <td>Lua</td>
    <td><tt->//</tt-></td>
    <td><tt->%</tt-></td>
    <td>to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></td>
</tr>
<tr>
    <td>R</td>
    <td><tt->%/%</tt-></td>
    <td><tt->%%</tt-></td>
    <td>to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></td>
</tr>
<tr>
    <td>Dart</td>
    <td><tt->~/</tt-></td>
    <td><tt->%</tt-></td>
    <td>to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></td>
</tr>
<tr>
    <td>Haskell</td>
    <td><tt->quot</tt->, <tt->div</tt-></td>
    <td><tt->rem</tt->, <tt->mod</tt-></td>
    <td><ul>
        <li><tt->quot</tt-> and <tt->rem</tt-> to zero</li>
        <li><tt->div</tt-> and <tt->mod</tt-> to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></li>
    </ul></td>
</tr>
<tr>
    <td>Ada</td>
    <td><tt->/</tt-></td>
    <td><tt->rem</tt->, <tt->mod</tt-></td>
    <td><ul>
        <li><tt->/</tt-> and <tt->rem</tt-> to zero</li>
        <li><tt->mod</tt-> to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></li>
    </ul></td>
</tr>
<tr>
    <td>Fortran</td>
    <td><tt->/</tt-></td>
    <td><tt->mod</tt->, <tt->modulo</tt-></td>
    <td><ul>
        <li><tt->/</tt-> and <tt->mod</tt-> to zero</li>
        <li><tt->modulo</tt-> to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></li>
    </ul></td>
</tr>
<tr>
    <td>CSS</td>
    <td>N/A</td>
    <td><tt->rem()</tt->, <tt->mod()</tt-></td>
    <td><ul>
        <li><tt->rem()</tt-> to zero</li>
        <li><tt->mod()</tt-> to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></li>
    </ul></td>
</tr>
<tr>
    <td>Kotlin</td>
    <td><tt->/</tt->, <tt->rem()</tt-></td>
    <td><tt->%</tt->, <tt->mod()</tt-></td>
    <td><ul>
        <li><tt->/</tt-> and <tt->rem()</tt-> to zero</li>
        <li><tt->mod()</tt-> to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math></li>
    </ul></td>
</tr>
<tr>
    <td>Julia</td>
    <td><tt->div(x,y,r)</tt-></td>
    <td><tt->rem(x,y,r)</tt-></td>
    <td>
        depending on <tt->RoundingMode</tt-> <tt->r</tt->:<ul>
            <li>to zero (default),</li>
            <li>away from zero,</li>
            <li>to <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math> or <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>, or</li>
            <li>to nearest (ties to even)</li>
        </ul>
    </td>
</tr>
</table>

<note-block><p><intro-></intro-> 
When a division rounds towards zero,
the remainder has the dividend (left operand) sign.
When a division rounds towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>,
the remainder has the divisor (right operand) sign.
</p></note-block>

<h4 id=hardware-support-for-integer-division><a class=para href=#hardware-support-for-integer-division></a>1.1.2. Hardware support for integer division</h4>

<table id=hw-comparison class="center striped">
<tr>
    <th>Architecture</th> <th>Type</th> <th>Quotient</th> <th>Remainder</th> <th>Rounding</th>
</tr>
<tr>
    <td>x86 and x86_64</td>
    <td>CPU</td>
    <td><tt->idiv</tt->, <tt->div</tt-></td>
    <td><tt->idiv</tt->, <tt->div</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>ARMv7-A and newer</td>
    <td>CPU</td>
    <td><tt->sdiv</tt->, <tt->udiv</tt-></td>
    <td>N/A</td>
    <td>to zero</td>
</tr>
<tr>
    <td>RISC-V</td>
    <td>CPU</td>
    <td><tt->div</tt->, <tt->divu</tt-></td>
    <td><tt->rem</tt->, <tt->remu</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>PowerPC</td>
    <td>CPU</td>
    <td><tt->divw</tt->, <tt->divwu</tt-></td>
    <td>N/A</td>
    <td>to zero</td>
</tr>
<tr>
    <td>MIPS</td>
    <td>CPU</td>
    <td><tt->div</tt->, <tt->divu</tt-></td>
    <td><tt->div</tt->, <tt->divu</tt->,<br/><tt->rem</tt->, <tt->remu</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>AVR (8-bit), PIC16, etc.</td>
    <td>CPU</td>
    <td>N/A</td>
    <td>N/A</td>
    <td>N/A</td>
</tr>
<tr>
    <td>WebAssembly</td>
    <td>VM</td>
    <td><tt->div_s</tt->, <tt->div_u</tt-></td>
    <td><tt->rem_s</tt->, <tt->rem_u</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>LLVM IR</td>
    <td>VM</td>
    <td><tt->sdiv</tt->, <tt->udiv</tt-></td>
    <td><tt->srem</tt->, <tt->urem</tt-></td>
    <td>to zero</td>
</tr>
<tr>
    <td>Java Bytecode</td>
    <td>VM</td>
    <td><tt->idiv</tt-></td>
    <td><tt->irem</tt-></td>
    <td>to zero</td>
</tr>
</table>

<note-block><p><intro-></intro-> 
For unsigned division like <tt->div</tt-> on x86,
there is no distinction between rounding to zero and rounding to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>,
which is why everything is listed as "to zero" for simplicity.
</p></note-block>

<p>While every architecture rounds to zero,
there there are major differences in how the remainder is obtained:
</p><ul>
    <li>On x86_64 and MIPS, the quotient and remainder are computed simultaneously,
    although MIPS also supports separate computation of the remainder.</li>
    <li>On other architectures, even if there is support for computing the remainder separately,
    if both the quotient and remainder are needed,
    it is faster to compute the remainder using the quotient of the division.</li>
    <li>In some cases, the remainder can <em>only</em> be computed using the quotient.</li>
</ul>

<note-block><p><intro-></intro-> 
Given two integers <math display=inline><mi>x</mi></math> and <math display=inline><mi>y</mi></math>,
the quotient <math display=inline><mrow>
    <mi>q</mi>
    <mo>=</mo>
    <mo>⌊</mo>
    <mfrac><mi>x</mi><mi>y</mi></mfrac>
    <mo>⌋</mo>
</mrow></math> (or rounded otherwise to an integer),
the remainder of the division is equal to
<math display=inline><mrow>
    <mi>x</mi>
    <mo>−</mo>
    <mi>y</mi>
    <mo>×</mo>
    <mi>q</mi>
</mrow></math>﻿.
</p>
<p><em>Only</em> if the division rounds towards zero can this also be translated literally
into a multiplication and subtraction,
without the possibility of overflow.
This makes rounding towards zero <em>by far</em> the most useful rounding mode in computing,
and it is no coincidence that every architecture implements it.
</p></note-block>

<h2 id=motivation><a class=para href=#motivation></a>2. Motivation</h2>

<p>Rounding modes other than rounding towards zero are commonly useful.
An extremely common alternative is rounding towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>,
which is the rounding mode of the division operator in some other languages
(<a href=#language-support>§1.1.1. Language support for integer division</a>).
See below for some motivating examples.
</p>
<example-block><p><intro-></intro-> 
A common problem is to compute how many chunks/buckets/blocks of a fixed size
are needed to fit a certain amount of elements,
which involves a division which rounds towards <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math>.
</p><code-block><h- data-h=kw>const</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>bucket_size</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>1000</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>elements</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>100</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>buckets_required</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>elements</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> WRONG, zero</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>buckets_required</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>elements</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, one bucket</h-></code-block>
</example-block>

<example-block><p><intro-></intro-> 
A common problem is to compute which chunk/bucket/block an element falls into.
This requires division which rounds towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>.
</p><code-block><h- data-h=kw>const</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>bucket_size</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>1000</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>10</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>b</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>-</h-><h- data-h=num>10</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>a_bucket</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, zero</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>b_bucket</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>b</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> WRONG, also zero</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>a_bucket</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, zero</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>b_bucket</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>b</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>bucket_size</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> OK, -1</h-></code-block>
<p>Note that with truncating division,
the zero-bucket would contain all elements in [-999, 999],
which would make it larger than any other bucket.
</p></example-block>

<p>While the examples are somewhat abstract,
they appear in vast amounts of concrete problems.
For example, we need to know how many blocks of memory must be allocated
to hold a certain amount of bytes,
do interval arithmetic,
fixed-point arithmetic with rounding of choice, etc. etc.
</p>
<h3 id=trivial-for-user><a class=para href=#trivial-for-user></a>2.1. Is this not trivial for the user to do?</h3>

<p>At first glance,
it would seem trivial to change rounding modes by making slight adjustments to <code><h- data-h=sym_op>/</h-></code>.
However, doing so with correct output, high performance,
and without introducing more undefined behavior than <code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> already has,
is surprisingly hard.
</p>
<p>There is an <em>ocean</em> of examples where C and C++ users have gotten this wrong.
A few droplets are listed below.
</p>
<bug-block><p><intro-></intro-> 
At the time of writing,
the <em>first</em> Google search result for "c++ ceiling integer division"
yields <a href="https://stackoverflow%2ecom/q/2745074/5740428">[StackOverflowCeil]</a>.
Almost every answer does not permit signed integers,
gives wrong results,
or has undefined behavior for certain inputs
(not counting division by zero or <code><h- data-h=mac>INT_MIN</h-> <h- data-h=sym_op>/</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-></code>).
</p>
<p>For example, one answer with 67 upvotes (at the time of writing)
attempts to implement ceiling (rounded towards <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math>)
integer division as follows:
</p><code-block><h- data-h=id>q</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=num>1</h-> <h- data-h=sym_punc>:</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h-></code-block>
<p>The quotient <code><h- data-h=id>q</h-></code> would be <code><h- data-h=num>1</h-></code>, not <code><h- data-h=num>0</h-></code>
for inputs <code><h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-></code> and <code><h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>2</h-></code>,
which is obviously wrong because it rounds <code><h- data-h=sym_op>-</h-><h- data-h=num>0</h-><h- data-h=num_dlim>.</h-><h- data-h=num>5</h-></code> up to <code><h- data-h=num>1</h-></code>, skipping zero.
</p>
<p>To be fair, the answer is correct for positive integers,
and perhaps the author didn't want to support negative inputs anyway.
However, the answer contains no disclaimer that clarifies this.
</p></bug-block>

<bug-block><p><intro-></intro-> 
In the question "Rounding integer division (instead of truncating)" for C
(<a href="https://stackoverflow%2ecom/q/2422712/5740428">[StackOverflowRound]</a>),
OP expresses that they want to divide with rounding to the nearest integer,
rather than rounding towards zero.
</p>
<p>While the top 11 answers are highly decorated with upvotes,
they all overflow for large inputs,
use <code><h- data-h=kw_type>float</h-></code> (which has accuracy issues),
have the wrong rounding mode,
or are plain incorrect.
</p>
<p>The first correct solution can only be found at 5 upvotes, by user A Fog:
</p><code-block><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>rounded_division</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>n</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>d</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>q</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>n</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>d</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> quotient</h->
    <h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>r</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>n</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>d</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> remainder</h->
    <h- data-h=kw_ctrl>if</h-> <h- data-h=sym_par>(</h-><h- data-h=id>r</h-> <h- data-h=sym_op>&gt;</h-> <h- data-h=id>d</h-><h- data-h=sym_op>&gt;&gt;</h-><h- data-h=num>1</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> fraction &gt; 0.5</h->
    <h- data-h=sym_op>||</h-> <h- data-h=sym_par>(</h-><h- data-h=id>r</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>d</h-><h- data-h=sym_op>&gt;&gt;</h-><h- data-h=num>1</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=sym_par>(</h-><h- data-h=id>q</h-><h- data-h=sym_op>&amp;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=sym_op>!</h-><h- data-h=sym_par>(</h-><h- data-h=id>d</h-><h- data-h=sym_op>&amp;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> fraction == 0.5 and odd</h->
        <h- data-h=id>q</h-><h- data-h=sym_op>++</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>q</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>Unfortunately, this solution does not support negative inputs,
and is somewhat branch-heavy.
When compiled with Clang,
a possible path of execution would go through four conditional jumps
depending on <code><h- data-h=sym_par>(</h-><h- data-h=id>r</h-> <h- data-h=sym_op>&gt;</h-> <h- data-h=id>d</h-><h- data-h=sym_op>&gt;&gt;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>, <code><h- data-h=sym_par>(</h-><h- data-h=id>r</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>d</h-><h- data-h=sym_op>&gt;&gt;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>, <code><h- data-h=sym_par>(</h-><h- data-h=id>q</h-><h- data-h=sym_op>&amp;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>, and <code><h- data-h=sym_op>!</h-><h- data-h=sym_par>(</h-><h- data-h=id>d</h-><h- data-h=sym_op>&amp;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>,
where all but <code><h- data-h=sym_par>(</h-><h- data-h=id>r</h-> <h- data-h=sym_op>==</h-> <h- data-h=id>d</h-><h- data-h=sym_op>&gt;&gt;</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code> are extremely unpredictable (basically coin flips).
See <a href=https://godbolt%2eorg/z/ax6hr1r53 class=sans>godbolt.org/z/ax6hr1r53</a>.
</p></bug-block>

<bug-block><p><intro-></intro-> 
These division functions taken from <a href="https://blog%2edemofox%2eorg/2022/07/21/rounding-modes-for-integer-division/">[BuggyDivisions]</a> have several problems:
</p><code-block><h- data-h=kw>static</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_floor</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_par>(</h-><h- data-h=id>a</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>?</h-> <h- data-h=sym_par>(</h-><h- data-h=num>1</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>a</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>-</h-> <h- data-h=num>1</h-> <h- data-h=sym_punc>:</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>b</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>static</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_round</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_par>(</h-><h- data-h=id>a</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=sym_par>(</h-><h- data-h=id>a</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>b</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>b</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_par>(</h-><h- data-h=id>a</h-> <h- data-h=sym_op>+</h-> <h- data-h=id>b</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>b</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>static</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ceil</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>a</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_par>(</h-><h- data-h=id>a</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>||</h-> <h- data-h=sym_op>!</h-><h- data-h=id>a</h-> <h- data-h=sym_op>?</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>b</h-> <h- data-h=sym_punc>:</h-> <h- data-h=sym_par>(</h-><h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>a</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>-</h-> <h- data-h=num>1</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>b</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>+</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<ul>
<li><code><h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>a</h-><h- data-h=sym_par>)</h-></code> and <code><h- data-h=id>abs</h-><h- data-h=sym_par>(</h-><h- data-h=id>b</h-><h- data-h=sym_par>)</h-></code> have undefined behavior given <code><h- data-h=mac>INT_MIN</h-></code> input</li>
<li><code><h- data-h=id>div_round</h-></code> overflows on large inputs in <code><h- data-h=id>a</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>b</h-></code> and <code><h- data-h=id>a</h-> <h- data-h=sym_op>+</h-> <h- data-h=id>b</h-></code></li>
<li>
all functions branch depending on whether the quotient is negative,
which may be highly unpredictable
</li>
</ul>
</bug-block>

<note-block><p><intro-></intro-> See <a href=#implementation>§ Appendix A — Reference implementation</a> for proper implementations.</p></note-block>

<p>Users sometimes also implement these functions using <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>floor</h-></code> or <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>ceil</h-></code>,
but this can equally yield incorrect results,
and use of floating-point numbers is unnecessary for this task.
</p>
<h3 id=computing-remainders-is-hard><a class=para href=#computing-remainders-is-hard></a>2.2. Computing remainders is hard, actually</h3>

<p>There exist various use cases (modular arithmetic, integer-to-string conversion, etc.)
where we need both the quotient and remainder at the same time.
The naive approach to computing the remainder
using an integer division function <tt-><i><h- data-h=id>divide</h-></i></tt-> looks something like:
</p>
<code-block><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <i><h- data-h=id>divide</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h-></code-block>

<p>This approach is only safe when <code><i><h- data-h=id>divide</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-></code> is <code><h- data-h=id>x</h-><h- data-h=sym_op>/</h-><h- data-h=id>y</h-></code>,
i.e. when rounding towards zero.
</p>
<bug-block><p><intro-></intro-> 
The following function, which yields the quotient rounded towards <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math>,
as well as the remainder,
is not safe for large inputs:
</p><code-block><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>div_t</h-> <h- data-h=id>div_rem_ceil</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_positive</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>==</h-> <h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>has_remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>quotient_positive</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>has_remainder</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>remainder</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>If we now call <code><h- data-h=id>div_rem_ceil</h-><h- data-h=sym_par>(</h-><h- data-h=mac>INT_MAX</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>2</h-><h- data-h=sym_par>)</h-></code>,
where <code><h- data-h=mac>INT_MAX</h-></code> is <code><h- data-h=num>2</h-><h- data-h=num_dlim>'</h-><h- data-h=num>147</h-><h- data-h=num_dlim>'</h-><h- data-h=num>483</h-><h- data-h=num_dlim>'</h-><h- data-h=num>647</h-></code>,
then <code><h- data-h=id>quotient</h-></code> is <code><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>073</h-><h- data-h=num_dlim>'</h-><h- data-h=num>741</h-><h- data-h=num_dlim>'</h-><h- data-h=num>824</h-></code>.
The multiplication <code><h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient</h-></code> has undefined behavior
because it results in <code><h- data-h=num>2</h-><h- data-h=num_dlim>'</h-><h- data-h=num>147</h-><h- data-h=num_dlim>'</h-><h- data-h=num>483</h-><h- data-h=num_dlim>'</h-><h- data-h=num>648</h-></code>, which cannot be represented as <code><h- data-h=kw_type>int</h-></code>.
</p>
<p>Crucially, it does not mean that <code><h- data-h=id>div_rem_ceil</h-></code> cannot be defined for these inputs.
The correct quotient is <code><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>073</h-><h- data-h=num_dlim>'</h-><h- data-h=num>741</h-><h- data-h=num_dlim>'</h-><h- data-h=num>824</h-></code>,
and the correct remainder is <code><h- data-h=sym_op>-</h-><h- data-h=num>1</h-></code>.
It just means that for any rounding mode except towards zero,
we cannot use the naive formula to obtain a remainder.
</p></bug-block>

<p>In conclusion,
the proposal should also include a way to obtain a remainder in tandem with the quotient.
Any other design would simply invite bugs where users foolishly assume that
the <code><h- data-h=id>x</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h-></code> method works for all rounding modes.
</p>
<h2 id=design><a class=para href=#design></a>3. Design</h2>

<p>The design aims of this proposal are to provide <em>concise</em>,
<em>simple</em>, <em>efficient</em>, <em>robust</em> functions
which are useful <em>in practice</em>.
</p>
<important-block><p><intro-></intro-> 
As a rule of thumb, the proposed functionality should be a drop-in replacement
for the various bad implementations that users have written themselves (<a href=#trivial-for-user>§2.1. Is this not trivial for the user to do?</a>),
and it should take the underlying implementation (<a href=#implementation>§ Appendix A — Reference implementation</a>) into consideration.
This rule of thumb influences <em>every</em> design choice.
</p></important-block>

<note-block><p><intro-></intro-> 
You may find a complete list of functions in
<a href=#try-it-yourself>§5. Try it yourself</a>,
<a href=#wording>§6. Wording</a>, and
<a href=#implementation>§ Appendix A — Reference implementation</a>.
</p></note-block>

<h3 id=relation-to-p0105r1><a class=para href=#relation-to-p0105r1></a>3.1. Relation to P0105R1</h3>

<p>The design somewhat leans on <a href="https://wg21%2elink/p0105r1">[P0105R1]</a>
(which first proposed division functions with custom rounding),
but heavily deviates from it.
In general, <a href="https://wg21%2elink/p0105r1">[P0105R1]</a> was a proposal with overly broad scope,
and some questionable design choices, such as:
</p>
<ul>
<li>Making some of the rounding modes conditionally supported,
even when providing them isn't particularly difficult.</li>
<li>Adding rounding modes which optimize for latency or code size,
without much motivation or details.
The proposal provided no concrete example of how this implementation freedom could be utilized,
and I suspect that any implementation would default to rounding to zero,
matching the <code><h- data-h=sym_op>/</h-></code> operator anyway.</li>
</ul>

<h3 id=naming><a class=para href=#naming></a>3.2. Naming</h3>

<p>All functions which compute a quotient begin with <code><h- data-h=id>div</h-></code>,
and functions which also compute a remainder begin with <code><h- data-h=id>div_rem</h-></code>.
Furthermore, the functions include the name of the rounding mode
in a format that requires as little prior knowledge as feasible.
</p>
<h4 id="isn&apos;t--inconsistent-with-the-existing-?"><a class=para href="#isn%27t--inconsistent-with-the-existing-?"></a>3.2.1. Isn't <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_</h-><h- data-h=sym_op>*</h-></code> inconsistent with the existing <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div</h-></code>?</h4>

<p>It is worth pointing out that there already exist <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div</h-></code>
functions in the standard library, returning <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>div_t</h-></code>,
which contains the quotient and remainder.
The proposal does not aim for consistency because the facilities are an unnecessary
and rarely-used C relic for the most part.
</p>
<p>On the contrary, when investigating existing practice in <a href=#trivial-for-user>§2.1. Is this not trivial for the user to do?</a>,
I found that almost every definition of these differently-rounded division functions
uses <code><h- data-h=id>div_</h-><h- data-h=sym_op>*</h-></code> names.
This naming scheme is <em>well-established</em> and <em>intuitive</em> for users.
</p>
<h4 id=should-it-be--and-?><a class=para href=#should-it-be--and-?></a>3.2.2. Should it be <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_floor</h-></code> and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ceil</h-></code>?</h4>

<p>While the use of names like <code><h- data-h=id>floor</h-></code> and <code><h- data-h=id>ceil</h-></code> is common in various domains,
including in <code><h- data-h=str>&lt;cmath&gt;</h-></code>,
I do not believe we should perpetuate this design because:
</p>
<ul>
<li>
The scheme does not nicely extend to division with rounding away from zero;
there is no established term for that.
</li>
<li>
A hypothetical <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_round</h-></code> (for rounding to the nearest integer)
would be somewhat perplexing because <em>all</em> proposed functions round,
just towards different targets.
</li>
<li>
The scheme is needlessly hostile towards novices
who are not yet familiar with the fact that <math display=inline><mrow><mi>floor</mi><mo>(</mo><mi>x</mi><mo>)</mo></mrow></math>
rounds towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>.
By comparison, <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-></code> is self-documenting.
</li>
</ul>

<p>Regardless whether the functions end up called <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_floor</h-></code>
or <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-></code>, the names should remain somewhat brief so they take up
a reasonable amount of space in C++ expressions.
</p>
<h4 id=should-it-be-?><a class=para href=#should-it-be-?></a>3.2.3. Should it be <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_pos_inf</h-></code>?</h4>

<p>While it looks nicer on paper if <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_pos_inf</h-></code>
and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-></code> have symmetrical names,
this does not have any clear technical benefit to the user.
<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_inf</h-></code> is sufficiently clear,
and adding <code><h- data-h=id>pos</h-></code> would merely make the function name longer.
</p>
<h4 id=naming-mod><a class=para href=#naming-mod></a>3.2.4. Why is it <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code>?</h4>

<note-block><p><intro-></intro-> 
See <a href=#mod>§3.5. <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code></a>.
</p></note-block>

<p>Despite the fact that <tt->mod</tt-> is somewhat of a misnomer
("remainder" and "modulo" are synonyms),
and despite that it is inconsistent with <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_rem</h-></code>,
it is arguably the best name because:
</p>
<ul>
<li>
It follows the conventions of Haskell, Ada, CSS, and many more languages,
where <tt->mod</tt-> rounds towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math> (unlike <tt->%</tt->, <tt->rem</tt->, etc.).
See <a href=#language-support>§1.1.1. Language support for integer division</a>.
</li>
<li>
It matches the notation of the modulo operator in mathematical literature.
That is,
<math display=inline><mrow>
    <mo>−</mo>
    <mn>2</mn>
    <mo>mod</mo>
    <mn>5</mn>
    <mo>=</mo>
    <mn>3</mn>
</mrow></math>﻿.
</li>
</ul>

<h3 id=interface><a class=para href=#interface></a>3.3. Interface</h3>

<p>The functions generally match the style of similar features in <code><h- data-h=str>&lt;numeric&gt;</h-></code>,
like <a href=https://eel%2eis/c++draft/numeric%2esat>[numeric.sat]</a> or <a href=https://eel%2eis/c++draft/numeric%2eops%2egcd>[numeric.ops.gcd]</a>.
The design also follows <a href="https://wg21%2elink/p3161r4">[P3161R4]</a>.
</p>
<example-block><p><intro-></intro-> 
For rounding to zero, the following functions exist:
</p><code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>struct</h-> <h- data-h=id>div_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>remainder</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> not noexcept </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>;</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> not noexcept </h-><h- data-h=cmt_dlim>*/</h-><h- data-h=sym_punc>;</h-></code-block>
<p>It is constrained to accept only signed or unsigned integer types.
</p></example-block>

<h4 id=error-handling-noexcept><a class=para href=#error-handling-noexcept></a>3.3.1. Error handling and <code><h- data-h=kw>noexcept</h-></code></h4>

<p>These functions are not <code><h- data-h=kw>noexcept</h-></code> because they could not have a wide contract;
they naturally have undefined behavior for cases like <code><h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-></code>
or <code><h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=mac>INT_MIN</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=sym_par>)</h-></code>.
Looking at <a href=#implementation>§ Appendix A — Reference implementation</a>,
it would require additional effort to perform error handling such as throwing exceptions,
so it seems best to leave these functions undefined if and only if division is undefined too.
</p>
<p>However, an invocation of these functions is not a constant expression for such inputs;
i.e. we don't get undefined behavior during constant evaluation.
This can even be implemented without a single additional line of code:
since we always perform a division in these functions,
they naturally get disqualified from being core constant expressions when division is undefiend.
</p>
<h4 id=why-no--parameter?><a class=para href=#why-no--parameter?></a>3.3.2. Why no <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>rounding</h-></code> parameter?</h4>

<p>As compared to <a href="https://wg21%2elink/p0105r1">[P0105R1]</a>,
I do not propose that the rounding mode is passed as a runtime parameter.
</p>
<p>In virtually every case, the rounding mode for an integer division is a fixed choice.
This is evidenced by the ten trillion existing uses of the <code><h- data-h=sym_op>/</h-></code> operator
which <em>always</em> truncate.
Also, the implementation of the proposed functions does not lend itself to a runtime parameter:
</p>
<code-block><h- data-h=kw_type>int</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_negative</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>-</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_negative</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=kw>auto</h-> <h- data-h=id>sgn</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_sqr>[</h-><h- data-h=sym_sqr>]</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>z</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>z</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-> <h- data-h=sym_punc>:</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>sgn</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>sgn</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>As can be seen, these implementations are substantially different.
</p>
<note-block><p><intro-></intro-> 
While <code><h- data-h=id>div_to_neg_inf</h-></code> could <em>theoretically</em> use the <code><h- data-h=id>quotient_sign</h-></code> instead,
it requires more operations to compute this positive/negative sign instead of merely checking
whether the quotient is negative.
This would be an unnecessary performance penalty.
</p>
<p>In practice, compilers optimize <code><h- data-h=id>sgn</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>sgn</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-></code>
strictly worse than <code><h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-></code>.
</p></note-block>

<p>If we now provided a runtime <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>rounding</h-></code>,
the obvious implementation would look like:
</p>
<code-block><h- data-h=kw>enum</h-> <h- data-h=kw>struct</h-> <h- data-h=id>rounding</h-> <h- data-h=sym_brac>{</h-> <h- data-h=id>to_zero</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>to_neg_inf</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>away_zero</h-><h- data-h=sym_punc>,</h-> <h- data-h=cmt_dlim>/*</h-><h- data-h=cmt> ... </h-><h- data-h=cmt_dlim>*/</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw_type>int</h-> <h- data-h=id>divide</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>rounding_mode</h-> <h- data-h=id>mode</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>switch</h-> <h- data-h=sym_par>(</h-><h- data-h=id>mode</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>case</h-> <h- data-h=id>rounding</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_zero</h-><h- data-h=sym_punc>:</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>case</h-> <h- data-h=id>rounding</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_neg_inf</h-><h- data-h=sym_punc>:</h-> <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>case</h-> <h- data-h=id>rounding</h-><h- data-h=sym_op>::</h-><h- data-h=id>away_zero</h-><h- data-h=sym_punc>:</h->  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> ...</h->
    <h- data-h=sym_brac>}</h->
    <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>unreachable</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<p>The user can trivially make such an <code><h- data-h=kw>enum</h-> <h- data-h=kw>class</h-></code> and <code><h- data-h=kw_ctrl>switch</h-></code> themselves,
if they actually need to.
If they don't (which is likely),
all we accomplish is making the user write
<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>divide</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>rounding</h-><h- data-h=sym_op>::</h-><h- data-h=id>to_neg_inf</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-></code> instead of
<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-></code>.
</p>
<h4 id=div-result><a class=para href=#div-result></a>3.3.3. <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-></code></h4>

<p>As seen in in <a href=#interface>§3.3. Interface</a>,
we define an additional class template <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_result</h-></code>:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>struct</h-> <h- data-h=id>div_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>remainder</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-></code-block>

<p>This generally matches standard library style,
including the active proposal <a href="https://wg21%2elink/p3161r4">[P3161R4]</a>,
and including the "legacy types" <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>div_t</h-></code>,
<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>ldiv_t</h-></code>.
That is, we should not use reference output parameters,
but return a value.
</p>
<p>However, we should also not reuse those legacy types
because it is not possible to deduce their "member type" from the class,
which would make them clunky in generic code.
There also exist no such classes for extended integer types and bit-precise integer types.
</p>
<p><code><h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-></code> exists because the user may want to compare
the quotient and remainder to an existing pair of values in one go,
or store results of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_rem</h-></code> functions in a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>set</h-></code>, etc.
It would seem arbitrarily limiting to make <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_result</h-></code> incomparable.
</p>
<h4 id=div-rem-combined><a class=para href=#div-rem-combined></a>3.3.4. Do we really need the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_rem_</h-><h- data-h=sym_op>*</h-></code> functions?</h4>

<p>Yes, because it is non-trivial to compute the remainder without overflow
for rounding modes other than towards zero.
See <a href=#computing-remainders-is-hard>§2.2. Computing remainders is hard, actually</a>.
</p>
<p>Furthermore,
it is relatively cheap to obtain the remainder as a side product of any division function
(see <a href=#implementation>§ Appendix A — Reference implementation</a>).
On extremely feature-starved hardware with no instructions for division and multiplication,
computing the remainder via multiplication may be more expensive
than producing it "directly" during division (implemented in software).
</p>
<h3 id=supported-rounding-modes><a class=para href=#supported-rounding-modes></a>3.4. Supported rounding modes</h3>

<p>It is apparent that the proposal contains quite a lot of rounding modes
– more than just the traditional <code><h- data-h=id>ceil</h-></code>, <code><h- data-h=id>floor</h-></code>, <code><h- data-h=id>round</h-></code>.
It is therefore valid to ask:
</p>
<blockquote><p>Do we really need all these rounding modes?</p></blockquote>

<p>All proposed "top-level rounding modes" have practical applications.
For consistency, the same set of "tie-breaking rounding modes" is provided.
In any case, the implementation of these modes is all fairly similar,
and there is neither any significant implementation cost (<a href=#implementation>§ Appendix A — Reference implementation</a>)
nor wording cost (<a href=#wording>§6. Wording</a>)
to having a few extra functions.
This would be a much different discussion for floating-point numbers.
</p>
<p>I suspect that cherry-picking the "useful" rounding modes out of the proposed ones
would devolve into endless discussion,
and the design would have an inconsistent feel to it if say,
division away from zero was provided,
but no division to the nearest integer with tie breaks away from zero.
</p>
<h4 id=rounding-to-zero><a class=para href=#rounding-to-zero></a>3.4.1. Rounding to zero</h4>

<p>The "trivial" functions <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_zero</h-></code>
and <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>rem_dividend_sign</h-></code> exist solely for consistency and enhanced expressiveness.
Note that not every has a truncating integer division like C++.
For example, the <tt-><h- data-h=sym_op>//</h-></tt-> operator in Python rounds towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>.
A team of developers with primarily Python experience/habits
may thus benefit from always expressing
rounding mode explicitly with <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_zero</h-></code> to avoid confusion.
</p>
<h4 id=rounding-to-even/odd><a class=para href=#rounding-to-even/odd></a>3.4.2. Rounding to even/odd</h4>

<p>Rounding to even/odd integers is mainly useful because it is unbiased.
That is, when dividing a large amount of integers,
results would not gravitate towards one end due to rounding mode bias towards zero, <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math>, etc.
This may be important when operating on fixed-point numbers.
</p>
<p><a href="https://wg21%2elink/p0105r1">[P0105R1]</a> provides additional motivation and explanation of these rounding modes.
</p>
<h4 id=to-nearest-rounding-division-and-tie-breaking><a class=para href=#to-nearest-rounding-division-and-tie-breaking></a>3.4.3. To-nearest-rounding division and tie breaking</h4>

<p>Saying "round to nearest" is not clear enough in itself
because ties (where the fractional part of the quotient is exactly <code><h- data-h=num_dlim>.</h-><h- data-h=num>5</h-></code>)
could also be resolved in multiple ways.
Any of the "top-level rounding modes" could plausibly be chosen
as a "tie-breaking rounding mode" as well,
which is what this proposal offers.
</p>
<h3 id=mod><a class=para href=#mod></a>3.5. <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code></h3>

<p>In addition to the quotient (<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_</h-><h- data-h=sym_op>*</h-></code>)
and quotient/remainder functions (<code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_rem_</h-><h- data-h=sym_op>*</h-></code>),
we also define a single function <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code>
which specifically computes the remainder of the division rounding towards <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math>.
</p>
<p>Unlike the other rounding modes,
the remainder of division rounding to <math display=inline><mrow><mo>−</mo><mi>∞</mi></mrow></math> is uniquely useful for modular arithmetic
because the sign of the remainder is the sign of the divisor.
In other words, if we divide by a positive number, the remainder is always positive.
This is why it has a dedicated function.
</p>
<p>Division rounding to zero, where the sign of the remainder is that of the divisor,
already has <code><h- data-h=sym_op>%</h-></code>, so no dedicated function is required.
The other rounding modes have more chaotic remainder signs,
and thus it is rarely useful to compute the remainder in isolation,
not in conjunction with the quotient.
</p>
<note-block><p><intro-></intro-> See <a href=#naming-mod>§3.2.4. Why is it <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-></code>?</a>.</p></note-block>

<h2 id=implementation-experience><a class=para href=#implementation-experience></a>4. Implementation experience</h2>

<p>A reference implementation can be found on <a href="https://github%2ecom/Eisenwave/integer-division">[GitHub]</a>.
A simplified version of that, for educational purposes,
can be found at <a href=#implementation>§ Appendix A — Reference implementation</a>.
</p>
<p>Generally speaking,
a portable strategy is to implement all divisions by performing a division
with rounding towards zero (<code><h- data-h=sym_op>/</h-></code> and <code><h- data-h=sym_op>%</h-></code>),
and then adjusting the quotient and remainder to emulate a different rounding mode.
</p>
<example-block><p><intro-></intro-> 
Just to illustrate the principle,
consider how one would round towards <math display=inline><mrow><mo>+</mo><mi>∞</mi></mrow></math> with unsigned operands:
</p><code-block><h- data-h=kw_type>unsigned</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> for reference</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->
<h- data-h=kw_type>unsigned</h-> <h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>unsigned</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>unsigned</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> + 1 if the remainder is nonzero</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>On x86_64, Clang compiles this as follows:
</p><code-block><h- data-h=id_labl_decl>div_to_zero:</h->               <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> edi = x, esi = y</h->
        <h- data-h=asm_ins>mov</h->     <h- data-h=id_var>eax</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>edi</h->   <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> eax = edi</h->
        <h- data-h=asm_ins>xor</h->     <h- data-h=id_var>edx</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>edx</h->   <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> edx = 0 (clear upper 32 bits of divided)</h->
        <h- data-h=asm_ins>div</h->     <h- data-h=id_var>esi</h->        <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> eax = eax / esi, edx = eax % esi</h->
        <h- data-h=asm_ins>ret</h->                <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> return eax</h->

<h- data-h=id_labl_decl>div_to_inf:</h->                <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> edi = x, esi = y</h->
        <h- data-h=asm_ins>mov</h->     <h- data-h=id_var>eax</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>edi</h->   <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> eax = edi</h->
        <h- data-h=asm_ins>xor</h->     <h- data-h=id_var>edx</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_var>edx</h->   <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> edx = 0 (clear upper 32 bits of divided)</h->
        <h- data-h=asm_ins>div</h->     <h- data-h=id_var>esi</h->        <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> eax = eax / esi, edx = eax % esi</h->
        <h- data-h=asm_ins>cmp</h->     <h- data-h=id_var>edx</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>1</h->     <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> b = edx &lt; 1</h->
        <h- data-h=asm_ins>sbb</h->     <h- data-h=id_var>eax</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h->    <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> eax -= -1 + b</h->
        <h- data-h=asm_ins>ret</h->                <h- data-h=cmt_dlim>;</h-><h- data-h=cmt> return eax</h-></code-block>
<p>Note that even on architectures where the remainder is not computed
simultaneously with the quotient like for <code><h- data-h=asm_ins>div</h-></code>,
only one division is necessary;
the remainder can be obtained from the quotient.
</p></example-block>

<p>Consequently, the implementation effort for all of these functions is close to zero.
None of them require intrinsics or much architecture-specific knowledge;
if any, rounding towards zero is supported in hardware
(<a href=#hardware-support-for-integer-division>§1.1.2. Hardware support for integer division</a>),
and even if it isn't,
<code><h- data-h=sym_op>/</h-></code> has to exist and the other rounding modes can be implemented in terms of it,
exactly the same.
</p>
<h2 id=try-it-yourself><a class=para href=#try-it-yourself></a>5. Try it yourself</h2>

<style>
.int-input {
    background: none;
    border: 1px solid var(--border-color);
    font-family: var(--monospace-family);
    text-align: right;
    width: fit-content;
    min-width: 2em;
    color: inherit;
}
</style>

<p>If you have JavaScript enabled,
you can play around with the following code block.
</p><code-block><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>=</h-> <input id=x-input class=int-input type=number value=-12></input><h- data-h=sym_punc>;</h->
<h- data-h=kw_type>int</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <input id=y-input class=int-input type=number value=5></input><h- data-h=sym_punc>;</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> input expression             </h-><h- data-h=cmt>→</h-><h- data-h=cmt>  output</h->
<h- data-h=kw_type>double</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>/</h-> <h- data-h=kw_type>double</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h->           →  <h- data-h=num><span id=quo-double>-2.4</span></h->

<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->          →  <h- data-h=num><span id=quo-trunc>-2</span></h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> x / y</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->        →  <h- data-h=num><span id=quo-mag>-3</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->           →  <h- data-h=num><span id=quo-ceil>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->       →  <h- data-h=num><span id=quo-floor>-3</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->           →  <h- data-h=num><span id=quo-odd>-3</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->          →  <h- data-h=num><span id=quo-even>-2</span></h->

<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->     →  <h- data-h=num><span id=quo-ties-trunc>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->   →  <h- data-h=num><span id=quo-ties-mag>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->      →  <h- data-h=num><span id=quo-ties-ceil>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->  →  <h- data-h=num><span id=quo-ties-floor>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->      →  <h- data-h=num><span id=quo-ties-odd>-2</span></h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>div_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->     →  <h- data-h=num><span id=quo-ties-even>-2</span></h->

<h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h->                           →  <h- data-h=num><span id=rem-trunc>-2</span></h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> sign matches x</h->
<h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>mod</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->                  →  <h- data-h=num><span id=rem-floor>3</span></h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> sign matches y</h-></code-block>

<note-block><p><intro-></intro-> 
This demonstration conveniently ignores that <code><h- data-h=kw_type>int</h-></code> has finite size.
Under the hood, calculations are performed using JavaScript's <tt->BigInt</tt->.
</p></note-block>

<script>const x_input = document.getElementById("x-input");
const y_input = document.getElementById("y-input");
const inputs = [x_input, y_input];

const quo_double = document.getElementById("quo-double");
const quo_trunc = document.getElementById("quo-trunc");
const quo_mag = document.getElementById("quo-mag");
const quo_floor = document.getElementById("quo-floor");
const quo_ceil = document.getElementById("quo-ceil");
const quo_odd = document.getElementById("quo-odd");
const quo_even = document.getElementById("quo-even");
const quo_ties_trunc = document.getElementById("quo-ties-trunc");
const quo_ties_mag = document.getElementById("quo-ties-mag");
const quo_ties_floor = document.getElementById("quo-ties-floor");
const quo_ties_ceil = document.getElementById("quo-ties-ceil");
const quo_ties_odd = document.getElementById("quo-ties-odd");
const quo_ties_even = document.getElementById("quo-ties-even");
const rem_trunc = document.getElementById("rem-trunc");
const rem_floor = document.getElementById("rem-floor");

const outputs = [
    quo_trunc, quo_mag, quo_floor, quo_ceil, quo_odd, quo_even,
    quo_ties_trunc, quo_ties_mag, quo_ties_floor, quo_ties_ceil, quo_ties_odd, quo_ties_even,
    rem_trunc, rem_floor
];

for (const input of inputs) {
    input.addEventListener("input", compute_outputs);
}

function compute_outputs() {
    try {
        const x = BigInt(x_input.value);
        const y = BigInt(y_input.value);

        if (y === 0n) {
            on_error("DIVISION BY ZERO");
            return;
        } else {
            clear_errors();
        }

        const quotient_negative = (x >= 0) != (y >= 0);
        const quotient_sign = sgn(x) * sgn(y);

        const double = Number(x) / Number(y);
        const trunc = x / y;
        const mag = trunc + BigInt(x % y !== 0n) * quotient_sign;
        const floor = trunc - BigInt(x % y !== 0n && quotient_negative);
        const ceil = trunc + BigInt(x % y !== 0n && !quotient_negative);
        const odd = trunc + BigInt(x % y !== 0n && trunc % 2n === 0n) * quotient_sign;
        const even = trunc + BigInt(x % y !== 0n && trunc % 2n !== 0n) * quotient_sign;

        quo_double.innerText = String(double);
        quo_trunc.innerText = String(trunc);
        quo_mag.innerText = String(mag);
        quo_floor.innerText = String(floor);
        quo_ceil.innerText = String(ceil);
        quo_odd.innerText = String(odd);
        quo_even.innerText = String(even);

        const abs_rem2 = (2n * x % (2n * y)) * sgn(x);
        const abs_y = y * sgn(y);

        const ties_trunc = trunc + BigInt(x % y !== 0n && abs_rem2 > abs_y) * quotient_sign;
        const ties_mag = trunc + BigInt(x % y !== 0n && abs_rem2 >= abs_y) * quotient_sign;
        const ties_floor = trunc + BigInt(x % y !== 0n && abs_rem2 >= abs_y + BigInt(!quotient_negative)) * quotient_sign;
        const ties_ceil = trunc + BigInt(x % y !== 0n && abs_rem2 >= abs_y + BigInt(quotient_negative)) * quotient_sign;
        const ties_odd = trunc + BigInt(x % y !== 0n && abs_rem2 >= abs_y + BigInt(trunc % 2n === 0)) * quotient_sign;
        const ties_even = trunc + BigInt(x % y !== 0n && abs_rem2 >= abs_y + BigInt(trunc % 2n !== 0)) * quotient_sign;

        quo_ties_trunc.innerText = String(ties_trunc);
        quo_ties_mag.innerText = String(ties_mag);
        quo_ties_floor.innerText = String(ties_floor);
        quo_ties_ceil.innerText = String(ties_ceil);
        quo_ties_odd.innerText = String(ties_odd);
        quo_ties_even.innerText = String(ties_even);

        const r_trunc = x % y;
        const r_floor = x - floor * y;

        rem_trunc.innerText = String(r_trunc);
        rem_floor.innerText = String(r_floor);
    } catch (e) {
        on_error("SYNTAX ERROR");
    }
}

function sgn(x) {
    return BigInt(x > 0n) - BigInt(x < 0n);
}

function clear_errors() {
    for (const output of outputs) {
        output.parentElement.setAttribute("data-h", "num");
    }
}

function on_error(text) {
    for (const output of outputs) {
        output.textContent = text;
        output.parentElement.setAttribute("data-h", "err");
    }
}

compute_outputs();
</script>

<h2 id=wording><a class=para href=#wording></a>6. Wording</h2>

<p>All changes are relative to <a href="https://wg21%2elink/n5008">[N5008]</a>.
</p>
<h3 id=[structure.specifications]><a class=para href=#[structure%2especifications]></a>6.1. [structure.specifications]</h3>

<p>In <a href=https://eel%2eis/c++draft/structure%2especifications#3>[structure.specifications] paragraph 3</a>,
add a bullet immediately following bullet 3.4:
</p>


<diff-block>
<ul>
<li>
<i>Preconditions</i>:
conditions that the function assumes to hold whenever it is called;
violation of any preconditions results in undefined behavior.
</li>
<li><i>Hardened preconditions</i>: […]</li>
<li><ins>
<i>Constant-checked preconditions</i>:
equivalent to a <i>Preconditions</i> specification,
except that a function call expression that violates the assumed condition
is not a core constant expression (<a href=https://eel%2eis/c++draft/expr%2econst>[expr.const]</a>).
</ins></li>
</ul>
</diff-block>

<p>Change <a href=https://eel%2eis/c++draft/structure%2especifications#4>[structure.specifications] paragraph 4</a> as follows:
</p>
<diff-block>
<p>Whenever the <i>Effects</i> element specifies that the semantics of some function
<code><h- data-h=id>F</h-></code> are <i>Equivalent to</i> some code sequence, then the various elements are
interpreted as follows.
If <code><h- data-h=id>F</h-></code>'s semantics specifies any <i>Constraints</i> or <i>Mandates</i> elements,
then those requirements are logically imposed prior to the <i>equivalent-to</i> semantics.
Next, the semantics of the code sequence are determined by the
<i>Constraints</i>,
<i>Mandates</i>,
<i>Preconditions</i>,
<i>Hardened preconditions</i>,
<ins><i>Constant-checked preconditions</i>,</ins>
<i>Effects</i>,
<i>Synchronization</i>,
<i>Postconditions</i>,
<i>Returns</i>,
<i>Throws</i>,
<i>Complexity</i>,
<i>Remarks</i>, and
<i>Error conditions</i>
specified for the function invocations contained in the code sequence.
The value returned from <code><h- data-h=id>F</h-></code> is specified by <code><h- data-h=id>F</h-></code>'s <i>Returns</i> element,
or if <code><h- data-h=id>F</h-></code> has no <i>Returns</i> element,
a non-<code><h- data-h=kw_type>void</h-></code> return from <code><h- data-h=id>F</h-></code> is specified by the
<code><h- data-h=kw_ctrl>return</h-></code> statements (<a href=https://eel%2eis/c++draft/stmt%2ereturn>[stmt.return]</a>) in the code sequence.
If <code><h- data-h=id>F</h-></code>'s semantics contains a <i>Throws</i>,
<i>Postconditions</i>, or <i>Complexity</i> element,
then that supersedes any occurrences of that element in the code sequence.
</p></diff-block>

<h3 id=[version.syn]><a class=para href=#[version%2esyn]></a>6.2. [version.syn]</h3>

<p>Change the synopsis in <a href=https://eel%2eis/c++draft/version%2esyn>[version.syn]</a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=mac>#define __cpp_lib_integer_comparison_functions      202002L </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>also in </h-></f-serif><h- data-h=cmt>&lt;utility&gt;</h->
<ins><h- data-h=mac>#define __cpp_lib_integer_division                  20XXXXL </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding, also in </h-></f-serif><h- data-h=cmt>&lt;numeric&gt;</h-></ins>
<h- data-h=mac>#define __cpp_lib_integer_sequence                  201304L </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>freestanding, also in </h-></f-serif><h- data-h=cmt>&lt;utility&gt;</h-></code-block>
</diff-block>

<h3 id=[bit.pow.two]><a class=para href=#[bit%2epow%2etwo]></a>6.3. [bit.pow.two]</h3>

<p>Change <a href=https://eel%2eis/c++draft/bit%2epow%2etwo#5>[bit.pow.two] paragraph 5</a> as follows:
</p>
<diff-block>
<p><del><i>Preconditions</i>:</del> <ins><i>Constant-checked preconditions</i>:</ins>
<math display=inline><mi>N</mi></math> is representable as a value of type <code><h- data-h=id>T</h-></code>.
</p></diff-block>

<p>Delete <a href=https://eel%2eis/c++draft/bit%2epow%2etwo#8>[bit.pow.two] paragraph 8</a>:
</p>
<del-block>
<p><i>Remarks</i>:
A function call expression that violates the precondition in the <i>Preconditions</i>: element
is not a core constant expression (<a href=https://eel%2eis/c++draft/expr%2econst>[expr.const]</a>).
</p></del-block>

<h3 id=[numeric.ops.overview]><a class=para href=#[numeric%2eops%2eoverview]></a>6.4. [numeric.ops.overview]</h3>

<p>Change the synopsis in <a href=https://eel%2eis/c++draft/numeric%2eops%2eoverview>[numeric.ops.overview]</a> as follows:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>namespace</h-> <h- data-h=id>std</h-> <h- data-h=sym_brac>{</h->
  […]

  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>[numeric.sat], saturation arithmetic</h-></f-serif>
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>add_sat</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>sub_sat</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>mul_sat</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_sat</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>class</h-> <h- data-h=id>U</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>saturate_cast</h-><h- data-h=sym_par>(</h-><h- data-h=id>U</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h->

<ins>  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>[numeric.int.div], integer division</h-></f-serif>
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>struct</h-> <h- data-h=id>div_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>remainder</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
  <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->

  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
    <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>mod</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></ins>
<h- data-h=sym_brac>}</h-></code-block>
</diff-block>

<h3 id=[numeric.sat.func]><a class=para href=#[numeric%2esat%2efunc]></a>6.5. [numeric.sat.func]</h3>

<p>Change <a href=https://eel%2eis/c++draft/numeric%2esat%2efunc#9>[numeric.sat.func] paragraph 9</a> as follows:
</p>
<diff-block>
<p><del><i>Preconditions</i>:</del> <ins><i>Constant-checked preconditions</i>:</ins>
<code><h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-></code> is <code><h- data-h=bool>true</h-></code>.
</p></diff-block>

<p>Delete <a href=https://eel%2eis/c++draft/numeric%2esat%2efunc#11>[numeric.sat.func] paragraph 11</a>:
</p>
<del-block>
<p><i>Remarks</i>:
A function call expression that violates the precondition in the <i>Preconditions</i>: element
is not a core constant expression (<a href=https://eel%2eis/c++draft/expr%2econst>[expr.const]</a>).   
</p></del-block>

<h3 id=new-subclause><a class=para href=#new-subclause></a>6.6. [numeric.int.div]</h3>

<p>Append a new subclause to <a href=https://eel%2eis/c++draft/numeric%2eops>[numeric.ops]</a>,
following <a href=https://eel%2eis/c++draft/numeric%2esat>[numeric.sat]</a>:
</p>
<ins-block>
<h2>Integer division <span class=stable-ref>[numeric.int.div]</span></h2>






<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>1
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>2
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>3
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards zero.<br/>
<wg21-block>[<i>Note</i>: 
The result equals <code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code>.
 — <i>end note</i>]</wg21-block>
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>4
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>5
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>6
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded away from zero.
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>7
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>8
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>9
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards positive infinity.
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>10
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>11
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>12
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards negative infinity.
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>13
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>14
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>15
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest odd integer.
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>16
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>17
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>18
<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest even integer.
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>19
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>20
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>21

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the integer with lower magnitude.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>22
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>23
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>24

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the integer with greater magnitude.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>25
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>26
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>27

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the greater integer.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>28
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>29
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>30

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the lower integer.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>31
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>32
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>33

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the odd integer.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>div_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>34
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>35
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>36

<i>Returns</i>: <math display=inline><mfrac><mi>x</mi><mi>y</mi></mfrac></math>, rounded towards the nearest integer.
If two integers are equidistant, the result is the even integer.

</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_</h-><i><h- data-h=id>rounding</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>37
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is a signed or unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).</p>

<p>38
<i>Constant-checked preconditions</i>:
<code><h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-></code> is well-defined.
</p>
<p>39
<i>Returns</i>:
A result object where
</p><ul style=margin:0>
<li><code><h- data-h=id>quotient</h-></code> is the quotient <math display=inline><mi>q</mi></math> returned by <code><h- data-h=id>div_</h-><i><h- data-h=id>rounding</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-></code> and</li>
<li>
<code><h- data-h=id>remainder</h-></code> is <math display=inline><mrow><mi>x</mi><mo>−</mo><mi>q</mi><mi>y</mi></mrow></math>
if <code><h- data-h=id>T</h-></code> is signed, otherwise
the integer congruent to <math display=inline><mrow><mi>x</mi><mo>−</mo><mi>q</mi><mi>y</mi></mrow></math>
modulo <math display=inline><msup><mn>2</mn><mi>N</mi></msup></math>
where <math display=inline><mi>N</mi></math> is the width of <code><h- data-h=id>T</h-></code>.
</li>
</ul>
<p><wg21-block>[<i>Note</i>: 
It is possible for <code><h- data-h=id>div_</h-><i><h- data-h=id>rounding</h-></i><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-></code> to have well-defined behavior even when
<code><h- data-h=id>x</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h-></code> has undefined behavior.
<br/><wg21-block>[<i>Example</i>: 
Assume that <code><h- data-h=mac>INT_MAX</h-></code> equals <code><h- data-h=num>2</h-><h- data-h=num_dlim>'</h-><h- data-h=num>147</h-><h- data-h=num_dlim>'</h-><h- data-h=num>483</h-><h- data-h=num_dlim>'</h-><h- data-h=num>647</h-></code>.
<code-block class=borderless><h- data-h=kw>const</h-> <h- data-h=kw>auto</h-> <h- data-h=id>q_to_zero</h-> <h- data-h=sym_op>=</h-> <h- data-h=mac>INT_MAX</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-><h- data-h=sym_punc>;</h->              <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><code><h- data-h=id>q_to_zero</h-></code><h- data-h=cmt> is </h-><code><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>073</h-><h- data-h=num_dlim>'</h-><h- data-h=num>741</h-><h- data-h=num_dlim>'</h-><h- data-h=num>823</h-></code><h- data-h=cmt>.</h-></f-serif>
<h- data-h=kw>const</h-> <h- data-h=kw>auto</h-> <h- data-h=sym_sqr>[</h-><h- data-h=id>q</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>r</h-><h- data-h=sym_sqr>]</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>div_rem_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=mac>INT_MAX</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>2</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><code><h- data-h=id>q</h-></code><h- data-h=cmt> is </h-><code><h- data-h=num>1</h-><h- data-h=num_dlim>'</h-><h- data-h=num>073</h-><h- data-h=num_dlim>'</h-><h- data-h=num>741</h-><h- data-h=num_dlim>'</h-><h- data-h=num>824</h-></code><h- data-h=cmt> and </h-><code><h- data-h=id>r</h-></code><h- data-h=cmt> is </h-><code><h- data-h=sym_op>-</h-><h- data-h=num>1</h-></code><h- data-h=cmt>.</h-></f-serif>
<h- data-h=kw_type>int</h-> <h- data-h=id>r2</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>q</h-> <h- data-h=sym_op>*</h-> <h- data-h=num>2</h-><h- data-h=sym_punc>;</h->                              <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>This multiplication has undefined behavior.</h-></f-serif></code-block>
 — <i>end example</i>]</wg21-block> — <i>end note</i>]</wg21-block>
</p></div>

<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>mod</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>40
<i>Effects</i>:
Equivalent to <code><h- data-h=id>div_rem_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-></code>.
<br/><wg21-block>[<i>Note</i>: 
The result is negative if and only if <code><h- data-h=id>y</h-></code> is negative and <code><h- data-h=id>x</h-></code> is nonzero.
 — <i>end note</i>]</wg21-block>
</p></div>

</ins-block>

<warning-block><p><intro-></intro-> 
If the mathematical notation in the block above does not render for you,
you are using an old browser with no MathML support.
Please open the document in a recent version of Firefox or Chrome.
</p></warning-block>

<h3 id=[simd.bit]><a class=para href=#[simd%2ebit]></a>6.7. [simd.bit]</h3>

<p>Change <a href=https://eel%2eis/c++draft/simd%2ebit#4>[simd.bit] paragraph 4</a> as follows:
</p>
<diff-block>
<p><del><i>Preconditions</i>:</del> <ins><i>Constant-checked preconditions</i>:</ins>
For every <math display=inline><mi>i</mi></math> […].
</p></diff-block>

<p>Delete <a href=https://eel%2eis/c++draft/simd%2ebit#6>[simd.bit] paragraph 6</a>:
</p>
<del-block>
<p><i>Remarks</i>:
A function call expression that violates the precondition in the <i>Preconditions</i>: element
is not a core constant expression (<a href=https://eel%2eis/c++draft/expr%2econst>[expr.const]</a>).   
</p></del-block>

<h2 id=acknowledgements><a class=para href=#acknowledgements></a>7. Acknowledgements</h2>

<p>I sincerely thank Lawrence Crowl (the author of the predecessor paper <a href="https://wg21%2elink/p0105r1">[P0105R1]</a>)
for reviewing this paper in great detail,
providing detailed feedback.
The choice to include combined quotient/remainder functions was only made
after his feedback.
</p>
<h2 id=references><a class=para href=#references></a>8. References</h2>










<div class=bib><div id=bib-item-N5008 class=bib-item>
<a href="https://wg21%2elink/n5008">[N5008]</a>
<span class=bib-author>Thomas Köppe.</span>
<span class=bib-title>Working Draft, Programming Languages — C++</span>
<span class=bib-date>2025-03-15</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/n5008%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5008.pdf</a></div><div id=bib-item-P0105R1 class=bib-item>
<a href="https://wg21%2elink/p0105r1">[P0105R1]</a>
<span class=bib-author>Lawrence Crowl.</span>
<span class=bib-title>Rounding and Overflow in C++</span>
<span class=bib-date>2017-02-05</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2017/p0105r1%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0105r1.html</a></div><div id=bib-item-P1889R1 class=bib-item>
<a href="https://wg21%2elink/p1889r1">[P1889R1]</a>
<span class=bib-author>Alexander Zaitsev.</span>
<span class=bib-title>C++ Numerics Work In Progress</span>
<span class=bib-date>2019-12-27</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2020/p1889r1%2epdf" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1889r1.pdf</a></div><div id=bib-item-P3161R4 class=bib-item>
<a href="https://wg21%2elink/p3161r4">[P3161R4]</a>
<span class=bib-author>Tiago Freire.</span>
<span class=bib-title>Unified integer overflow arithmetic</span>
<span class=bib-date>2025-03-26</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p3161r4%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3161r4.html</a></div><div id=bib-item-StackOverflowCeil class=bib-item>
<a href="https://stackoverflow%2ecom/q/2745074/5740428">[StackOverflowCeil]</a>
<span class=bib-title>Fast ceiling of an integer division in C / C++</span>
<a href="https://stackoverflow%2ecom/q/2745074/5740428" class=bib-link>https://stackoverflow.com/q/2745074/5740428</a></div><div id=bib-item-StackOverflowRound class=bib-item>
<a href="https://stackoverflow%2ecom/q/2422712/5740428">[StackOverflowRound]</a>
<span class=bib-title>Rounding integer division (instead of truncating)</span>
<a href="https://stackoverflow%2ecom/q/2422712/5740428" class=bib-link>https://stackoverflow.com/q/2422712/5740428</a></div><div id=bib-item-BuggyDivisions class=bib-item>
<a href="https://blog%2edemofox%2eorg/2022/07/21/rounding-modes-for-integer-division/">[BuggyDivisions]</a>
<span class=bib-author>njohnny84.</span>
<span class=bib-title>Rounding Modes For Integer Division</span>
<a href="https://blog%2edemofox%2eorg/2022/07/21/rounding-modes-for-integer-division/" class=bib-link>https://blog.demofox.org/2022/07/21/rounding-modes-for-integer-division/</a></div><div id=bib-item-GitHub class=bib-item>
<a href="https://github%2ecom/Eisenwave/integer-division">[GitHub]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>integer-division GitHub repository</span>
<a href="https://github%2ecom/Eisenwave/integer-division" class=bib-link>https://github.com/Eisenwave/integer-division</a></div></div>

<h2 id=implementation><a class=para href=#implementation></a>Appendix A — Reference implementation</h2>

<p>See below a simplified implementation for educational purposes,
which works exclusively with <code><h- data-h=kw_type>int</h-></code>.
See <a href="https://github%2ecom/Eisenwave/integer-division">[GitHub]</a> for the full implementation.
</p>
<code-block><h- data-h=mac>#include &lt;type_traits&gt;</h->
<h- data-h=mac>#include &lt;compare&gt;</h->

<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>struct</h-> <h- data-h=id>div_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>remainder</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>auto</h-> <h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&amp;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>=</h-> <h- data-h=kw>default</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>if</h-> <h- data-h=kw>constexpr</h-> <h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>is_signed_v</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Equivalent to: (x &gt;&gt; (width_of_T - 1)) | 1</h->
        <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>?</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-> <h- data-h=sym_punc>:</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h->    
    <h- data-h=sym_brac>}</h-> <h- data-h=kw_ctrl>else</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=kw_ctrl>return</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>/ Given a dividend x, divisor y, and quotient offset d (-1, 0, or 1),</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>/ returns (x / y + d) as the quotient,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>/ and a remainder of a division between x and y</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>/ that would have yielded that quotient.</h->
<h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw>class</h-> <h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-> <h- data-h=id>d</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>if</h-> <h- data-h=kw>constexpr</h-> <h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>is_signed_v</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=kw>using</h-> <h- data-h=id>U</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>make_unsigned_t</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-><h- data-h=sym_punc>;</h->
        <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h->
            <h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=id>d</h-><h- data-h=sym_punc>,</h->
            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> This is (x % y - d * y),</h->
            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> except that we use unsigned int to avoid overflow when y is INT_MIN.</h->
            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Due to modular arithmetic rules, when we multiply y with -1,</h->
            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> the remainder is congruent to (x % y + y),</h->
            <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> so simply doing it all with unsigned integers fixes our overflow problems.</h->
            <h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>T</h-><h- data-h=sym_par>(</h-><h- data-h=id>U</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>U</h-><h- data-h=sym_par>(</h-><h- data-h=id>d</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>U</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h->
        <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</h-> <h- data-h=kw_ctrl>else</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h-> 
            <h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=id>d</h-><h- data-h=sym_punc>,</h->
            <h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>-</h-> <h- data-h=id>d</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h->
        <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: trivial implementation.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h-> <h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: since '/' truncates,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       we need to increase the quotient magnitude</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       in all cases except when the remainder is zero.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: since '/' truncates,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       the result is one greater than what we want</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       for negative quotients, unless the remainder is zero.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_positive</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>adjust</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_positive</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=sym_op>.</h-><h- data-h=id>quotient</h->  <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>,</h->
        <h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>-</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h->
    <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: since '/' truncates,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       the result is one lower than what we want</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       for positive quotients, unless the remainder is zero.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_negative</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>adjust</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_negative</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=sym_brac>{</h->
        <h- data-h=sym_op>.</h-><h- data-h=id>quotient</h->  <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>-</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>,</h->
        <h- data-h=sym_op>.</h-><h- data-h=id>remainder</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>adjust</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h->
    <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify when this gets us away</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       from an even integer.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>==</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify when this gets us away</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       from an odd integer.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify when the remainder</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       is greater than abs(y / 2).</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;</h-> <h- data-h=id>abs_half_y</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_to_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_away_zero, but we only magnify when the remainder</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       is greater or equal to abs(y / 2).</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       This is actually somewhat tricky because abs(y / 2) drops one bit of precision,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       i.e. the bit indicating .5 or .0 in the number,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       and (abs(2 * x % y) &gt;= abs(y)) may overflow, so we cannot use that instead.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       However, we can get back that one bit of precision using (y % 2 != 0),</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       which optimizes to (y &amp; 1).</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       When y is even, that bit is zero and we didn't drop any precision anyway.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       When y is odd, there are no exact ties, and we increase the right hand side</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       of the comparison to bias more towards truncation instead of magnification.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_away_zero</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_ties_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify on ties when the quotient is positive.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_to_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_ties_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify on ties when the quotient is negative.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>&gt;</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_to_neg_inf</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_ties_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify on ties when the quotient is even.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_to_odd</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: same as div_ties_away_zero,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       but we only magnify on ties when the quotient is odd.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=id>div_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=kw_type>int</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>div_rem_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient_sign</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>__sgn2</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>/</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>increment</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>abs_rem</h-> <h- data-h=sym_op>&gt;=</h-> <h- data-h=id>abs_half_y</h-> <h- data-h=sym_op>+</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>||</h-> <h- data-h=id>quotient</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>2</h-> <h- data-h=sym_op>==</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>__div_rem_offset_quotient</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>increment</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=id>quotient_sign</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>div_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>div_rem_ties_to_even</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-><h- data-h=sym_op>.</h-><h- data-h=id>quotient</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h->

<h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Idea: if the there is a mismatch between the x and y being negative,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       the result sign would be wrong, and we need to flip it;</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       If they match (i.e. if the quotient is positive),</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       we already have the right result.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       If the mismatch is caused by the dividend being negative,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       the remainder is also negative and we should add the (positive) divisor.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       If the mismatch is caused by the divisor being negative,</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       we should add the (negative) divisor to get a negative remainder.</h->
<h- data-h=cmt_dlim>//</h-><h- data-h=cmt>       In either case, adding the divisor is the right thing to do.</h->
<h- data-h=kw>constexpr</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>mod</h-><h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw_type>int</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=kw_type>bool</h-> <h- data-h=id>quotient_negative</h-> <h- data-h=sym_op>=</h-> <h- data-h=sym_par>(</h-><h- data-h=id>x</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_type>int</h-> <h- data-h=id>rem</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>x</h-> <h- data-h=sym_op>%</h-> <h- data-h=id>y</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>rem</h-> <h- data-h=sym_op>+</h-> <h- data-h=id>y</h-> <h- data-h=sym_op>*</h-> <h- data-h=kw_type>int</h-><h- data-h=sym_par>(</h-><h- data-h=id>rem</h-> <h- data-h=sym_op>!=</h-> <h- data-h=num>0</h-> <h- data-h=sym_op>&amp;&amp;</h-> <h- data-h=id>quotient_negative</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>

<note-block><p><intro-></intro-> 
Since integer division occurs unconditionally in these functions,
they also trivially satisfy the <a href=#wording>§6. Wording</a> requirement that invocations of these functions
are not constant expressions when the result is not representable.
</p></note-block>


</main></body>
</html>
