<!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>Carry-less product: std::clmul</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;
  }

  .five-way-poll {
    table-layout: fixed;
  }
  .five-way-poll td {
    width: 20%;
    text-align: center;
  }
</style>

<p><div class=wg21-head><h1>Carry-less product: <tt->std::clmul</tt-></h1>

<dl>
    <dt>Document number:</dt> <dd><a href=https://wg21%2elink/P3642R2>P3642R2</a></dd>
    <dt>Date:</dt>            <dd><tt->2025-07-02</tt-></dd>
    <dt>Audience:</dt>        <dd>LEWG</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/P3642/github class=sans>wg21.link/P3642/github</a></dd>
    <dt>Source:</dt>          <dd><a href=https://github%2ecom/Eisenwave/cpp-proposals/blob/master/src/clmul%2ecow class=sans>github.com/Eisenwave/cpp-proposals/blob/master/src/clmul.cow</a></dd>
</dl>
<hr/>
</div></p>

<abstract-block><p><intro-></intro-> 
Add widening and non-widening carry-less multiplication functions.
</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=#revision-history><h2>Revision history</h2></a>
<div class=toc-num data-level=3>1.1</div>
<a href=#changes-since-r1><h3>Changes since R1</h3></a>
<div class=toc-num data-level=3>1.2</div>
<a href=#changes-since-r0><h3>Changes since R0</h3></a>
<div class=toc-num data-level=2>2</div>
<a href=#introduction><h2>Introduction</h2></a>
<div class=toc-num data-level=2>3</div>
<a href=#motivation><h2>Motivation</h2></a>
<div class=toc-num data-level=3>3.1</div>
<a href=#parity-computation-and-json-parsing><h3>Parity computation and JSON parsing</h3></a>
<div class=toc-num data-level=3>3.2</div>
<a href=#fast-space-filling-curves><h3>Fast space-filling curves</h3></a>
<div class=toc-num data-level=2>4</div>
<a href=#possible-implementation><h2>Possible implementation</h2></a>
<div class=toc-num data-level=3>4.1</div>
<a href=#hardware-support><h3>Hardware support</h3></a>
<div class=toc-num data-level=2>5</div>
<a href=#design-considerations><h2>Design considerations</h2></a>
<div class=toc-num data-level=3>5.1</div>
<a href=#naming><h3>Naming</h3></a>
<div class=toc-num data-level=3>5.2</div>
<a href=#widening><h3>Widening operation</h3></a>
<div class=toc-num data-level=3>5.3</div>
<a href=#simd><h3>SIMD support</h3></a>
<div class=toc-num data-level=4>5.3.1</div>
<a href=#simd-widening-operations-are-out-of-scope><h4>SIMD widening operations are out of scope</h4></a>
<div class=toc-num data-level=2>6</div>
<a href=#wording><h2>Proposed wording</h2></a>
<div class=toc-num data-level=2>7</div>
<a href=#references><h2>References</h2></a>
</div>

<h2 id=revision-history><a class=para href=#revision-history></a>1. Revision history</h2>

<h3 id=changes-since-r1><a class=para href=#changes-since-r1></a>1.1. Changes since R1</h3>

<p>The paper was seen by SG6 at Sofia 2025
with the following feedback:
</p>
<blockquote>
<p><b>Summary</b>:
SG6 had no numerics concerns but recommended to include std::simd overloads into the paper.
</p>
<p><b>POLL</b>:
Forward P3642R1 to LEWG with the expectation
that the next revision includes <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>simd</h-></code> overloads.
</p>
<table class=five-way-poll>
<tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr>
<tr><td>7</td> <td>4</td> <td>0</td> <td>0</td> <td>0</td></tr>
</table>
</blockquote>

<p>The following changes were made:
</p>
<ul>
  <li>Provide (non-widening) <a href=#simd>§5.3. SIMD support</a></li>
  <li>Use two-space indentation, and generally match the code style of the C++ standard</li>
  <li>Provide detailed design description for <a href=#widening>§5.2. Widening operation</a></li>
  <li>Make <a href=#wording>§6. Proposed wording</a> and design independent of <a href="https://wg21%2elink/p3161r4">[P3161R4]</a></li>
  <li>Fix stray <code><h- data-h=id>U</h-></code> type name in <a href=#wording>§6. Proposed wording</a>, and improve wording generally</li>
  <li>Rebase <a href=#wording>§6. Proposed wording</a> on <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>simd</h-></code> naming changes in <a href="https://wg21%2elink/p3691r1">[P3691R1]</a></li>
</ul>

<h3 id=changes-since-r0><a class=para href=#changes-since-r0></a>1.2. Changes since R0</h3>

<ul>
<li>Generate the proposal using COWEL instead of bikeshed</li>
<li>Fix incorrect formula in <a href=#wording>§6. Proposed wording</a> for bits &ge; the integer width</li>
<li>Fix <a href=#hardware-support>§4.1. Hardware support</a> missing new VPCLMULQDQ instructions</li>
<li>Fix improper uses of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>unsigned_integral</h-></code> in <a href=#introduction>§2. Introduction</a></li>
<li>Make slight editorial wording adjustments</li>
<li>Rebase on N5008 and <a href="https://wg21%2elink/p3161r4">[P3161R4]</a></li>
<li>Mention <a href="https://branchfree%2eorg/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/">[SimdJsonClmul]</a> in <a href=#motivation>§3. Motivation</a></li>
</ul>

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

<p><a href=https://en%2ewikipedia%2eorg/wiki/Carry-less_product>Carry-less multiplication</a>
is a simple numerical operation on unsigned integers.
It can be a seen as a regular multiplication where
<code><h- data-h=kw>xor</h-></code> is being used as a reduction instead of <code><h- data-h=sym_op>+</h-></code>.
</p>
<p>It is also known as "XOR multiplication" and "polynomial multiplication".
The latter name is used because mathematically, it is equivalent to performing a multiplication of
two polynomials in GF(2), where each bit is a coefficient.
</p>
<p>I propose a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-></code> function to perform this operation:
</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>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>clmul</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-></code-block>

<p>I also propose a widening operation in the style of <a href="https://wg21%2elink/p3161r4">[P3161R4]</a>, as follows:
</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>wide_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>low_bits</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>high_bits</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>wide_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>clmul_wide</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-></code-block>

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

<p>Carry-less multiplication is an important operation in a number of use cases:
</p>
<ul>
<li>
  <b>CRC Computation:</b> While cyclic redundancy checks can theoretically be performed with a finite
  field of any length, in practice,
  <a href=https://en%2ewikipedia%2eorg/wiki/GF(2)>GF(2)[X]</a>,
  the <i>polynomial ring</i> over the <i>Galois field</i> with two elements is used.
  Polynomial addition in this ring can be implemented via <code><h- data-h=kw>xor</h-></code>,
  and multiplication via <code><h- data-h=id>clmul</h-></code>,
  which makes cyclic redundancy checks considerably faster.
</li>
<li>
  <b>Cryptography:</b> <code><h- data-h=id>clmul</h-></code> may be used to implement AES-GCM.
  <a href="https://www%2eintel%2ecom/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20%2epdf">[IntelClmul]</a> describes this process in great detail and motivates hardware support for
  carry-less multiplication via the <code><h- data-h=id>pclmulqdq</h-></code> instruction.
</li>
<li>
  <b>Bit manipulation:</b> <code><h- data-h=id>clmul</h-></code> performs a large amount
  of <code><h- data-h=sym_op>&lt;&lt;</h-></code> and <code><h- data-h=kw>xor</h-></code> operations in parallel.
  This is utilized in the reference implementation <a href="https://github%2ecom/Eisenwave/cxx26-bit-permutations">[BitPermutations]</a>
  of <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_compressr</h-></code>,
  proposed in <a href="https://wg21%2elink/p3104r3">[P3104R3]</a>.
  For example, the form <span class=word><code><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-></code></span> computes the bitwise inclusive parity
  for each bit of <code><h- data-h=id>x</h-></code> and the bits to its right.
</li>
</ul>

<p>Carry-less multiplication is of such great utility that there is widespread hardware support,
some dating back more than a decade.
See below for motivating examples.
</p>
<h3 id=parity-computation-and-json-parsing><a class=para href=#parity-computation-and-json-parsing></a>3.1. Parity computation and JSON parsing</h3>

<p>The <dfn>parity</dfn> of an integer <code><h- data-h=id>x</h-></code> is <code><h- data-h=num>0</h-></code> if the number of one-bits is even,
and <code><h- data-h=num>1</h-></code> if it is odd.
The parity can also be computed with <code><h- data-h=id>popcount</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=num>1</h-></code>.
</p>
<example-block><p><intro-></intro-> 
The special form <code><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</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> computes the parity of each bit in <code><h- data-h=id>x</h-></code>
and the bits to its right.
The most significant bit holds the parity of <code><h- data-h=id>x</h-></code> as a whole.
</p><code-block><h- data-h=kw_type>bool</h-> <h- data-h=id>parity</h-><h- data-h=sym_par>(</h-><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id_type>uint32_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>return</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=num>31</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
</example-block>

<p>While the parity of <em>all</em> bits can be obtained with <code><h- data-h=id>clmul</h-></code>,
it computes the inclusive cumulative parity,
which can be used to accelerate parsing JSON and other file formats (<a href="https://branchfree%2eorg/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/">[SimdJsonClmul]</a>).
This can be done by mapping each <code><h- data-h=str_dlim>"</h-></code> character onto a <code><h- data-h=num>1</h-></code>-bit,
and any other character onto <code><h- data-h=num>0</h-></code>.
<code><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</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> would then produce masks where string characters
corresponds to a <code><h- data-h=num>1</h-></code>-bit.
</p>
<example-block><p><intro-></intro-> 
</p><pre>
abc xxx <h- data-h=str_dlim>"</h-><h- data-h=str>foobar</h-><h- data-h=str_dlim>"</h-> zzz <h- data-h=str_dlim>"</h-><h- data-h=str>a</h-><h- data-h=str_dlim>"</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> input string</h->
00000000<h- data-h=str_dlim>1</h->000000<h- data-h=str_dlim>1</h->00000<h- data-h=str_dlim>1</h->0<h- data-h=str_dlim>1</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> quote_mask</h->
00000000<h- data-h=str_dlim>.</h-><h- data-h=str>111111</h-><h- data-h=str_dlim>.</h->00000<h- data-h=str_dlim>.</h-><h- data-h=str>1</h-><h- data-h=str_dlim>.</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> clmul(quote_mask, -1), ignoring 1-bits of quote_mask</h->
</pre>
</example-block>

<h3 id=fast-space-filling-curves><a class=para href=#fast-space-filling-curves></a>3.2. Fast space-filling curves</h3>

<p>The special form <code><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</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> can be used to accelerate the computation of Hilbert curves.
To properly understand this example, I will explain the basic notion of space-filling curves.
</p>
<p>We can fill space using a 2D curve by mapping the index <code><h- data-h=id>i</h-></code> on the curve
onto Cartesian coordinates <code><h- data-h=id>x</h-></code> and <code><h- data-h=id>y</h-></code>.
A naive curve that fills a 4x4 square can be computed as follows:
</p><code-block><h- data-h=kw>struct</h-> <h- data-h=id>pos</h-> <h- data-h=sym_brac>{</h-> <h- data-h=id_type>uint32_t</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=sym_brac>}</h-><h- data-h=sym_punc>;</h->

<h- data-h=id>pos</h-> <h- data-h=id>naive_curve</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>uint32_t</h-> <h- data-h=id>i</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=id>i</h-> <h- data-h=sym_op>%</h-> <h- data-h=num>4</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>i</h-> <h- data-h=sym_op>/</h-> <h- data-h=num>4</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_brac>}</h-></code-block>
<p>When mapping the index <code><h- data-h=id>i</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>...</h-><h- data-h=sym_punc>,</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>f</h-></code> onto the returned 2D coordinates,
we obtain the following pattern:
</p><pre>
0 1 2 3
4 5 6 7
8 9 a b
c d e f
</pre>
<p>The problem with such a naive curve is that adjacent indices can be positioned very far apart
(the distance increases with row length).
For image processing, if we store pixels in this pattern, cache locality is bad;
two adjacent pixels can be very far apart in memory.
</p>
<p>A <a href=https://en%2ewikipedia%2eorg/wiki/Hilbert_curve>Hilbert curve</a>
is a family of space-filling curves where the distance between two adjacent
elements is <code><h- data-h=num>1</h-></code>:
</p><pre>
0 1 e f
3 2 d c
4 7 8 b
5 6 9 a
</pre>
<p>De-interleaving bits of <code><h- data-h=id>i</h-></code> into <code><h- data-h=id>x</h-></code> and <code><h- data-h=id>y</h-></code>
yields a <a href=https://en%2ewikipedia%2eorg/wiki/Z-order_curve>Z-order curve</a>,
and performing further transformations yields a
<a href=https://en%2ewikipedia%2eorg/wiki/Hilbert_curve>Hilbert curve</a>.
</p>
<example-block><p><intro-></intro-> 
<code><h- data-h=id>clmul</h-></code> can be used to compute the bitwise parity for each bit and the bits to its right,
which is helpful for computing Hilbert curves.
Note that the following example uses the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_compress</h-></code> function from <a href="https://wg21%2elink/p3104r3">[P3104R3]</a>,
which may also be accelerated using <code><h- data-h=id>clmul</h-></code>.
</p>
<code-block><h- data-h=id>pos</h-> <h- data-h=id>hilbert_to_xy</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>uint32_t</h-> <h- data-h=id>i</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> De-interleave the bits of i.</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>i0</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_compress</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><h- data-h=sym_punc>,</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>55555555</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> abcdefgh </h-><h- data-h=cmt>→</h-><h- data-h=cmt> bdfh</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>i1</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_compress</h-><h- data-h=sym_par>(</h-><h- data-h=id>i</h-><h- data-h=sym_punc>,</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>aaaaaaaa</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> abcdefgh </h-><h- data-h=cmt>→</h-><h- data-h=cmt> aceg</h->
  
  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> Undo the permutation that Hilbert curves apply on top of Z-order curves.</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>A</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>i0</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=id>i1</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>B</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>i0</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>i1</h-> <h- data-h=sym_op>^</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>ffff</h-><h- data-h=num_deco>u</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>C</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>A</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=num>16</h-><h- data-h=sym_punc>;</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>D</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>B</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>-</h-><h- data-h=num>1</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=num>16</h-><h- data-h=sym_punc>;</h->
  
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>C</h-> <h- data-h=sym_op>^</h-> <h- data-h=sym_par>(</h-><h- data-h=id>i0</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=id>D</h-><h- data-h=sym_par>)</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>x</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>i1</h-><h- data-h=sym_punc>,</h-> <h- data-h=sym_op>.</h-><h- data-h=id>y</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>a</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>i0</h-> <h- data-h=sym_op>^</h-> <h- data-h=id>i1</h-> <h- data-h=sym_brac>}</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
<p>This specific example is taken from <a href="%22http://threadlocalmutex%2ecom/?p=188">[FastHilbertCurves]</a>.
<a href="https://doc%2elagout%2eorg/security/Hackers'Delight%2epdf">[HackersDelight]</a> explains the basis behind this computation
of Hilbert curves using bitwise operations.
</p></example-block>

<p>When working with space-filling curves, the inverse operation is also common:
mapping the Cartesian coordinates onto an index on the curve.
In the case of Z-order curves aka. Morton curves,
this can be done by simply interleaving the bits of <code><h- data-h=id>x</h-></code> and <code><h- data-h=id>y</h-></code>.
A Z-order curve is laid out as follows:
</p><pre>
0 1 4 5
2 3 6 7
8 9 c d
a b e f
</pre>

<example-block><p><intro-></intro-> 
<code><h- data-h=id>clmul</h-></code> can be used to implement bit-interleaving in order to generate a
<a href=https://en%2ewikipedia%2eorg/wiki/Z-order_curve>Z-order curves</a>.
</p><code-block><h- data-h=id_type>uint32_t</h-> <h- data-h=id>xy_to_morton</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>uint32_t</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_type>uint32_t</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>lo</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;&lt;</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> abcd -&gt; 0a0b0c0d</h->
  <h- data-h=id_type>uint32_t</h-> <h- data-h=id>hi</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;&lt;</h-> <h- data-h=num>1</h-><h- data-h=sym_punc>;</h-> <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> abcd -&gt; a0b0c0d0</h->
  <h- data-h=kw_ctrl>return</h-> <h- data-h=id>hi</h-> <h- data-h=sym_op>|</h-> <h- data-h=id>lo</h-><h- data-h=sym_punc>;</h->
<h- data-h=sym_brac>}</h-></code-block>
</example-block>

<note-block><p><intro-></intro-> 
In the example above, <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-></code> is equivalent to
<a href="https://wg21%2elink/p3104r3">[P3104R3]</a>'s <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>bit_expand</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=num_deco>0x</h-><h- data-h=num>55555555</h-><h- data-h=num_deco>u</h-><h- data-h=sym_par>)</h-></code>.
</p></note-block>

<h2 id=possible-implementation><a class=para href=#possible-implementation></a>4. Possible implementation</h2>

<p>A naive and unconstrained implementation looks as follows:
</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>constexpr</h-> <h- data-h=id>T</h-> <h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>T</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</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_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>result</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw_ctrl>for</h-> <h- data-h=sym_par>(</h-><h- data-h=kw_type>int</h-> <h- data-h=id>i</h-> <h- data-h=sym_op>=</h-> <h- data-h=num>0</h-><h- data-h=sym_punc>;</h-> <h- data-h=id>i</h-> <h- data-h=sym_op>&lt;</h-> <h- data-h=id>numeric_limits</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_op>::</h-><h- data-h=id>digits</h-><h- data-h=sym_punc>;</h-> <h- data-h=sym_op>++</h-><h- data-h=id>i</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
      <h- data-h=id>result</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;&lt;</h-> <h- data-h=id>i</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>*</h-> <h- data-h=sym_par>(</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-> <h- data-h=sym_op>&gt;&gt;</h-> <h- data-h=id>i</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&amp;</h-> <h- data-h=num>1</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</h->
    <h- data-h=kw_ctrl>return</h-> <h- data-h=id>result</h-><h- data-h=sym_punc>;</h->
  <h- data-h=sym_brac>}</h-></code-block>

<h3 id=hardware-support><a class=para href=#hardware-support></a>4.1. Hardware support</h3>

<p>The implementation difficulty lies mostly in utilizing available hardware instructions,
not in the naive fallback implementation.
</p>
<p>In the following table, let <tt->uN</tt-> denote <tt->N</tt->-bit unsigned integer operands,
and <tt->×N</tt-> denote the amount of operands that are processed in parallel.
</p>
<style>
  #optable {
    margin-left: auto;
    margin-right: auto;
  }
</style>

<table id=optable>
<tr>
  <th>Operation</th><th>x86_64</th><th>ARM</th><th>RV64</th>
</tr>

<tr>
  <td><tt->clmul u64×4 → u128×4</tt-></td>
  <td><tt->vpclmulqdq</tt-><sup>VPCLMULQDQ</sup></td>
  <td></td>
  <td></td>
</tr>

<tr>
  <td><tt->clmul u64×2 → u128×2</tt-></td>
  <td><tt->vpclmulqdq</tt-><sup>VPCLMULQDQ</sup></td>
  <td></td>
  <td></td>
</tr>

<tr>
  <td><tt->clmul u64 → u128</tt-></td>
  <td><tt->pclmulqdq</tt-><sup>PCLMULQDQ</sup></td>
  <td><tt->pmull</tt->+<tt->pmull2</tt-><sup>Neon</sup></td>
  <td><tt->clmul</tt->+<tt->clmulh</tt-><sup>Zbc, Zbkc</sup></td>
</tr>

<tr>
  <td><tt->clmul u64 → u128</tt-></td>
  <td><tt->pclmulqdq</tt-><sup>PCLMULQDQ</sup></td>
  <td><tt->pmull</tt->+<tt->pmull2</tt-><sup>Neon</sup></td>
  <td><tt->clmul</tt->+<tt->clmulh</tt-><sup>Zbc, Zbkc</sup></td>
</tr>

<tr>
  <td><tt->clmul u64 → u64</tt-></td>
  <td></td>
  <td><tt->pmull</tt-><sup>Neon</sup></td>
  <td><tt->clmul</tt-><sup>Zbc, Zbkc</sup></td>
</tr>

<tr>
  <td><tt->clmul u8×8 → u16×8</tt-></td>
  <td></td>
  <td><tt->pmull</tt-><sup>Neon</sup></td>
  <td></td>
</tr>
<tr>
  <td><tt->clmul u8×8 → u8×8</tt-></td>
  <td></td>
  <td><tt->pmul</tt-><sup>Neon</sup></td>
  <td></td>
</tr>

</table>

<example-block><p><intro-></intro-> 
A limited x86_64 implementation of <code><h- data-h=id>clmul_wide</h-></code> may look as follows:
</p>
<code-block><h- data-h=mac>#include &lt;immintrin.h&gt;</h->
<h- data-h=mac>#include &lt;cstdint&gt;</h->

<h- data-h=id>wide_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id_type>uint64_t</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>clmul_wide</h-><h- data-h=sym_par>(</h-><h- data-h=id_type>uint64_t</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=id_type>uint64_t</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-> <h- data-h=sym_brac>{</h->
  <h- data-h=kw_type>__m128i</h-> <h- data-h=id>x_128</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>_mm_set_epi64x</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  <h- data-h=kw_type>__m128i</h-> <h- data-h=id>y_128</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>_mm_set_epi64x</h-><h- data-h=sym_par>(</h-><h- data-h=num>0</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>__m128i</h-> <h- data-h=id>result_128</h-> <h- data-h=sym_op>=</h-> <h- data-h=id>_mm_clmulepi64_si128</h-><h- data-h=sym_par>(</h-><h- data-h=id>x_128</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y_128</h-><h- data-h=sym_punc>,</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=sym_brac>{</h->
    <h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h->  <h- data-h=sym_op>=</h-> <h- data-h=id_type>uint64_t</h-><h- data-h=sym_par>(</h-><h- data-h=id>_mm_extract_epi64</h-><h- data-h=sym_par>(</h-><h- data-h=id>result_128</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>0</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>,</h->
    <h- data-h=sym_op>.</h-><h- data-h=id>high_bits</h-> <h- data-h=sym_op>=</h-> <h- data-h=id_type>uint64_t</h-><h- data-h=sym_par>(</h-><h- data-h=id>_mm_extract_epi64</h-><h- data-h=sym_par>(</h-><h- data-h=id>result_128</h-><h- data-h=sym_punc>,</h-> <h- data-h=num>1</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-></code-block>
</example-block>

<p>There also exists an LLVM pull request (<a href="https://github%2ecom/llvm/llvm-project/pull/140301">[LLVMClmul]</a>)
which would add an <tt->@llvm.clmul</tt-> intrinsic function.
</p>

<h2 id=design-considerations><a class=para href=#design-considerations></a>5. Design considerations</h2>

<p>Multiple design choices lean on <a href="https://wg21%2elink/p0543r3">[P0543R3]</a> and <a href="https://wg21%2elink/p3161r4">[P3161R4]</a>.
Specifically,
</p>
<ul>
<li>the choice of header <code><h- data-h=str>&lt;numeric&gt;</h-></code>,</li>
<li>the choice to have a widening operation,</li>
<li>the <code><h- data-h=id>_wide</h-></code> naming scheme,</li>
<li>the <code><h- data-h=id>wide_result</h-></code> template, and</li>
<li>the decision to have a <code><h- data-h=sym_par>(</h-><h- data-h=id>T</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>T</h-><h- data-h=sym_par>)</h-></code> parameter list.</li>
</ul>

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

<p>Carry-less multiplication is also commonly called "Galois Field Multiplication" or "Polynomial Multiplication".
</p>
<p>The name <code><h- data-h=id>clmul</h-></code> was chosen because it carries no domain-specific connotation,
and because it is widespread:
</p>
<ul>
<li>
Intel refers to <code><h- data-h=id>PCLMULQDQ</h-></code> As "Carry-Less Multiplication Quadword" in its manual;
see <a href="https://software%2eintel%2ecom/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4">[IntelManual]</a>.
</li>
<li>
RISC-V refers to <code><h- data-h=id>clmul</h-></code> as carry-less multiplication,
and this is obvious from the mnemonic.
</li>
<li>
The Wikipedia article (<a href="https://en%2ewikipedia%2eorg/wiki/Carry-less_product">[WikipediaClmul]</a>) for this operation is titled "Carry-less product".
</li>
<li>
The (proposed) LLVM intrinsic function (<a href="https://github%2ecom/llvm/llvm-project/pull/140301">[LLVMClmul]</a>) is tentatively named <tt->@llvm.clmul</tt->.
</li>
</ul>

<h3 id=widening><a class=para href=#widening></a>5.2. Widening operation</h3>

<p>In addition to the <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-></code> function template,
there exists a <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul_wide</h-></code> function template:
</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>wide_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>low_bits</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>high_bits</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h->
      <h- data-h=kw>operator</h-><h- data-h=sym_op>==</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>wide_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>wide_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=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>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->
    <h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h->
    <h- data-h=sym_op>-&gt;</h-> <h- data-h=kw>decltype</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_brac>{</h->
      <h- data-h=kw_ctrl>return</h-> <h- data-h=id>tie</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>high_bits</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>tie</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>high_bits</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
    <h- data-h=sym_brac>}</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>wide_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>clmul_wide</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-></code-block>

<p>Such a widening function is important in a various cryptographic use cases.
There is universal <a href=#hardware-support>§4.1. Hardware support</a> for obtaining all 128 bits
of a multiplication for that reason.
</p>
<p>Most of the design choices take the design of <a href="https://wg21%2elink/p3161r4">[P3161R4]</a> into consideration:
</p>
<ul>
  <li>
    The result type is deliberately not named <code><h- data-h=id>clmul_wide_result</h-></code>
    so that future <code><h- data-h=id>mul_wide</h-></code> and other operations can use the same result type,
    which avoids creating an ever-growing set of equivalent (but distinct) types.
  </li>
  <li>
    The <code><h- data-h=id>low_bits</h-></code> appear before the <code><h- data-h=id>high_bits</h-></code>,
    so that on the more widespread little-endian architectures,
    the layout of the <code><h- data-h=kw>struct</h-></code> is identical to that of an integer,
    which is slightly better for calling conventions.
  </li>
</ul>

<p>However, the comparison operators are a novel invention of this proposal.
They are intended to behave as if the comparisons were performed on an
integer with twice the width of <code><h- data-h=id>T</h-></code>.
These comparisons exists so that the result can be easily compared
against expected results in test cases,
stored in containers like <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>set</h-></code>,
used out of the box with <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>sort</h-></code>, etc.
</p>
<p>Also, <code><h- data-h=id>wide_result</h-></code> should be a broadly useful vocabulary type
which may be instantiated with user-defined numeric types,
simply because that seems like a useful side product of this proposal.
</p>
<note-block><p><intro-></intro-> 
<code><h- data-h=kw>operator</h-><h- data-h=sym_op>&lt;=&gt;</h-></code> cannot be a hidden friend because
<code><h- data-h=id>wide_result</h-></code> is meant to compile even when given a type
that has no <code><h- data-h=sym_op>&lt;=&gt;</h-></code> operator.
</p></note-block>

<note-block><p><intro-></intro-> 
It would not be possible to simply return an integer with twice the
width of the input because it is not guaranteed that such a type exists,
especially in the case of <code><h- data-h=kw_type>unsigned</h-> <h- data-h=kw_type>long</h-> <h- data-h=kw_type>long</h-></code> inputs.
</p></note-block>

<h3 id=simd><a class=para href=#simd></a>5.3. SIMD support</h3>

<p>Upon seeing this proposal at Sofia 2025,
SG6 recommended to add SIMD support.
This recommendation was provided under the assumption that it would be
a simple addition in the style of <a href="https://wg21%2elink/p2933r4">[P2933R4]</a>.
Therefore, this proposal provides non-widening SIMD carry-less multiplication
with the following signature:
</p>
<code-block><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>simd-type</h-></i> <h- data-h=id>V</h-><h- data-h=sym_op>&gt;</h->
  <h- data-h=kw>constexpr</h-> <h- data-h=id>V</h-> <h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>V</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>v</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h-></code-block>

<h4 id=simd-widening-operations-are-out-of-scope><a class=para href=#simd-widening-operations-are-out-of-scope></a>5.3.1. SIMD widening operations are out of scope</h4>

<p>AVX-512 provides a <tt->u64×4 → u128×4</tt-> operation,
and there is currently no precedent for such widening operations in the SIMD library.
Specifically, the <tt->VPCLMULQDQ</tt-> instruction ignores
one of each <tt->u64×2</tt-> pairs,
and produces a 128-bit output for each such pair.
</p>
<p>It would take <em>considerable</em> design and wording effort to standardize this,
especially if one wants to expose the full <tt->VPCLMULQDQ</tt-> behavior,
which allows choosing for each <tt->u64×2</tt-> integer pair,
which of these integers is multiplied and which is ignored.
Procedurally, that design effort should be part of
<a href="https://wg21%2elink/p3161r4">[P3161R4]</a> (which proposes widening operations in general)
or some follow-up proposal for SIMD widening operations.
Some other SIMD instructions like <tt->PMULUDQ</tt-> perform multiple widening multiplications in parallel,
in the same style as <tt->VPCLMULQDQ</tt->,
while some others compute just the upper bits, like <tt->VPMULHUW</tt->.
This is a broad design space.
</p>
<p>In conclusion, a proposal for widening SIMD operations <em>in general</em> would be well-motivated.
For <code><h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>clmul</h-></code>, designing SIMD widening operations would be scope creep.
</p>
<h2 id=wording><a class=para href=#wording></a>6. Proposed wording</h2>

<p>The proposed changes are relative to <a href="https://wg21%2elink/N5008">[N5008]</a>
with the changes in <a href="https://wg21%2elink/p3691r1">[P3691R1]</a> applied.
</p>
<p>Change <a href=https://eel%2eis/c++draft/version%2esyn#2>[version.syn] paragraph 2</a> as follows:
</p>
<diff-block>
<code-block class=borderless>[…]
<ins><h- data-h=mac>#define __cpp_lib_clmul 20????L </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>also in &lt;numeric&gt;</h-></f-serif></ins>
[…]
<h- data-h=mac>#define __cpp_lib_simd </h-><del><h- data-h=mac>202506L</h-></del><h- data-h=mac> </h-><ins><h- data-h=mac>20????L</h-></ins><h- data-h=mac> </h-><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>also in &lt;simd&gt;</h-></f-serif></code-block>
</diff-block>

<note-block><p><intro-></intro-> 
We only bump <code><h- data-h=id>__cpp_lib_simd</h-></code> without creating a new SIMD
feature test macro because <a href="https://wg21%2elink/p2933r4">[P2933R4]</a> did the same,
and because <code><h- data-h=id>__cpp_lib_clmul</h-></code> can be used to test for the presence
of both the scalar and SIMD version.
</p></note-block>

<p>Add the following declarations to the synopsis in <a href=https://eel%2eis/c++draft/numeric%2eops%2eoverview>[numeric.ops.overview]</a>,
immediately following the declarations associated with <a href=https://eel%2eis/c++draft/numeric%2esat>[numeric.sat]</a>:
</p>
<ins-block>
<code-block class=borderless><h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>[numeric.clmul], carry-less product</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>wide_result</h-> <h- data-h=sym_brac>{</h->
    <h- data-h=id>T</h-> <h- data-h=id>low_bits</h-><h- data-h=sym_punc>;</h->
    <h- data-h=id>T</h-> <h- data-h=id>high_bits</h-><h- data-h=sym_punc>;</h->
    <h- data-h=kw>friend</h-> <h- data-h=kw>constexpr</h-> <h- data-h=kw_type>bool</h->
      <h- data-h=kw>operator</h-><h- data-h=sym_op>==</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>wide_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>wide_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=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>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->
    <h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h->
    <h- data-h=sym_op>-&gt;</h-> <h- data-h=kw>decltype</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</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>wide_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>clmul_wide</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>clmul</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-></code-block>
</ins-block>

<p>In subclause <a href=https://eel%2eis/c++draft/numeric%2eops>[numeric.ops]</a>,
append a subclause immediately following <a href=https://eel%2eis/c++draft/numeric%2esat>[numeric.sat]</a>:
</p>
<ins-block>
<h3>Carry-less product <span class=stable-ref>[numeric.clmul]</span></h3>


<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=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>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>x</h-><h- data-h=sym_punc>,</h-> <h- data-h=kw>const</h-> <h- data-h=id>wide_result</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>y</h-><h- data-h=sym_par>)</h->
    <h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=kw>noexcept</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-><h- data-h=sym_par>)</h->
    <h- data-h=sym_op>-&gt;</h-> <h- data-h=kw>decltype</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>1
<i>Returns</i>:
<code><h- data-h=id>tie</h-><h- data-h=sym_par>(</h-><h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>high_bits</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>x</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-> <h- data-h=sym_op>&lt;=&gt;</h-> <h- data-h=id>tie</h-><h- data-h=sym_par>(</h-><h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>high_bits</h-><h- data-h=sym_punc>,</h-> <h- data-h=id>y</h-><h- data-h=sym_op>.</h-><h- data-h=id>low_bits</h-><h- data-h=sym_par>)</h-></code>.
</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>wide_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>clmul_wide</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-></code-block>
<div class=indent>


<p>2
Let:
</p><ul>
  <li>
    <math display=inline><mo>⨁</mo></math> be
    a reduction using the exclusive OR operation (<a href=https://eel%2eis/c++draft/expr%2exor>[expr.xor]</a>);
  </li>
  <li>
    <math display=inline><msub><mi>α</mi><mi>i</mi></msub></math> be
    the <math display=inline><msup><mi>i</mi><mtext>th</mtext></msup></math> least significant bit
    in the base-2 representation of an integer <math display=inline><mi>α</mi></math>;
  </li>
  <li><math display=inline><mi>N</mi></math> be the width of <code><h- data-h=id>T</h-></code>.</li>
</ul>

<p>3
<i>Constraints</i>:
<code><h- data-h=id>T</h-></code> is an unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).
</p>
<p>4
<i>Returns</i>:
A <code><h- data-h=id>wide_result</h-><h- data-h=sym_op>&lt;</h-><h- data-h=id>T</h-><h- data-h=sym_op>&gt;</h-></code> object storing the bits of an integer <math display=inline><mi>c</mi></math>,
where the value of <math display=inline><msub><mi>c</mi><mi>i</mi></msub></math>
is given by Formula <tt->?.?</tt->,
<math display=inline><mi>x</mi></math> is <code><h- data-h=id>x</h-></code>, and
<math display=inline><mi>y</mi></math> is <code><h- data-h=id>y</h-></code>.
The result object is initialized so that
</p><ul>
  <li><code><h- data-h=id>low_bits</h-></code> stores the <math display=inline><mi>N</mi></math> least significant bits of <math display=inline><mi>c</mi></math>, and</li>
  <li><code><h- data-h=id>high_bits</h-></code> stores the subsequent <math display=inline><mi>N</mi></math> bits of <math display=inline><mi>c</mi></math>.</li>
</ul>

<style>
  math[display=block] {
      margin-left: auto;
      margin-right: auto;
      font-size: 125%;
  }

  .formula-container {
      position: relative;
      width: 100%;
  }

  .formula-number {
      position: absolute;
      right: 0;
      vertical-align: middle;
      top: 50%;
      transform: translate(0, -50%);
  }
</style>

<div class=formula-container>
  <span class=formula-number>[FORMULA ?.?]</span>
  <math display=block>
    <mrow>
      <msub>
        <mi>c</mi>
        <mi>i</mi>
      </msub>
      <mo>=</mo>
      <munderover>
        <mo>⨁</mo>
        <mrow><mi>j</mi><mo>=</mo><mn>0</mn></mrow>
        <mi>i</mi>
      </munderover>
      <msub><mi>x</mi><mi>j</mi></msub>
      <msub>
        <mi>y</mi>
        <mrow>
          <mi>i</mi><mo>−</mo><mi>j</mi>
        </mrow>
      </msub>
    </mrow>
  </math>
</div>

</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>clmul</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-></code-block>
<div class=indent>
<p>5
<i>Effects</i>:
Equivalent to <code><h- data-h=id>clmul_wide</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>low_bits</h-></code>.
</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>

<note-block><p><intro-></intro-> 
The formula is taken from <a href="https://www%2eintel%2ecom/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20%2epdf">[IntelClmul]</a>, with different variable names,
and with no special case for the upper <math display=inline><mi>N</mi></math> bits;
we can simply treat the integers as mathematical integers with
<math display=inline><mrow><mn>2</mn><mi>N</mi></mrow></math> width.
</p>
<p>See <a href=https://eel%2eis/c++draft/iterator%2econcept%2ewine>[iterator.concept.wine]</a>
for precedent on using <math display=inline><mi>N</mi></math> to denote the width of a type.
</p>
<p>See <a href=https://eel%2eis/c++draft/sf%2ecmath%2eriemann%2ezeta>[sf.cmath.riemann.zeta]</a>
for precedent on wording which includes formulae.
</p></note-block>

<note-block><p><intro-></intro-> 
The formula above in TeX notation is:
</p><code-block>c<h- data-h=sym_op>_</h->i = <h- data-h=mk_tag>\bigoplus</h-><h- data-h=sym_op>_</h-><h- data-h=sym_brac>{</h->j = 0<h- data-h=sym_brac>}</h-><h- data-h=sym_op>^</h->i x<h- data-h=sym_op>_</h->i y<h- data-h=sym_op>_</h-><h- data-h=sym_brac>{</h->i - j<h- data-h=sym_brac>}</h-></code-block>
</note-block>

<p>Add the following declarations to the synopsis in <a href=https://eel%2eis/c++draft/simd%2esyn>[simd.syn]</a>:
</p>
<diff-block>
<code-block class=borderless><h- data-h=kw>namespace</h-> <h- data-h=id>std</h-><h- data-h=sym_op>::</h-><h- data-h=id>simd</h-> <h- data-h=sym_brac>{</h->
  […]

<ins>  <h- data-h=cmt_dlim>//</h-><h- data-h=cmt> </h-><f-serif><h- data-h=cmt>[simd.clmul], Carry-less product</h-></f-serif>
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>simd-type</h-></i> <h- data-h=id>V</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw>constexpr</h-> <h- data-h=id>V</h-> <h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>V</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>v</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>[simd.math], Mathematical functions</h-></f-serif>
  <h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>math-floating-point</h-></i> <h- data-h=id>V</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw>constexpr</h-> <i><h- data-h=id>deduced-simd-t</h-></i><h- data-h=sym_op>&lt;</h-><h- data-h=id>V</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=id>acos</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>V</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>x</h-><h- data-h=sym_par>)</h-><h- data-h=sym_punc>;</h->
  […]
<h- data-h=sym_brac>}</h-></code-block>
</diff-block>

<p>In subclause <a href=https://eel%2eis/c++draft/simd>[simd]</a>,
append a subclause immediately preceding <a href=https://eel%2eis/c++draft/simd%2emath>[simd.math]</a>:
</p>
<ins-block>
<h3><code><h- data-h=id>basic_vec</h-></code> carry-less product <span class=stable-ref>[simd.clmul]</span></h3>


<code-block class=borderless><h- data-h=kw>template</h-><h- data-h=sym_op>&lt;</h-><i><h- data-h=id>simd-type</h-></i> <h- data-h=id>V</h-><h- data-h=sym_op>&gt;</h-> <h- data-h=kw>constexpr</h-> <h- data-h=id>V</h-> <h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=kw>const</h-> <h- data-h=id>V</h-><h- data-h=sym_op>&amp;</h-> <h- data-h=id>v</h-><h- data-h=sym_par>)</h-> <h- data-h=kw>noexcept</h-><h- data-h=sym_punc>;</h-></code-block>

<div class=indent>
<p>1
<i>Constraints</i>:
The type <code><h- data-h=id>V</h-><h- data-h=sym_op>::</h-><h- data-h=id>value_type</h-></code> is an unsigned integer type (<a href=https://eel%2eis/c++draft/basic%2efundamental>[basic.fundamental]</a>).
</p>
<p>2
<i>Returns</i>:
A <code><h- data-h=id>basic_vec</h-></code> object where the <math display=inline><msup><mi>i</mi><mtext>th</mtext></msup></math> element is initialized
to the result of <code><h- data-h=id>clmul</h-><h- data-h=sym_par>(</h-><h- data-h=id>v</h-><h- data-h=sym_sqr>[</h-><math display=inline><mi>i</mi></math><h- data-h=sym_sqr>]</h-><h- data-h=sym_par>)</h-></code> (<a href=https://eel%2eis/c++draft/numeric%2eclmul>[numeric.clmul]</a>)
for all <math display=inline><mi>i</mi></math> in the range [<code><h- data-h=num>0</h-></code>, <code><h- data-h=id>V</h-><h- data-h=sym_op>::</h-><h- data-h=id>size</h-><h- data-h=sym_par>(</h-><h- data-h=sym_par>)</h-></code>).
</p></div>
</ins-block>

<h2 id=references><a class=para href=#references></a>7. 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-P0543R3 class=bib-item>
<a href="https://wg21%2elink/p0543r3">[P0543R3]</a>
<span class=bib-author>Jens Maurer.</span>
<span class=bib-title>Saturation arithmetic</span>
<span class=bib-date>2023-07-19</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2023/p0543r3%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0543r3.html</a></div><div id=bib-item-P3104R3 class=bib-item>
<a href="https://wg21%2elink/p3104r3">[P3104R3]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>Bit permutations</span>
<span class=bib-date>2025-02-11</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p3104r3%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3104r3.html</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-P2933R4 class=bib-item>
<a href="https://wg21%2elink/p2933r4">[P2933R4]</a>
<span class=bib-author>Daniel Towner, Ruslan Arutyunyan.</span>
<span class=bib-title>Extend &lt;bit&gt; header function with overloads for std::simd</span>
<span class=bib-date>2025-02-13</span>
<a href="https://www%2eopen-std%2eorg/jtc1/sc22/wg21/docs/papers/2025/p2933r4%2ehtml" class=bib-link>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2933r4.html</a></div><div id=bib-item-P3691R1 class=bib-item>
<a href="https://wg21%2elink/p3691r1">[P3691R1]</a>
<span class=bib-author>Matthias Kretz et al..</span>
<span class=bib-title>Reconsider naming of the namespace for "std::simd"</span>
<span class=bib-date>2025-06-17</span>
<a href="https://wg21%2elink/p3691r1" class=bib-link>https://wg21.link/p3691r1</a></div><div id=bib-item-BitPermutations class=bib-item>
<a href="https://github%2ecom/Eisenwave/cxx26-bit-permutations">[BitPermutations]</a>
<span class=bib-author>Jan Schultke.</span>
<span class=bib-title>C++26 Bit permutations reference implementation</span>
<a href="https://github%2ecom/Eisenwave/cxx26-bit-permutations" class=bib-link>https://github.com/Eisenwave/cxx26-bit-permutations</a></div><div id=bib-item-SimdJsonClmul class=bib-item>
<a href="https://branchfree%2eorg/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/">[SimdJsonClmul]</a>
<span class=bib-author>Geoff Langdale.</span>
<span class=bib-title>Code Fragment: Finding quote pairs with carry-less multiply (PCLMULQD)</span>
<span class=bib-date>2019-03-06</span>
<a href="https://branchfree%2eorg/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/" class=bib-link>https://branchfree.org/2019/03/06/code-fragment-finding-quote-pairs-with-carry-less-multiply-pclmulqdq/</a></div><div id=bib-item-IntelClmul class=bib-item>
<a href="https://www%2eintel%2ecom/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20%2epdf">[IntelClmul]</a>
<span class=bib-author>Shay Gueron, Michael E. Kounavis.</span>
<span class=bib-title>Intel® Carry-Less Multiplication Instruction and its Usage for Computing the GCM Mode</span>
<a href="https://www%2eintel%2ecom/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20%2epdf" class=bib-link>https://www.intel.com/content/dam/develop/external/us/en/documents/clmul-wp-rev-2-02-2014-04-20.pdf</a></div><div id=bib-item-IntelManual class=bib-item>
<a href="https://software%2eintel%2ecom/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4">[IntelManual]</a>
<span class=bib-author>Intel Corporation.</span>
<span class=bib-title>Intel® 64 and IA-32 Architectures Software Developer's Manual</span>
<a href="https://software%2eintel%2ecom/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4" class=bib-link>https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4</a></div><div id=bib-item-HackersDelight class=bib-item>
<a href="https://doc%2elagout%2eorg/security/Hackers'Delight%2epdf">[HackersDelight]</a>
<span class=bib-author>Henry S. Warren.</span>
<span class=bib-title>Hacker's Delight, Second Edition</span>
<a href="https://doc%2elagout%2eorg/security/Hackers'Delight%2epdf" class=bib-link>https://doc.lagout.org/security/Hackers'Delight.pdf</a></div><div id=bib-item-FastHilbertCurves class=bib-item>
<a href="%22http://threadlocalmutex%2ecom/?p=188">[FastHilbertCurves]</a>
<span class=bib-author>rawrunprotected.</span>
<span class=bib-title>2D Hilbert curves in O(1)</span>
<a href="%22http://threadlocalmutex%2ecom/?p=188" class=bib-link>"http://threadlocalmutex.com/?p=188</a></div><div id=bib-item-WikipediaClmul class=bib-item>
<a href="https://en%2ewikipedia%2eorg/wiki/Carry-less_product">[WikipediaClmul]</a>
<span class=bib-author>Wikipedia community.</span>
<span class=bib-title>Carry-less product</span>
<a href="https://en%2ewikipedia%2eorg/wiki/Carry-less_product" class=bib-link>https://en.wikipedia.org/wiki/Carry-less_product</a></div><div id=bib-item-LLVMClmul class=bib-item>
<a href="https://github%2ecom/llvm/llvm-project/pull/140301">[LLVMClmul]</a>
<span class=bib-author>Oscar Smith.</span>
<span class=bib-title>[IR] Add llvm clmul intrinsic</span>
<a href="https://github%2ecom/llvm/llvm-project/pull/140301" class=bib-link>https://github.com/llvm/llvm-project/pull/140301</a></div></div>
</main></body>
</html>
