diff --git a/papers/n4972.html b/papers/n4972.html new file mode 100644 index 0000000000..61df993043 --- /dev/null +++ b/papers/n4972.html @@ -0,0 +1,846 @@ + + + + + +N4972 + + +

N4972 Editors’ Report:
Programming Languages — C++

+ +

Date: 2023-12-18

+ +

Thomas Köppe (editor, Google DeepMind)
+Jens Maurer (co-editor)
+Dawn Perchik (co-editor, Bright Side Computing, LLC)
+Richard Smith (co-editor, Google Inc)

+ +

Email: cxxeditor@gmail.com

+ +

Acknowledgements

+ +

Thanks to all those who have submitted editorial +issues +and to those who have provided pull requests with fixes, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications.

+ +

New papers

+ + + +

Motions incorporated into working draft

+ +

Notes on motions

+ +

All motions were applied cleanly, and the following additional changes applied +for the sake of integration:

+ + + +

The feature test macro __cpp_lib_span has been modified both LWG Poll 3 and +LWG Poll 10, and is now set to a common, updated value (202311L).

+ +

The linear algebra paper P1673R13 moved by LWG Poll 19 adds a substantial amount +of material, and numerous minor issues were discovered during application, many +of which have been fixed immediately, and some will be addressed in future +editorial work. One particular issue, which is not new and also affects the +random number and special maths functions, is how to relate variables in code +and mathematical variables in a mathematical expression.

+ +

Core working group polls

+ +

CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues in +P3046R0 +(Core Language Working Group "ready" Issues for the November, 2023 meeting) to the C++ Working Paper.

+ +

CWG Poll 2: Accept as a Defect Report and apply the changes in +P2308R1 +(Template parameter initialization) to the C++ Working Paper.

+ +

CWG Poll 3: Apply the changes in +P2662R3 +(Pack Indexing) to the C++ Working Paper.

+ +

CWG Poll 4: Apply the changes in +P2864R2 +(Remove Deprecated Arithmetic Conversion on Enumerations From C++26) to the C++ Working Paper.

+ +

CWG Poll 5 was withdrawn.

+ +

Library working group polls

+ +

LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +P3040R0 +(C++ Standard Library Issues to be moved in Kona, Nov. 2023) to the C++ working paper.

+ +

LWG Poll 2: Apply the changes in +P0543R3 +(Saturation arithmetic) to the C++ working paper.

+ +

LWG Poll 3: Apply the changes in +P2407R5 +(Freestanding Library: Partial Classes) to the C++ working paper.

+ +

LWG Poll 4: Apply the changes in +P2546R5 +(Debugging Support) to the C++ working paper.

+ +

LWG Poll 5: Accept as a Defect Report and apply the changes in +P2905R2 +(Runtime format strings) to the C++ working paper.

+ +

LWG Poll 6: Apply the changes in +P2918R2 +(Runtime format strings II) to the C++ working paper.

+ +

LWG Poll 7: Accept as a Defect Report and apply the changes in +P2909R4 +(Fix formatting of code units as integers (Dude, where's my char?)) to the C++ working paper.

+ +

LWG Poll 8: Apply the changes in +P0952R2 +(A new specification for std::generate_canonical) to the C++ working paper.

+ +

LWG Poll 9: Apply the changes in +P2447R6 +(std::span over an initializer list) to the C++ working paper.

+ +

LWG Poll 10: Apply the changes in +P2821R5 +(span.at()) to the C++ working paper.

+ +

LWG Poll 11: Apply the changes in +P2868R3 +(Remove Deprecated std::allocator Typedef From C++26) to the C++ working paper.

+ +

LWG Poll 12: Apply the changes in +P2870R3 +(Remove basic_string::reserve() From C++26) to the C++ working paper.

+ +

LWG Poll 13: Apply the changes in +P2871R3 +(Remove Deprecated Unicode Conversion Facets from C++26) to the C++ working paper.

+ +

LWG Poll 14: Apply the changes in +P2819R2 +(Add tuple protocol to complex) to the C++ working paper.

+ +

LWG Poll 15: Apply the changes in +P2937R0 +(Freestanding: Remove strtok) to the C++ working paper.

+ +

LWG Poll 16: Apply the changes in +P2833R2 +(Freestanding Library: inout expected span) to the C++ working paper.

+ +

LWG Poll 17: Accept as a Defect Report and apply the changes in +P2836R1 +(std::basic_const_iterator should follow its underlying type's convertibility) to the C++ working paper.

+ +

LWG Poll 18: Apply the changes in +P2264R7 +(Make assert() macro user friendly for C and C++) to the C++ working paper.

+ +

LWG Poll 19: Apply the changes in +P1673R13 +(A free function linear algebra interface based on the BLAS) to the C++ working paper.

+ +

Comments on the Draft International Standard

+ +

This report includes our final dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial.

+ + + +

Editorial changes

+ +

Major editorial changes

+ +

A number of editorial changes were made in response to requests from the ISO +secretariat during the publication of C++23. We list just a few noteworthy ones.

+ + + +

Minor editorial changes

+ +

A log of editorial fixes made to the working draft since N4964 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +draft sources on GitHub.

+ +
commit a27ede64fef7fda551d480e5a1cf1b9a73832574
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Tue Oct 24 20:55:27 2023 +0800
+
+    [span.cons] Add `std::` for `data(arr)` (#6632)
+
+commit 84c526ebbda74553bf935f35f5594b8d5591bce5
+Author: Casey Carter <Casey@Carter.net>
+Date:   Mon Oct 30 14:22:57 2023 -0700
+
+    [format.formatter.spec] Add missing include to example (#6636)
+
+    The example code refers to `std::string` directly so it should `#include<string>`.
+
+commit 4a6f2e3f4791c44b8c8f32a75d0bebac4a7b6a9e
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Nov 2 00:53:04 2023 +0100
+
+    [intro.refs] Move nicknames for standards to relevant subclauses
+
+commit dc6eed02986d9c3c6827c710adb577ba0809f939
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 04:32:19 2023 -0500
+
+    [dcl.dcl, over.best.ics, temp.param, class.union.anon] Remove mentions of "storage class" (#3906)
+
+commit 17c09925b2423c596196d3f88a61ff7b4052ef7a
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 01:16:28 2023 -0500
+
+    [class.conv.fct] Fix reference to 'ref-qualifier-seq'
+
+commit 90720a35b0c3d65488d9dc9ecea682c271f43d52
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 30 09:34:01 2023 +0800
+
+    [queue.syn] Show `formatter` specializations in the synopsis
+
+commit e43aa89a4882f8080fb10c843cdb25c9740b65c7
+Author: A. Jiang <de34@live.cn>
+Date:   Mon Oct 30 09:36:24 2023 +0800
+
+    [stack.syn] Show the `formatter` specialization in the synopsis
+
+commit 80a8748fd401cfceee804bc96d2bfc518726d2e7
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Oct 12 18:24:21 2023 -0400
+
+    [class.copy.assign] Remove a superfluous note.
+
+    Alternatively we could have added the word "non-object"; or changed
+    it to say "An overloaded assignment operator must be a member function";
+    but it doesn't seem like it needs to be here at all.
+
+commit c9c69dc54052badeb9b80458027371438d886763
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Thu Oct 12 18:58:39 2023 -0400
+
+    [class.copy.assign] Add some missing "non-object"s
+
+commit 2b5fc2936f12f73e975dbb9f34d3790fe0aa708f
+Author: Matt Bentley <mattreecebentley@gmail.com>
+Date:   Wed Nov 8 14:56:22 2023 +1300
+
+    [sequence.reqmts] Remove misleading, oversimplified informative text
+
+commit 11334c71244a046f0c29b01dfd79b35f6fea8cc4
+Author: Eisenwave <me@eisenwave.net>
+Date:   Fri Sep 1 09:29:01 2023 +0200
+
+    [class.copy.elision] improve reference and replace informal term
+
+commit 4feefb62e0419bb52c678389163729959785d44a
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Nov 8 02:59:01 2023 +0100
+
+    [mem.res.pool.options] Change "field" to "member" (#6479)
+
+commit a700e3b87b00d2673b3cded0a61201d09dfc051a
+Author: S. B. Tam <cpplearner@outlook.com>
+Date:   Wed Nov 8 10:01:46 2023 +0800
+
+     [version.syn] Bump value of __cpp_lib_constexpr_complex (#6421)
+
+    P1383R2 "More constexpr for <cmath> and <complex>" modifies two headers;
+    both __cpp_lib_constexpr_cmath and __cpp_lib_constexpr_complex should be updated.
+
+    This aligns with existing practice in SD6.
+
+commit e9fb04e1c1e67bfb07bf3c61145b9d63a0f0adcf
+Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
+Date:   Tue Sep 27 15:36:08 2022 -0400
+
+    [dcl.enum] Enumerators don't have "initializers"
+
+commit bc3cb41a36dfff0d2358f4e294be9636590e680e
+Author: Krystian Stasiowski <sdkrystian@gmail.com>
+Date:   Tue Nov 7 21:08:15 2023 -0500
+
+    [dcl.name] Turn informative wording into note (#3964)
+
+commit 82b2ba6f6245e717cb002a9a836117a918aab36a
+Author: Patrick Johnston <gcupcakekid@gmail.com>
+Date:   Wed Nov 8 02:10:58 2023 +0000
+
+    [streambuf.general] Remove incorrect "abstract"
+
+    The referenced class template `basic_streambuf` is not abstract.
+
+commit bbaa4a497e03d944fc38279db4d8c47eed7831d9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Thu Oct 12 20:51:57 2023 +0200
+
+    [basic.lval] turn reference paragraph into note
+
+commit a03b8b70d6666b67d27c801b68d41683e987e929
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Thu Oct 5 15:27:29 2023 -0400
+
+    [temp.param] Introduce term to xref structural type
+
+    The current cross-references to [temp.param] appear confusing,
+    as the structural type definition is buried a couple of pages
+    below.  Also, this change looks clearer in the source.
+
+commit 71ee18ab8cd9efca0d8afa1f6e639cb02610a52b
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 7 16:18:40 2023 -1000
+
+    [basic.types.general] Introduce term to xref implicit-lifetime type (#6591)
+
+commit 21454c7ebf67a1a723b61c32901a842c684e6b94
+Author: Language Lawyer <language.lawyer@gmail.com>
+Date:   Wed Aug 23 01:35:22 2023 +0500
+
+    [intro.races] Make reading atomic objects nondeterministic
+
+commit df26017a6bfd74d794345ea9313eae1efacbf7c9
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Wed Nov 8 03:31:10 2023 +0100
+
+    [diff.dcl] Replace 'field initializers' with 'member initializers' (#6482)
+
+commit cc69fc0dd6b1a2fdc834bade578acb84cc7d2cfa
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Nov 8 10:54:52 2023 +0800
+
+    [intro.races] Remove inappropriate uses of "shall" (#6457)
+
+commit 60e280391a06b8d27f778a56310b0827109623aa
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Aug 31 00:19:24 2023 +0200
+
+    [cmath.syn] fix misaligned parameter lists
+
+commit 646bfb2a060e3c7f490f6c4672ee93a0cbaf6d0d
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 8 05:59:28 2023 -1000
+
+    [container.alloc.reqmts] Better xrefs for allocator-aware containers
+
+    There are now more allocator-aware containers in the standard
+    than when this subclause was first written, so ensure we have
+    call outs to all relevent subclauses.
+
+    The current wording for 'basic_stacktrace' also shows how
+    containers can properly call out the allocator-aware container
+    requirements, now that they have their own, titled subclause.
+
+commit 62e33ca8a0a55764227e6a67c1f554783ffefe40
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Thu Nov 9 00:01:38 2023 +0800
+
+    [time.zone.leap.overview] Fix example (#6383)
+
+commit 07ae51af31587ac533b1b39c95777ecb725dcab0
+Author: A. Jiang <de34@live.cn>
+Date:   Wed Jan 25 18:22:53 2023 +0800
+
+    [expr.prim.req.general] Correct the IFNDR example
+
+commit f3059744c84f561f8ead4c5d117bc1160c43b7e2
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 8 23:52:44 2023 +0000
+
+    [defns.character.container] Improve note to entry (#6644)
+
+commit 8b38857b22f6518a41e506e4c9b2e9a1792a0fbd
+Author: A. Jiang <de34@live.cn>
+Date:   Tue Oct 10 09:40:20 2023 +0800
+
+    [iterator.requirements.general] Clarify non-forward iterator
+
+commit fbb1a6ebbd1f78e644df2dbcb3ce31250410779e
+Author: onihusube <44743040+onihusube@users.noreply.github.com>
+Date:   Fri Nov 10 08:36:12 2023 +0900
+
+    [execpol.unseq] Fix missing \itemdescr (#5931)
+
+commit 10e2799f5d524dd941d424dfd08927c77a6b87f1
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Fri Feb 17 10:47:28 2023 -0500
+
+    [pairs.pair] Consistent wording for assignment
+
+    Apply a consistent pattern to how we specify assigning members in assignment operators.
+
+commit 78300aa38c23f1356dca8e786205e5aaf7769d01
+Author: Barry Revzin <barry.revzin@gmail.com>
+Date:   Thu Nov 9 14:45:17 2023 -1000
+
+    [class.compare] Don't introduce `V` for the return value (#6035)
+
+    In both cases, I'm not sure introducing `V` helps much - just requires name lookup for `V`. If we just say "the return value" in every case, I think that's clearer.
+
+commit 838cb0649b1f4061e960772aee3563cedb20b108
+Author: Michael Florian Hava <mfh@live.at>
+Date:   Thu Nov 9 13:51:58 2023 -1000
+
+    [basic.extended.fp] Replaced usage of 'mantissa' with 'significand'
+    according to SO/IEC/IEEE 60559:2008
+
+commit ce5ef1b5334f1fc756d40e40ec300257b0ff99d9
+Author: Michael Florian Hava <mfh@live.at>
+Date:   Thu Nov 9 13:57:32 2023 -1000
+
+    [numeric.limits.members] Replaced usage of 'mantissa' with 'significand' according to
+    SO/IEC/IEEE 60559:2008
+
+commit 3e1f377a9dc3bece7acd2dddb7237065504db65c
+Author: Brian Bi <bbi5291@gmail.com>
+Date:   Thu Nov 9 16:00:22 2023 -1000
+
+    [macros, styles] Add \hypertarget to headings (#6516)
+
+    This allows forming URLs with a stable label as a fragment and
+    have PDF viewers jump to the corresponding (sub)clause.
+
+    For example: std.pdf#basic.life
+
+commit 60f7bb72cdd36e9d359fa7aea84a5b836079a0ed
+Author: Eisenwave <me@eisenwave.net>
+Date:   Thu Jul 6 13:41:56 2023 +0200
+
+    [namespace.std] convert (a) and (b) notation to items
+
+commit f48f316c42c6cb67058d9f9106852154497b4516
+Author: Jan Schultke <me@eisenwave.net>
+Date:   Fri Nov 10 06:57:17 2023 +0100
+
+    [atomics.order] Use "recommended practice" (#6380)
+
+commit 1ec1d9e6fa98734b3edf20f6c2217a4482f78103
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Fri Nov 10 16:59:21 2023 +0800
+
+    [meta.{unary.prop.query,trans.arr] Use `static_assert` instead of `assert` in example
+
+commit bd8f4540720e52dab9187a62c5598e735aeacfdd
+Author: Eisenwave <me@eisenwave.net>
+Date:   Sat Aug 19 15:57:39 2023 +0200
+
+    [expr.sizeof] use constexpr member in example
+
+commit b1f922a126dcda78acb4bae055843e7a7321fe1d
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:42:39 2023 +0200
+
+    [basic.def.odr] Fix hyphenation of "{copy,move} assignment"
+
+commit 54e465a17adfcba56a57ff2fefe43ec898725efb
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:43:46 2023 +0200
+
+    [res.on.arguments] Fix hyphenation of "move assignment"
+
+commit 3c5b5b0c58d0440233d992e1a0791a449936f203
+Author: Eisenwave <me@eisenwave.net>
+Date:   Wed Aug 23 13:44:40 2023 +0200
+
+    [futures.{unique,shared}.future] Fix hyphenation of "{copy,move} assignment"
+
+commit 9483cb7cf6973689ad563d30778d8da2dff42a8d
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Nov 8 22:57:57 2023 +0000
+
+    [string.capacity] Remove parentheses from "reserve()"
+
+    It's very confusing to talk about `reserve()` when describing a call to
+    `reserve(size_type)`, given that the overload `reserve()` also exists.
+
+commit 2a9f28670a0df6e239d9b335bdb014f20f577732
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Mon Jul 24 16:19:01 2023 +0000
+
+    [dcl.meaning.general] Use 'declarator-id' instead of 'name'
+
+commit d8b72f0ceb36b3537ef576ab216d588642e332ab
+Author: lprv <100177227+lprv@users.noreply.github.com>
+Date:   Tue Jul 25 18:26:03 2023 +0000
+
+    [module.global.frag] Simplify wording
+
+    Also make variable order consistent across bullets.
+
+commit f0c172c5604b47c3ecc7b64669aad660df403624
+Author: Oliver Rosten <oliver.rosten@gmail.com>
+Date:   Fri Nov 10 18:12:06 2023 +0000
+
+    [algorithms] Change stable label "mismatch" to "alg.mismatch" (#6653)
+
+commit d97603a90d2fcfeec2caf4371ca9e6c8f562842a
+Author: A. Jiang <de34@live.cn>
+Date:   Sat Nov 11 03:21:17 2023 +0800
+
+    [forward.iterators] Use "Cpp17" requirement (#6612)
+
+commit f474227b69d10350999a5fc63503725421a89954
+Author: Geng Cheng <xmcgcg@qq.com>
+Date:   Sat Nov 11 10:25:39 2023 +0800
+
+    [stringstream.general] Add missing template argument "Allocator" (#6560)
+
+commit f5fdfe453e5a1e0370f2cb28bfc2dfeecab6370e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Wed Nov 8 15:12:16 2023 -1000
+
+    [diff.cpp20.library] Add missing new headers for C++23
+
+commit 38dfe3db0f08bd09a2b445ba82e83f7caae28d94
+Author: A. Jiang <de34@live.cn>
+Date:   Thu Nov 9 11:00:44 2023 +0800
+
+    [dcl.init.ref] Clarify "related type"
+
+    "Related type" is not a term, "reference-related type" is clearer.
+
+commit 979983929bb592c02c9ae3e52f1c676dd5ae06fe
+Author: Hewill Kang <67143766+hewillk@users.noreply.github.com>
+Date:   Tue Nov 14 02:27:01 2023 +0800
+
+    [range.cartesian.view] Don't name unused template parameter (#6177)
+
+commit ecbeb5ad4e4c0ac1d0cdb5e8dd01daab8df8d62e
+Author: Alisdair Meredith <alisdairm@me.com>
+Date:   Tue Nov 14 14:27:27 2023 -0500
+
+    [diff.cpp23.library] Entry for new headers in C++26 (#6648)
+
+commit eb7f0bcbff2af109643089ef36dfe67040a27f4a
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Nov 13 01:12:50 2023 -1000
+
+    [intro.defs, macros] Add cross-references among definitions
+
+    Fixes ISO/CS 017 (C++23 DIS).
+
+commit 706880e4ed855ae76d503c70adfb0015bbfb3df0
+Author: Lewis Baker <lewissbaker@users.noreply.github.com>
+Date:   Thu Nov 16 10:36:25 2023 +1030
+
+    [allocator.requirements.general] Fix missing ellipsis (#6695)
+
+commit 5c0103c0a656cbcd725780388b0879e992a1b21a
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Thu Nov 16 15:38:47 2023 +0000
+
+    [stacktrace.format], [stacktrace.basic.hash] change rSec3 to rSec2
+
+    These should not be nested below std::basic_stacktrace because they
+    apply to both std::stacktrace_entry and std::basic_stacktrace.
+
+commit a6ad6083ab75901cb41b5bc8d034c0b322433457
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Tue Dec 5 23:42:23 2023 +0000
+
+    [std, styles] Adjust table captions as per ISO request
+
+    ISO has asked for captions to be bold and table numbers to be
+    separated by a dash.
+
+commit f519ea4aa97592703ba5bbe9164242d946723721
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 7 01:00:53 2023 +0100
+
+    [intro.refs, time.format] Update references from ISO 8601:2004 to ISO 8601-1:2019 (#6720)
+
+commit 37956fb3685c2c279bd6b4b701964b20913d0c79
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Wed Dec 6 19:01:29 2023 +0000
+
+    [syntax] Change "italic" to "italic, sans-serif"
+
+    We changed the grammar non-terminal font to sans-serif,
+    so we should update the description.
+
+commit 4eed7a0f1e44c45554f8a210af34fd6e1ea19596
+Author: Jens Maurer <Jens.Maurer@gmx.net>
+Date:   Thu Dec 7 22:13:35 2023 +0100
+
+    [intro.abstract] Actually use the phrase 'unspecified/undefined behavior'
+
+    Fixes ISO/CS 011 (C++23 DIS).
+
+commit f8a6138da1e431779ac43a893faa32f3f0cad7d0
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Dec 7 12:45:11 2023 +0000
+
+    [intro.defs] Fix introductory text according to ISO rules.
+
+    In principle, "symbols and abbreviated terms" can be listed in a
+    standard, and can be listed in a separate clause or in a combined
+    clause 3 "Terms, definitions, symbols and abbreviated terms", we do
+    not actually need symbol definitions. In any case, the introductory
+    text would never mention "symbols".
+
+commit 9961cd4f16aca645c77d6927526ea71f635a2932
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Thu Dec 7 00:01:48 2023 +0000
+
+    [introduction] A minimal "Introduction" clause
+
+    This clause explains our conventions regarding stable labels and
+    choice of fonts.
+
+commit 9041b27206388fecd03073bb913185ac738c6dca
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Mon Dec 18 00:57:45 2023 +0000
+
+    [optional.monaic] Restore wording effected by LWG3973.
+
+    Both LWG3973 (Motion 1) and P2407R5 (Motion 3) modified this wording:
+    LWG3973 changes "value()" to "*val" to address ADL concerns, and
+    P2407R5 changed "value()" to "**this" to be freestanding. In light of
+    the former, the latter should also use "*val".
+
+    Independently, additional problems have been discovered with LWG3973,
+    but those will be addressed by a future LWG issue.
+
+commit 2b1867a3404562c4261722e0a913cbcbf5a0a476
+Author: Thomas Köppe <tkoeppe@google.com>
+Date:   Sun Dec 17 23:10:44 2023 +0000
+
+    [version.syn] New feature test macro __cpp_lib_freestanding_numeric
+
+    This macro indicates that freestanding support for "saturation
+    arithmetic" is available, which was added in motion LWG-2 (via
+    P0543R3). This reverts the previous change
+    148e03a16d53ff8cffd219384df37efad5fd386d, which I had made subsequent
+    to motion LWG-3 (P2407R5), on advice of LWG. A separate macro is
+    preferable to mixing both headers under "algorithm".
+
+commit fa54f9e7306b3d0abb21a82b5cc951711c96161f
+Author: Jonathan Wakely <cxx@kayari.org>
+Date:   Wed Dec 13 11:03:18 2023 +0000
+
+    [range.access.general] Use consistent "In addition to being available ..." form
+
+    Elsewhere we say "the header" or "any of the headers", e.g. [meta.trans.other],
+    [tuple.helper], etc.
+
+commit 8c611593555b93a45a13543ad265d8cfaf646932
+Author: Cassio Neri <cassio.neri@gmail.com>
+Date:   Mon Nov 27 19:47:29 2023 +0000
+
+    [expected.general] Fix description of expected<T, E> (issue #6714.)
+
+commit 12565ed5ea083761b25df3c8325989f95fa04898
+Author: Po-yao Chang <poyaoc97@gmail.com>
+Date:   Wed Nov 22 23:02:49 2023 +0800
+
+    [class.eq] Fix the return value of a defaulted == operator function
+
+ + diff --git a/papers/n4972.md b/papers/n4972.md new file mode 100644 index 0000000000..ed66878372 --- /dev/null +++ b/papers/n4972.md @@ -0,0 +1,699 @@ +# N4972 Editors' Report -- Programming Languages -- C++ + +Date: 2023-12-18 + +Thomas Köppe (editor, Google DeepMind) +Jens Maurer (co-editor) +Dawn Perchik (co-editor, Bright Side Computing, LLC) +Richard Smith (co-editor, Google Inc) + +Email: `cxxeditor@gmail.com` + +## Acknowledgements + +Thanks to all those who have [submitted editorial +issues](https://github.com/cplusplus/draft/wiki/How-to-submit-an-editorial-issue) +and to those who have provided pull requests with fixes, +and special thanks to Johel Ernesto Guerrero Peña for providing in-depth review +of many of the draft motion applications. + +## New papers + + * [N4971](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) is the + current working draft for C++26. It replaces + [N4964](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf). + * N4972 is this Editors' Report. + +## Motions incorporated into working draft + +### Notes on motions + +All motions were applied cleanly, and the following additional changes applied +for the sake of integration: + +* LWG Polls 1 and 3 both modified [optional.monadic]: + [LWG-3973](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3040r0.html#3973) + changed `**this` to `*val`, and + [P2407R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2407r5.html) + changed `value()` to `**this`. This has been reconciled by changing the + latter to `*val`, too. +* LWG Poll 2 created a freestanding facility (saturation arithmetic) but did + not define a freestanding feature test macro. We added the macro + `__cpp_lib_freestanding_numeric`, also defined in the `` header. + +The feature test macro `__cpp_lib_span` has been modified both LWG Poll 3 and +LWG Poll 10, and is now set to a common, updated value (`202311L`). + +The linear algebra paper P1673R13 moved by LWG Poll 19 adds a substantial amount +of material, and numerous minor issues were discovered during application, many +of which have been fixed immediately, and some will be addressed in future +editorial work. One particular issue, which is not new and also affects the +random number and special maths functions, is how to relate variables in code +and mathematical variables in a mathematical expression. + +### Core working group polls + +CWG Poll 1: Accept as a Defect Report and apply the proposed resolution of all issues in +[P3046R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3046r0.html) +(Core Language Working Group "ready" Issues for the November, 2023 meeting) to the C++ Working Paper. + +CWG Poll 2: Accept as a Defect Report and apply the changes in +[P2308R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2308r1.html) +(Template parameter initialization) to the C++ Working Paper. + +CWG Poll 3: Apply the changes in +[P2662R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2662r3.pdf) +(Pack Indexing) to the C++ Working Paper. + +CWG Poll 4: Apply the changes in +[P2864R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2864r2.pdf) +(Remove Deprecated Arithmetic Conversion on Enumerations From C++26) to the C++ Working Paper. + +CWG Poll 5 was withdrawn. + +### Library working group polls + +LWG Poll 1: Apply the changes for all Ready and Tentatively Ready issues in +[P3040R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p3040r0.html) +(C++ Standard Library Issues to be moved in Kona, Nov. 2023) to the C++ working paper. + +LWG Poll 2: Apply the changes in +[P0543R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0543r3.html) +(Saturation arithmetic) to the C++ working paper. + +LWG Poll 3: Apply the changes in +[P2407R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2407r5.html) +(Freestanding Library: Partial Classes) to the C++ working paper. + +LWG Poll 4: Apply the changes in +[P2546R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2546r5.html) +(Debugging Support) to the C++ working paper. + +LWG Poll 5: Accept as a Defect Report and apply the changes in +[P2905R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2905r2.html) +(Runtime format strings) to the C++ working paper. + +LWG Poll 6: Apply the changes in +[P2918R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2918r2.html) +(Runtime format strings II) to the C++ working paper. + +LWG Poll 7: Accept as a Defect Report and apply the changes in +[P2909R4](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2909r4.html) +(Fix formatting of code units as integers (Dude, where's my char?)) to the C++ working paper. + +LWG Poll 8: Apply the changes in +[P0952R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0952r2.html) +(A new specification for `std::generate_canonical`) to the C++ working paper. + +LWG Poll 9: Apply the changes in +[P2447R6](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2447r6.html) +(`std::span` over an initializer list) to the C++ working paper. + +LWG Poll 10: Apply the changes in +[P2821R5](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2821r5.html) +(`span.at()`) to the C++ working paper. + +LWG Poll 11: Apply the changes in +[P2868R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2868r3.pdf) +(Remove Deprecated `std::allocator` Typedef From C++26) to the C++ working paper. + +LWG Poll 12: Apply the changes in +[P2870R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2870r3.pdf) +(Remove `basic_string::reserve()` From C++26) to the C++ working paper. + +LWG Poll 13: Apply the changes in +[P2871R3](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2871r3.pdf) +(Remove Deprecated Unicode Conversion Facets from C++26) to the C++ working paper. + +LWG Poll 14: Apply the changes in +[P2819R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2819r2.pdf) +(Add tuple protocol to `complex`) to the C++ working paper. + +LWG Poll 15: Apply the changes in +[P2937R0](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2937r0.html) +(Freestanding: Remove `strtok`) to the C++ working paper. + +LWG Poll 16: Apply the changes in +[P2833R2](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2833r2.html) +(Freestanding Library: `inout` `expected` `span`) to the C++ working paper. + +LWG Poll 17: Accept as a Defect Report and apply the changes in +[P2836R1](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2836r1.html) +(`std::basic_const_iterator` should follow its underlying type's convertibility) to the C++ working paper. + +LWG Poll 18: Apply the changes in +[P2264R7](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2264r7.html) +(Make `assert()` macro user friendly for C and C++) to the C++ working paper. + +LWG Poll 19: Apply the changes in +[P1673R13](https://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1673r13.html) +(A free function linear algebra interface based on the BLAS) to the C++ working paper. + +## Comments on the Draft International Standard + +This report includes our final dispositions on the Draft International Standard (DIS) +ballot comments for C++23 from national bodies and the ISO secretariat. Some of them only apply +to the published standard document and not the working draft, and the corresponding edits do not +appear in the working draft commit history. All comments on the ballot were editorial. + +* **ISO/CS 01:** Accepted. We added references to the tables. +* **ISO/CS 02:** Accepted. We moved the explanations close to their point of use. +* **ISO/CS 03:** Accepted. We are now referring to a specific element, and keeping the dated reference. +* **ISO/CS 04:** Accepted. +* **ISO/CS 05:** Rejected: We do not understand the justification "Since there is no specific element referenced this reference shall be undated." The Drafting Directives seem to make a clear case for when undated (10.4) and dated (10.5) references are appropriate, and we firmly fall into the case where an undated reference is inappropriate ("if it will be possible to use all future changes of the referenced document" is definitely not the case). Reference to a specific element does not seem to be required in order to permit the use of a dated reference. Even the House Style seems to permit dated references when necessary: "When referring to the whole document, use an undated document number unless it is necessary that the user refers to a specific edition". +* **ISO/CS 06:** Rejected: Moot by comment 05. +* **ISO/CS 07:** Rejected: Moot by comment 05. +* **ISO/CS 08:** Accepted. We reworded the reference to the Unicode standard to make the normative nature more obvious. +* **ISO/CS 09:** Accepted. +* **ISO/CS 10:** Rejected: We find domains valuable here, since the terms often sound like plain English words, but have rather domain-specific meaning, and the domain establishes important context to aid understandability. +* **ISO/CS 11:** Accepted with modifications: four unused definitions are removed. The remaining term, "unspecified behavior" is retained, since it captures a variety of patterns which are not lexically spelled "behavior" but are neatly covered by this umbrella term. +* **ISO/CS 12:** Accepted with modifications: we have italicized the cross-references. However, for the formal grammar terms that we display in italic sans font, please see the discussion on comment 32. +* **ISO/CS 13:** Rejected: The token "CE" is not an acronym, but a meta variable (like "x" or "y". It is typeset distinctly. The name is evocative of its use. +* **ISO/CS 14:** Accepted. +* **ISO/CS 15:** Accepted. +* **ISO/CS 16:** Rejected: The wording is correct as written. However, this is also mooted by comment 11, which deletes the wording in question. +* **ISO/CS 17:** Accepted. +* **ISO/CS 18:** Accepted. +* **ISO/CS 19:** Accepted. +* **CA 20:** n/a, comment was filed erroneously +* **JP 21:** Accepted. We added an example. +* **JP 22:** Rejected: No consensus for change; any attributes of a lambda-declarator are considered to be attached to the synthesized function call operator or operator template (i.e. the member function of the closure type), not the closure type itself. +* **JP 23:** Accepted with modifications: The example is written as intended. The comments in the example have been amended to clarify the exposition. +* **JP 24:** Accepted. +* **JP 25:** Accepted. +* **JP 26:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 27:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **JP 28:** Rejected: No consensus for change; the example deliberately introduces a facility to aid comprehension. +* **ISO/CS 29:** Accepted. +* **ISO/CS 30:** Accepted. We added a note that refers to the annex. +* **ISO/CS 31:** Accepted. We had previously used foreword wording from an older document. +* **ISO/CS 32:** Rejected, along with comment 12: our document has complex typographic requirements, and we have carefully selected a harmonizing family of typefaces in our document processing system that meets our needs. For example, certain parts of a formal grammar (some of which appear in Clause 3; see comment 12) require typographic distinction to avoid ambiguity. We have discussed this with the ISO secretariat. +* **ISO/CS 33:** Rejected: We have an approved SC22 ballot to permit the use of paragraph numbers. (We also have a proposal for the JDMT to add such a permission to the Drafting Directives.) +* **ISO/CS 34:** Accepted. Reworded to clarify. +* **ISO/CS 35:** Accepted. +* **ISO/CS 36:** Accepted the notes and tables captioning changes. Rejected the UK English spelling: The document defines many terms that must be spelled the same way by conforming implementations and by users of those implementations, and these terms use US English spelling. It would be confusing for the document text to use UK English spelling when describing these terms. (This is the same disposition as for a similar comment on the DIS ballot of 14882:2017.) +* **ISO/CS 37:** Rejected, please see comment 39. +* **ISO/CS 38:** Accepted with modifications: We will review the presentation of cross-references in Clause 3. However, the use of italics in Clause 3 is not a regular "emphasis/definition" in body font, but rather a grammar production, which we typeset distinctly. Please also see the discussion regarding comment 32. +* **ISO/CS 39:** Rejected: For this comment and for comment 37, we have carefully reviewed the permitted verbal constructions. We believe that the notes are the best place for this explanatory, optional information, and the wording as-is accurately describes the consequences of normative requirements for illustrative purposes. We would like to not move this explanatory material into the main text, since that text already contains a complex range of requirements on the C++ language, its implementations, and its users, and our community has been finding our established boundary for what is explanatory note material helpful. +* **ISO/CS 40:** Accepted. The logic that processed the notes was erroneous and failed to handle subclauses with more than 9 notes; this has been fixed. + +## Editorial changes + +### Major editorial changes + +A number of editorial changes were made in response to requests from the ISO +secretariat during the publication of C++23. We list just a few noteworthy ones. + +* There is now a new "Introduction" subclause, which explains our use of + stable labels and some typographic choices. In the future, we would like to + expand the introduction to explain more comprehensively how the Standard is + structured, phrased, and intended to be read. +* Table captions are now formatted in bold, and the table number is separated + from the caption by a dash. +* Inadmissible text has been removed from Clauses 2 (Normative references) and + 3 (Terms and definitions), as those clauses must only contain specific, + fixed wording. The removed text has been moved nearer to the places in the + main text where it is needed. +* Definitions in Clause 3 (Terms and definitions) now contain cross references + to one another as appropriate. + +### Minor editorial changes + +A log of editorial fixes made to the working draft since N4964 is below. This +list excludes changes that do not affect the body text or only affect whitespace +or typeface. For a complete list including such changes (or for the actual +deltas applied by these changes), consult the +[draft sources on GitHub](https://github.com/cplusplus/draft/compare/n4964...n4971). + + commit a27ede64fef7fda551d480e5a1cf1b9a73832574 + Author: S. B. Tam + Date: Tue Oct 24 20:55:27 2023 +0800 + + [span.cons] Add `std::` for `data(arr)` (#6632) + + commit 84c526ebbda74553bf935f35f5594b8d5591bce5 + Author: Casey Carter + Date: Mon Oct 30 14:22:57 2023 -0700 + + [format.formatter.spec] Add missing include to example (#6636) + + The example code refers to `std::string` directly so it should `#include`. + + commit 4a6f2e3f4791c44b8c8f32a75d0bebac4a7b6a9e + Author: Jens Maurer + Date: Thu Nov 2 00:53:04 2023 +0100 + + [intro.refs] Move nicknames for standards to relevant subclauses + + commit dc6eed02986d9c3c6827c710adb577ba0809f939 + Author: Krystian Stasiowski + Date: Tue Nov 7 04:32:19 2023 -0500 + + [dcl.dcl, over.best.ics, temp.param, class.union.anon] Remove mentions of "storage class" (#3906) + + commit 17c09925b2423c596196d3f88a61ff7b4052ef7a + Author: Krystian Stasiowski + Date: Tue Nov 7 01:16:28 2023 -0500 + + [class.conv.fct] Fix reference to 'ref-qualifier-seq' + + commit 90720a35b0c3d65488d9dc9ecea682c271f43d52 + Author: A. Jiang + Date: Mon Oct 30 09:34:01 2023 +0800 + + [queue.syn] Show `formatter` specializations in the synopsis + + commit e43aa89a4882f8080fb10c843cdb25c9740b65c7 + Author: A. Jiang + Date: Mon Oct 30 09:36:24 2023 +0800 + + [stack.syn] Show the `formatter` specialization in the synopsis + + commit 80a8748fd401cfceee804bc96d2bfc518726d2e7 + Author: Arthur O'Dwyer + Date: Thu Oct 12 18:24:21 2023 -0400 + + [class.copy.assign] Remove a superfluous note. + + Alternatively we could have added the word "non-object"; or changed + it to say "An overloaded assignment operator must be a member function"; + but it doesn't seem like it needs to be here at all. + + commit c9c69dc54052badeb9b80458027371438d886763 + Author: Arthur O'Dwyer + Date: Thu Oct 12 18:58:39 2023 -0400 + + [class.copy.assign] Add some missing "non-object"s + + commit 2b5fc2936f12f73e975dbb9f34d3790fe0aa708f + Author: Matt Bentley + Date: Wed Nov 8 14:56:22 2023 +1300 + + [sequence.reqmts] Remove misleading, oversimplified informative text + + commit 11334c71244a046f0c29b01dfd79b35f6fea8cc4 + Author: Eisenwave + Date: Fri Sep 1 09:29:01 2023 +0200 + + [class.copy.elision] improve reference and replace informal term + + commit 4feefb62e0419bb52c678389163729959785d44a + Author: Jan Schultke + Date: Wed Nov 8 02:59:01 2023 +0100 + + [mem.res.pool.options] Change "field" to "member" (#6479) + + commit a700e3b87b00d2673b3cded0a61201d09dfc051a + Author: S. B. Tam + Date: Wed Nov 8 10:01:46 2023 +0800 + + [version.syn] Bump value of __cpp_lib_constexpr_complex (#6421) + + P1383R2 "More constexpr for and " modifies two headers; + both __cpp_lib_constexpr_cmath and __cpp_lib_constexpr_complex should be updated. + + This aligns with existing practice in SD6. + + commit e9fb04e1c1e67bfb07bf3c61145b9d63a0f0adcf + Author: Arthur O'Dwyer + Date: Tue Sep 27 15:36:08 2022 -0400 + + [dcl.enum] Enumerators don't have "initializers" + + commit bc3cb41a36dfff0d2358f4e294be9636590e680e + Author: Krystian Stasiowski + Date: Tue Nov 7 21:08:15 2023 -0500 + + [dcl.name] Turn informative wording into note (#3964) + + commit 82b2ba6f6245e717cb002a9a836117a918aab36a + Author: Patrick Johnston + Date: Wed Nov 8 02:10:58 2023 +0000 + + [streambuf.general] Remove incorrect "abstract" + + The referenced class template `basic_streambuf` is not abstract. + + commit bbaa4a497e03d944fc38279db4d8c47eed7831d9 + Author: Jan Schultke + Date: Thu Oct 12 20:51:57 2023 +0200 + + [basic.lval] turn reference paragraph into note + + commit a03b8b70d6666b67d27c801b68d41683e987e929 + Author: Alisdair Meredith + Date: Thu Oct 5 15:27:29 2023 -0400 + + [temp.param] Introduce term to xref structural type + + The current cross-references to [temp.param] appear confusing, + as the structural type definition is buried a couple of pages + below. Also, this change looks clearer in the source. + + commit 71ee18ab8cd9efca0d8afa1f6e639cb02610a52b + Author: Alisdair Meredith + Date: Tue Nov 7 16:18:40 2023 -1000 + + [basic.types.general] Introduce term to xref implicit-lifetime type (#6591) + + commit 21454c7ebf67a1a723b61c32901a842c684e6b94 + Author: Language Lawyer + Date: Wed Aug 23 01:35:22 2023 +0500 + + [intro.races] Make reading atomic objects nondeterministic + + commit df26017a6bfd74d794345ea9313eae1efacbf7c9 + Author: Jan Schultke + Date: Wed Nov 8 03:31:10 2023 +0100 + + [diff.dcl] Replace 'field initializers' with 'member initializers' (#6482) + + commit cc69fc0dd6b1a2fdc834bade578acb84cc7d2cfa + Author: A. Jiang + Date: Wed Nov 8 10:54:52 2023 +0800 + + [intro.races] Remove inappropriate uses of "shall" (#6457) + + commit 60e280391a06b8d27f778a56310b0827109623aa + Author: Eisenwave + Date: Thu Aug 31 00:19:24 2023 +0200 + + [cmath.syn] fix misaligned parameter lists + + commit 646bfb2a060e3c7f490f6c4672ee93a0cbaf6d0d + Author: Alisdair Meredith + Date: Wed Nov 8 05:59:28 2023 -1000 + + [container.alloc.reqmts] Better xrefs for allocator-aware containers + + There are now more allocator-aware containers in the standard + than when this subclause was first written, so ensure we have + call outs to all relevent subclauses. + + The current wording for 'basic_stacktrace' also shows how + containers can properly call out the allocator-aware container + requirements, now that they have their own, titled subclause. + + commit 62e33ca8a0a55764227e6a67c1f554783ffefe40 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Thu Nov 9 00:01:38 2023 +0800 + + [time.zone.leap.overview] Fix example (#6383) + + commit 07ae51af31587ac533b1b39c95777ecb725dcab0 + Author: A. Jiang + Date: Wed Jan 25 18:22:53 2023 +0800 + + [expr.prim.req.general] Correct the IFNDR example + + commit f3059744c84f561f8ead4c5d117bc1160c43b7e2 + Author: Jonathan Wakely + Date: Wed Nov 8 23:52:44 2023 +0000 + + [defns.character.container] Improve note to entry (#6644) + + commit 8b38857b22f6518a41e506e4c9b2e9a1792a0fbd + Author: A. Jiang + Date: Tue Oct 10 09:40:20 2023 +0800 + + [iterator.requirements.general] Clarify non-forward iterator + + commit fbb1a6ebbd1f78e644df2dbcb3ce31250410779e + Author: onihusube <44743040+onihusube@users.noreply.github.com> + Date: Fri Nov 10 08:36:12 2023 +0900 + + [execpol.unseq] Fix missing \itemdescr (#5931) + + commit 10e2799f5d524dd941d424dfd08927c77a6b87f1 + Author: Alisdair Meredith + Date: Fri Feb 17 10:47:28 2023 -0500 + + [pairs.pair] Consistent wording for assignment + + Apply a consistent pattern to how we specify assigning members in assignment operators. + + commit 78300aa38c23f1356dca8e786205e5aaf7769d01 + Author: Barry Revzin + Date: Thu Nov 9 14:45:17 2023 -1000 + + [class.compare] Don't introduce `V` for the return value (#6035) + + In both cases, I'm not sure introducing `V` helps much - just requires name lookup for `V`. If we just say "the return value" in every case, I think that's clearer. + + commit 838cb0649b1f4061e960772aee3563cedb20b108 + Author: Michael Florian Hava + Date: Thu Nov 9 13:51:58 2023 -1000 + + [basic.extended.fp] Replaced usage of 'mantissa' with 'significand' + according to SO/IEC/IEEE 60559:2008 + + commit ce5ef1b5334f1fc756d40e40ec300257b0ff99d9 + Author: Michael Florian Hava + Date: Thu Nov 9 13:57:32 2023 -1000 + + [numeric.limits.members] Replaced usage of 'mantissa' with 'significand' according to + SO/IEC/IEEE 60559:2008 + + commit 3e1f377a9dc3bece7acd2dddb7237065504db65c + Author: Brian Bi + Date: Thu Nov 9 16:00:22 2023 -1000 + + [macros, styles] Add \hypertarget to headings (#6516) + + This allows forming URLs with a stable label as a fragment and + have PDF viewers jump to the corresponding (sub)clause. + + For example: std.pdf#basic.life + + commit 60f7bb72cdd36e9d359fa7aea84a5b836079a0ed + Author: Eisenwave + Date: Thu Jul 6 13:41:56 2023 +0200 + + [namespace.std] convert (a) and (b) notation to items + + commit f48f316c42c6cb67058d9f9106852154497b4516 + Author: Jan Schultke + Date: Fri Nov 10 06:57:17 2023 +0100 + + [atomics.order] Use "recommended practice" (#6380) + + commit 1ec1d9e6fa98734b3edf20f6c2217a4482f78103 + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Fri Nov 10 16:59:21 2023 +0800 + + [meta.{unary.prop.query,trans.arr] Use `static_assert` instead of `assert` in example + + commit bd8f4540720e52dab9187a62c5598e735aeacfdd + Author: Eisenwave + Date: Sat Aug 19 15:57:39 2023 +0200 + + [expr.sizeof] use constexpr member in example + + commit b1f922a126dcda78acb4bae055843e7a7321fe1d + Author: Eisenwave + Date: Wed Aug 23 13:42:39 2023 +0200 + + [basic.def.odr] Fix hyphenation of "{copy,move} assignment" + + commit 54e465a17adfcba56a57ff2fefe43ec898725efb + Author: Eisenwave + Date: Wed Aug 23 13:43:46 2023 +0200 + + [res.on.arguments] Fix hyphenation of "move assignment" + + commit 3c5b5b0c58d0440233d992e1a0791a449936f203 + Author: Eisenwave + Date: Wed Aug 23 13:44:40 2023 +0200 + + [futures.{unique,shared}.future] Fix hyphenation of "{copy,move} assignment" + + commit 9483cb7cf6973689ad563d30778d8da2dff42a8d + Author: Jonathan Wakely + Date: Wed Nov 8 22:57:57 2023 +0000 + + [string.capacity] Remove parentheses from "reserve()" + + It's very confusing to talk about `reserve()` when describing a call to + `reserve(size_type)`, given that the overload `reserve()` also exists. + + commit 2a9f28670a0df6e239d9b335bdb014f20f577732 + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Mon Jul 24 16:19:01 2023 +0000 + + [dcl.meaning.general] Use 'declarator-id' instead of 'name' + + commit d8b72f0ceb36b3537ef576ab216d588642e332ab + Author: lprv <100177227+lprv@users.noreply.github.com> + Date: Tue Jul 25 18:26:03 2023 +0000 + + [module.global.frag] Simplify wording + + Also make variable order consistent across bullets. + + commit f0c172c5604b47c3ecc7b64669aad660df403624 + Author: Oliver Rosten + Date: Fri Nov 10 18:12:06 2023 +0000 + + [algorithms] Change stable label "mismatch" to "alg.mismatch" (#6653) + + commit d97603a90d2fcfeec2caf4371ca9e6c8f562842a + Author: A. Jiang + Date: Sat Nov 11 03:21:17 2023 +0800 + + [forward.iterators] Use "Cpp17" requirement (#6612) + + commit f474227b69d10350999a5fc63503725421a89954 + Author: Geng Cheng + Date: Sat Nov 11 10:25:39 2023 +0800 + + [stringstream.general] Add missing template argument "Allocator" (#6560) + + commit f5fdfe453e5a1e0370f2cb28bfc2dfeecab6370e + Author: Alisdair Meredith + Date: Wed Nov 8 15:12:16 2023 -1000 + + [diff.cpp20.library] Add missing new headers for C++23 + + commit 38dfe3db0f08bd09a2b445ba82e83f7caae28d94 + Author: A. Jiang + Date: Thu Nov 9 11:00:44 2023 +0800 + + [dcl.init.ref] Clarify "related type" + + "Related type" is not a term, "reference-related type" is clearer. + + commit 979983929bb592c02c9ae3e52f1c676dd5ae06fe + Author: Hewill Kang <67143766+hewillk@users.noreply.github.com> + Date: Tue Nov 14 02:27:01 2023 +0800 + + [range.cartesian.view] Don't name unused template parameter (#6177) + + commit ecbeb5ad4e4c0ac1d0cdb5e8dd01daab8df8d62e + Author: Alisdair Meredith + Date: Tue Nov 14 14:27:27 2023 -0500 + + [diff.cpp23.library] Entry for new headers in C++26 (#6648) + + commit eb7f0bcbff2af109643089ef36dfe67040a27f4a + Author: Thomas Köppe + Date: Mon Nov 13 01:12:50 2023 -1000 + + [intro.defs, macros] Add cross-references among definitions + + Fixes ISO/CS 017 (C++23 DIS). + + commit 706880e4ed855ae76d503c70adfb0015bbfb3df0 + Author: Lewis Baker + Date: Thu Nov 16 10:36:25 2023 +1030 + + [allocator.requirements.general] Fix missing ellipsis (#6695) + + commit 5c0103c0a656cbcd725780388b0879e992a1b21a + Author: Jonathan Wakely + Date: Thu Nov 16 15:38:47 2023 +0000 + + [stacktrace.format], [stacktrace.basic.hash] change rSec3 to rSec2 + + These should not be nested below std::basic_stacktrace because they + apply to both std::stacktrace_entry and std::basic_stacktrace. + + commit a6ad6083ab75901cb41b5bc8d034c0b322433457 + Author: Thomas Köppe + Date: Tue Dec 5 23:42:23 2023 +0000 + + [std, styles] Adjust table captions as per ISO request + + ISO has asked for captions to be bold and table numbers to be + separated by a dash. + + commit f519ea4aa97592703ba5bbe9164242d946723721 + Author: Jens Maurer + Date: Thu Dec 7 01:00:53 2023 +0100 + + [intro.refs, time.format] Update references from ISO 8601:2004 to ISO 8601-1:2019 (#6720) + + commit 37956fb3685c2c279bd6b4b701964b20913d0c79 + Author: Thomas Köppe + Date: Wed Dec 6 19:01:29 2023 +0000 + + [syntax] Change "italic" to "italic, sans-serif" + + We changed the grammar non-terminal font to sans-serif, + so we should update the description. + + commit 4eed7a0f1e44c45554f8a210af34fd6e1ea19596 + Author: Jens Maurer + Date: Thu Dec 7 22:13:35 2023 +0100 + + [intro.abstract] Actually use the phrase 'unspecified/undefined behavior' + + Fixes ISO/CS 011 (C++23 DIS). + + commit f8a6138da1e431779ac43a893faa32f3f0cad7d0 + Author: Thomas Köppe + Date: Thu Dec 7 12:45:11 2023 +0000 + + [intro.defs] Fix introductory text according to ISO rules. + + In principle, "symbols and abbreviated terms" can be listed in a + standard, and can be listed in a separate clause or in a combined + clause 3 "Terms, definitions, symbols and abbreviated terms", we do + not actually need symbol definitions. In any case, the introductory + text would never mention "symbols". + + commit 9961cd4f16aca645c77d6927526ea71f635a2932 + Author: Thomas Köppe + Date: Thu Dec 7 00:01:48 2023 +0000 + + [introduction] A minimal "Introduction" clause + + This clause explains our conventions regarding stable labels and + choice of fonts. + + commit 9041b27206388fecd03073bb913185ac738c6dca + Author: Thomas Köppe + Date: Mon Dec 18 00:57:45 2023 +0000 + + [optional.monaic] Restore wording effected by LWG3973. + + Both LWG3973 (Motion 1) and P2407R5 (Motion 3) modified this wording: + LWG3973 changes "value()" to "*val" to address ADL concerns, and + P2407R5 changed "value()" to "**this" to be freestanding. In light of + the former, the latter should also use "*val". + + Independently, additional problems have been discovered with LWG3973, + but those will be addressed by a future LWG issue. + + commit 2b1867a3404562c4261722e0a913cbcbf5a0a476 + Author: Thomas Köppe + Date: Sun Dec 17 23:10:44 2023 +0000 + + [version.syn] New feature test macro __cpp_lib_freestanding_numeric + + This macro indicates that freestanding support for "saturation + arithmetic" is available, which was added in motion LWG-2 (via + P0543R3). This reverts the previous change + 148e03a16d53ff8cffd219384df37efad5fd386d, which I had made subsequent + to motion LWG-3 (P2407R5), on advice of LWG. A separate macro is + preferable to mixing both headers under "algorithm". + + commit fa54f9e7306b3d0abb21a82b5cc951711c96161f + Author: Jonathan Wakely + Date: Wed Dec 13 11:03:18 2023 +0000 + + [range.access.general] Use consistent "In addition to being available ..." form + + Elsewhere we say "the header" or "any of the headers", e.g. [meta.trans.other], + [tuple.helper], etc. + + commit 8c611593555b93a45a13543ad265d8cfaf646932 + Author: Cassio Neri + Date: Mon Nov 27 19:47:29 2023 +0000 + + [expected.general] Fix description of expected (issue #6714.) + + commit 12565ed5ea083761b25df3c8325989f95fa04898 + Author: Po-yao Chang + Date: Wed Nov 22 23:02:49 2023 +0800 + + [class.eq] Fix the return value of a defaulted == operator function diff --git a/papers/wd-index.md b/papers/wd-index.md index c7e0741fd5..5ea3d75a59 100644 --- a/papers/wd-index.md +++ b/papers/wd-index.md @@ -47,3 +47,4 @@ * [N4950](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf) 2023-05 C++ Working Draft * [N4958](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4958.pdf) 2023-08 C++ Working Draft * [N4964](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4964.pdf) 2023-10 C++ Working Draft + * [N4971](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4971.pdf) 2023-12 C++ Working Draft diff --git a/source/algorithms.tex b/source/algorithms.tex index 5fe7ecfb5e..ff4c3b38ed 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -297,7 +297,7 @@ by invoking the following functions: \begin{itemize} \item - All operations of the categories of the iterators + All operations of the categories of the iterators or \tcode{mdspan} types that the algorithm is instantiated with. \item Operations on those sequence elements that are required by its specification. @@ -348,7 +348,7 @@ int a[] = {1,2}; std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard guard(m); // incorrect: \tcode{lock_guard} constructor calls \tcode{m.lock()} - ++x; + ++x; }); } \end{codeblock} @@ -369,7 +369,8 @@ \tcode{UnaryOperation}, \tcode{BinaryOperation}, \tcode{BinaryOperation1}, -\tcode{BinaryOperation2}, and +\tcode{BinaryOperation2}, +\tcode{BinaryDivideOp}, and the operators used by the analogous overloads to these parallel algorithms that are formed by an invocation with the specified default predicate or operation (where applicable) @@ -977,7 +978,7 @@ count_if(R&& r, Pred pred, Proj proj = {}); } - // \ref{mismatch}, mismatch + // \ref{alg.mismatch}, mismatch template constexpr pair mismatch(InputIterator1 first1, InputIterator1 last1, @@ -1630,7 +1631,7 @@ void fill(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} ForwardIterator first, ForwardIterator last, const T& value); template - constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); + constexpr OutputIterator fill_n(OutputIterator first, Size n, const T& value); // freestanding template ForwardIterator fill_n(ExecutionPolicy&& exec, // see \ref{algorithms.parallel.overloads} @@ -4044,7 +4045,7 @@ of the corresponding predicate and any projection. \end{itemdescr} -\rSec2[mismatch]{Mismatch} +\rSec2[alg.mismatch]{Mismatch} \indexlibraryglobal{mismatch}% \begin{itemdecl} @@ -5207,7 +5208,7 @@ template constexpr ForwardIterator2 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, - ForwardIterator2 first2); + ForwardIterator2 first2); // freestanding template ForwardIterator2 swap_ranges(ExecutionPolicy&& exec, @@ -9621,6 +9622,18 @@ constexpr T midpoint(T a, T b) noexcept; template constexpr T* midpoint(T* a, T* b); + + // \ref{numeric.sat}, saturation arithmetic + template + constexpr T add_sat(T x, T y) noexcept; // freestanding + template + constexpr T sub_sat(T x, T y) noexcept; // freestanding + template + constexpr T mul_sat(T x, T y) noexcept; // freestanding + template + constexpr T div_sat(T x, T y) noexcept; // freestanding + template + constexpr T saturate_cast(U x) noexcept; // freestanding } \end{codeblock} @@ -10755,6 +10768,119 @@ where the result of the division is truncated towards zero. \end{itemdescr} +\rSec2[numeric.sat]{Saturation arithmetic} + +\rSec3[numeric.sat.func]{Arithmetic functions} + +\pnum +\begin{note} +In the following descriptions, an arithmetic operation +is performed as a mathematical operation with infinite range and then +it is determined whether the mathematical result fits into the result type. +\end{note} + +\indexlibraryglobal{add_sat}% +\begin{itemdecl} +template + constexpr T add_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} + \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} + \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} + \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{sub_sat}% +\begin{itemdecl} +template + constexpr T sub_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} - \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} - \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} - \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{mul_sat}% +\begin{itemdecl} +template + constexpr T mul_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\returns +If $\tcode{x} \times \tcode{y}$ is representable as a value of type \tcode{T}, $\tcode{x} \times \tcode{y}$; +otherwise, either the largest or smallest representable value of type \tcode{T}, +whichever is closer to the value of $\tcode{x} \times \tcode{y}$. +\end{itemdescr} + +\indexlibraryglobal{div_sat}% +\begin{itemdecl} +template + constexpr T div_sat(T x, T y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{T} is a signed or unsigned integer type\iref{basic.fundamental}. + +\pnum +\expects +\tcode{y != 0} is \tcode{true}. + +\pnum +\returns +If \tcode{T} is a signed integer type +and \tcode{x == numeric_limits::min() \&\& y == -1} is \tcode{true}, +\tcode{numeric_limits::max()}, otherwise, \tcode{x / y}. + +\pnum +\remarks +A function call expression +that violates the precondition in the \Fundescx{Preconditions} element +is not a core constant expression\iref{expr.const}. +\end{itemdescr} + +\rSec3[numeric.sat.cast]{Casting} + +\indexlibraryglobal{saturate_cast}% +\begin{itemdecl} +template + constexpr R saturate_cast(T x) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{R} and \tcode{T} are signed or unsigned integer types\iref{basic.fundamental}. + +\pnum +\returns +If \tcode{x} is representable as a value of type \tcode{R}, \tcode{x}; +otherwise, either the largest or smallest representable value of type \tcode{R}, +whichever is closer to the value of \tcode{x}. +\end{itemdescr} + \rSec1[specialized.algorithms]{Specialized \tcode{} algorithms} \rSec2[specialized.algorithms.general]{General} diff --git a/source/back.tex b/source/back.tex index 1107b0c2b4..335f834a90 100644 --- a/source/back.tex +++ b/source/back.tex @@ -1,48 +1,72 @@ %!TEX root = std.tex -\chapter{Bibliography} - -\begin{itemize} -\renewcommand{\labelitemi}{---} +\begin{thebibliography}{99} % ISO documents in numerical order. -\item +\bibitem{iso4217} ISO 4217:2015, \doccite{Codes for the representation of currencies} -\item +\bibitem{iso10967-1} ISO/IEC 10967-1:2012, \doccite{Information technology --- Language independent arithmetic --- Part 1: Integer and floating point arithmetic} -\item +\bibitem{iso18661-3} ISO/IEC TS 18661-3:2015, \doccite{Information Technology --- Programming languages, their environments, and system software interfaces --- Floating-point extensions for C --- Part 3: Interchange and extended types} % Other international standards. -\item +\bibitem{iana-charset} IANA Character Sets Database. Available from:\newline \url{https://www.iana.org/assignments/character-sets/}, 2021-04-01 -\item +\bibitem{iana-tz} IANA Time Zone Database. Available from: \url{https://www.iana.org/time-zones} -\item +\bibitem{unicode-charmap} Unicode Character Mapping Markup Language [online]. Edited by Mark Davis and Markus Scherer. Revision 5.0.1; 2017-05-31 Available from: \url{http://www.unicode.org/reports/tr22/tr22-8.html} % Literature references. -\item +\bibitem{cpp-r} Bjarne Stroustrup, \doccite{The \Cpp{} Programming Language, second edition}, Chapter R\@. Addison-Wesley Publishing Company, ISBN 0-201-53992-6, copyright \copyright 1991 AT\&T -\item +\bibitem{kr} Brian W.\ Kernighan and Dennis M. Ritchie, \doccite{The C Programming Language}, Appendix A\@. Prentice-Hall, 1978, ISBN 0-13-110163-3, copyright \copyright 1978 AT\&T -\item +\bibitem{cpp-lib} P.J.\ Plauger, \doccite{The Draft Standard \Cpp{} Library}. Prentice-Hall, ISBN 0-13-117003-1, copyright \copyright 1995 P.J.\ Plauger -\end{itemize} +\bibitem{linalg-stable} + J.\ Demmel, I.\ Dumitriu, and O.\ Holtz, + \doccite{Fast linear algebra is stable}, + Numerische Mathematik 108 (59--91), 2007. +\bibitem{blas1} + C.\,L.\ Lawson, R.\,J.\ Hanson, D.\ Kincaid, and F.\,T.\ Krogh, + \doccite{Basic linear algebra subprograms for Fortran usage}. + ACM Trans.\ Math.\ Soft., Vol.\ 5, pp.\ 308--323, 1979. +\bibitem{blas2} + Jack J.\ Dongarra, Jeremy Du Croz, Sven Hammarling, and Richard J. Hanson, + \doccite{An Extended Set of FORTRAN Basic Linear Algebra Subprograms}. + ACM Trans.\ Math.\ Soft., Vol.\ 14, No.\ 1, pp.\ 1--17, Mar.\ 1988. +\bibitem{blas3} + Jack J.\ Dongarra, Jeremy Du Croz, Sven Hammarling, and Iain Duff, + \doccite{A Set of Level 3 Basic Linear Algebra Subprograms}. + ACM Trans.\ Math.\ Soft., Vol.\ 16, No.\ 1, pp.\ 1--17, Mar.\ 1990. +\bibitem{lapack} + E.\ Anderson, Z.\ Bai, C.\ Bischof, S.\ Blackford, J.\ Demmel, J.\ Dongarra, + J.\ Du Croz, A.\ Greenbaum, S.\ Hammarling, A.\ McKenney, D.\ Sorensen + \doccite{LAPACK Users' Guide, Third Edition}. + SIAM, Philadelphia, PA, USA, 1999. +\bibitem{blas-std} + L. Susan Blackford, Ames Demmel, Jack Dongarra, Iain Duff, Sven Hammarling, + Greg Henry, Michael Heroux, Linda Kaufman, Andrew Lumbsdaine, Antoine Petitet, + Roldan Pozo, Karin Remington, R. Client Whaley + \doccite{An Updated Set of Basic Linear Algebra Subprograms (BLAS)}. + ACM Trans.\ Math.\ Soft., Vol.\ 28, Issue 2, 2002. +\end{thebibliography} The arithmetic specification described in ISO/IEC 10967-1:2012 is called \defn{LIA-1} in this document. diff --git a/source/basic.tex b/source/basic.tex index 65947ad304..aa5ea9413a 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -489,7 +489,7 @@ \pnum An assignment operator function in a class is odr-used by an implicitly-defined -copy-assignment or move-assignment function for another class as specified +copy assignment or move assignment function for another class as specified in~\ref{class.copy.assign}. A constructor for a class is odr-used as specified in~\ref{dcl.init}. A destructor for a class is odr-used if it is potentially @@ -1000,10 +1000,22 @@ \pnum A declaration is \defnx{name-independent}{declaration!name-independent} if its name is \tcode{_} (\unicode{005f}{low line}) and it declares +\begin{itemize} +\item a variable with automatic storage duration, -a structured binding not inhabiting a namespace scope, +\item +a structured binding +%FIXME: "and" is strange below; maybe reword to something like: +%FIXME: "that has no \grammarterm{storage-class-specifier} and +%FIXME: that is not inhabiting a namespace scope," +with no \grammarterm{storage-class-specifier} and +not inhabiting a namespace scope, +\item the variable introduced by an \grammarterm{init-capture}, or -a non-static data member. +\item +%FIXME: "of" is strange below; remove it? +a non-static data member of other than an anonymous union. +\end{itemize} \recommended Implementations should not emit a warning @@ -1206,7 +1218,7 @@ \pnum The locus of a \grammarterm{concept-definition} -is immediately after its concept-name\iref{temp.concept}. +is immediately after its \grammarterm{concept-name}\iref{temp.concept}. \begin{note} The \grammarterm{constraint-expression} cannot use the \grammarterm{concept-name}. @@ -1278,7 +1290,7 @@ \pnum If a declaration that is not a name-independent declaration and -whose target scope is the block scope $S$ of a +that binds a name in the block scope $S$ of a \begin{itemize} \item \grammarterm{compound-statement} of a \grammarterm{lambda-expression}, @@ -2170,7 +2182,7 @@ followed by a \tcode{::} scope resolution operator considers only namespaces, types, and templates whose specializations are types. -If a name, \grammarterm{template-id}, or \grammarterm{decltype-specifier} +If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} is followed by a \tcode{::}, it shall designate a namespace, class, enumeration, or dependent type, and the \tcode{::} is never interpreted as @@ -3300,6 +3312,12 @@ standard-layout type\iref{basic.types.general} shall occupy contiguous bytes of storage. +\pnum +An object is a \defnadj{potentially non-unique}{object} if it is +a string literal object\iref{lex.string}, +the backing array of an initializer list\iref{dcl.init.ref}, or +a subobject thereof. + \pnum \indextext{most derived object!bit-field}% \indextext{most derived object!zero size subobject}% @@ -3308,11 +3326,13 @@ Two objects with overlapping lifetimes that are not bit-fields -may have the same address -if one is nested within the other, +may have the same address if +\begin{itemize} +\item one is nested within the other, +\item at least one is a subobject of zero size and they are not of similar types\iref{conv.qual}, or -if at least one is a subobject of zero size -and they are of different types; +\item they are both potentially non-unique objects; +\end{itemize} otherwise, they have distinct addresses and occupy disjoint bytes of storage. \begin{footnote} @@ -3326,6 +3346,14 @@ static const char test1 = 'x'; static const char test2 = 'x'; const bool b = &test1 != &test2; // always \tcode{true} + +static const char (&r) [] = "x"; +static const char *s = "x"; +static std::initializer_list il = { 'x' }; +const bool b2 = r != il.begin(); // unspecified result +const bool b3 = r != s; // unspecified result +const bool b4 = il.begin() != &test1; // always \tcode{true} +const bool b5 = r != &test1; // always \tcode{true} \end{codeblock} \end{example} The address of a non-bit-field subobject of zero size is @@ -3338,7 +3366,7 @@ within a specified region of storage. For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of -zero or more objects of implicit-lifetime types\iref{basic.types.general} +zero or more objects of implicit-lifetime types\iref{term.implicit.lifetime.type} in its specified region of storage if doing so would result in the program having defined behavior. If no such set of objects would give the program defined behavior, @@ -3816,7 +3844,6 @@ \rSec3[basic.stc.static]{Static storage duration} \pnum -\indextext{storage duration!static}% All variables which \begin{itemize} \item @@ -3826,7 +3853,7 @@ are first declared with the \keyword{static} or \keyword{extern} keywords\iref{dcl.stc} \end{itemize} -have \defn{static storage duration}. +have \defnadj{static}{storage duration}. The storage for these entities lasts for the duration of the program\iref{basic.start.static,basic.start.term}. @@ -4834,6 +4861,7 @@ types\iref{class.prop}, arrays of such types, and cv-qualified versions of these types are collectively called \defnadjx{standard-layout}{types}{type}. +\label{term.implicit.lifetime.type}% Scalar types, implicit-lifetime class types\iref{class.prop}, array types, and cv-qualified versions of these types are collectively called \defnadjx{implicit-lifetime}{types}{type}. @@ -5248,8 +5276,8 @@ \pnum \begin{note} A summary of the parameters for each type is given in \tref{basic.extended.fp}. -The precision $p$ includes the implicit 1 bit at the beginning of the mantissa, -so the storage used for the mantissa is $p-1$ bits. +The precision $p$ includes the implicit 1 bit at the beginning of the significand, +so the storage used for the significand is $p-1$ bits. ISO/IEC/IEEE 60559 does not assign a name for a type having the parameters specified for \tcode{std::bfloat16_t}. \end{note} @@ -6251,7 +6279,7 @@ \end{itemize} The value of a non-atomic scalar object or bit-field $M$, as determined by -evaluation $B$, shall be the value stored by the +evaluation $B$, is the value stored by the \indextext{side effects!visible}% visible side effect $A$. \begin{note} @@ -6269,8 +6297,8 @@ \pnum The value of an -atomic object $M$, as determined by evaluation $B$, shall be the value -stored by some +atomic object $M$, as determined by evaluation $B$, is the value +stored by some unspecified side effect $A$ that modifies $M$, where $B$ does not happen before $A$. \begin{note} @@ -6281,7 +6309,7 @@ \pnum \indextext{coherence!write-write}% If an operation $A$ that modifies an atomic object $M$ happens before -an operation $B$ that modifies $M$, then $A$ shall be earlier +an operation $B$ that modifies $M$, then $A$ is earlier than $B$ in the modification order of $M$. \begin{note} This requirement is known as write-write coherence. @@ -6293,7 +6321,7 @@ \indextext{value computation}% value computation $A$ of an atomic object $M$ happens before a value computation $B$ of $M$, and $A$ takes its value from a side -effect $X$ on $M$, then the value computed by $B$ shall either be +effect $X$ on $M$, then the value computed by $B$ is either the value stored by $X$ or the value stored by a \indextext{side effects}% side effect $Y$ on $M$, @@ -6307,7 +6335,7 @@ If a \indextext{value computation}% value computation $A$ of an atomic object $M$ happens before an -operation $B$ that modifies $M$, then $A$ shall take its value from a side +operation $B$ that modifies $M$, then $A$ takes its value from a side effect $X$ on $M$, where $X$ precedes $B$ in the modification order of $M$. \begin{note} @@ -6320,7 +6348,7 @@ If a \indextext{side effects}% side effect $X$ on an atomic object $M$ happens before a value -computation $B$ of $M$, then the evaluation $B$ shall take its +computation $B$ of $M$, then the evaluation $B$ takes its value from $X$ or from a \indextext{side effects}% side effect $Y$ that follows $X$ in the modification order of $M$. diff --git a/source/classes.tex b/source/classes.tex index bfb2b24787..65231de79a 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -63,7 +63,7 @@ a partial specialization\iref{temp.spec.partial}. A \grammarterm{class-specifier} whose \grammarterm{class-head} omits the -\grammarterm{class-head-name} defines an unnamed class. +\grammarterm{class-head-name} defines an \defnadj{unnamed}{class}. \begin{note} An unnamed class thus can't be \tcode{final}. @@ -796,9 +796,10 @@ \item corresponding entities have the same alignment requirements\iref{basic.align}, \item -either both entities are declared with -the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr} -or neither is, and +if a \grammarterm{has-attribute-expression}\iref{cpp.cond} +is not \tcode{0} for the \tcode{no_unique_address} attribute, +then neither entity is declared with +the \tcode{no_unique_address} attribute\iref{dcl.attr.nouniqueaddr}, and \item either both entities are bit-fields with the same width or neither is a bit-field. @@ -1095,7 +1096,9 @@ \begin{itemize} \item the function is not deleted, \item the associated constraints\iref{temp.constr}, if any, are satisfied, and -\item no special member function of the same kind is more constrained\iref{temp.constr.order}. +\item no special member function of the same kind +whose associated constraints, if any, are satisfied +is more constrained\iref{temp.constr.order}. \end{itemize} \pnum @@ -1679,7 +1682,7 @@ \begin{note} If a class \tcode{X} -only has a copy assignment operator with a parameter of type +only has a copy assignment operator with a non-object parameter of type \tcode{X\&}, an expression of type const \tcode{X} @@ -1719,12 +1722,12 @@ \begin{itemize} \item each direct base class \tcode{B} of \tcode{X} -has a copy assignment operator whose parameter is of type +has a copy assignment operator whose non-object parameter is of type \tcode{const B\&}, \tcode{const volatile B\&}, or \tcode{B}, and \item for all the non-static data members of \tcode{X} that are of a class type \tcode{M} (or array thereof), -each such class type has a copy assignment operator whose parameter is of type +each such class type has a copy assignment operator whose non-object parameter is of type \tcode{const M\&}, \tcode{const volatile M\&}, or \tcode{M}. \begin{footnote} @@ -1746,11 +1749,6 @@ one non-object parameter of type \tcode{X\&\&}, \tcode{const X\&\&}, \tcode{volatile X\&\&}, or \tcode{const volatile X\&\&}. \begin{note} -An overloaded assignment operator must be -declared to have only one parameter; see~\ref{over.ass}. -\end{note} -{} -\begin{note} More than one form of move assignment operator can be declared for a class. \end{note} @@ -1988,9 +1986,8 @@ shall be \keyword{friend}, \keyword{inline}, -\keyword{virtual}, -\keyword{constexpr}, or -\keyword{consteval}. +\keyword{virtual}, or +\keyword{constexpr}. \pnum \indextext{generated destructor|see{destructor, default}}% @@ -2119,7 +2116,8 @@ \tcode{X} calls the destructors for \tcode{X}'s -direct non-variant non-static data members, the destructors for +direct non-variant non-static data members other than anonymous unions, +the destructors for \tcode{X}'s non-virtual direct base classes and, if \tcode{X} @@ -2193,7 +2191,7 @@ In an explicit destructor call, the destructor is specified by a \tcode{\~{}} followed by a -\grammarterm{type-name} or \grammarterm{decltype-specifier} +\grammarterm{type-name} or \grammarterm{computed-type-specifier} that denotes the destructor's class type. The invocation of a destructor is subject to the usual rules for member functions\iref{class.mfct}; @@ -2356,7 +2354,7 @@ \begin{codeblock} struct X { X(int); - X(const char*, int =0); + X(const char*, int = 0); X(int, int); }; @@ -2438,7 +2436,7 @@ a function declarator\iref{dcl.fct} of the form \begin{ncsimplebnf} ptr-declarator \terminal{(} parameter-declaration-clause \terminal{)} \opt{cv-qualifier-seq}\br -\bnfindent \opt{ref-qualifier-seq} \opt{noexcept-specifier} \opt{attribute-specifier-seq} +\bnfindent \opt{ref-qualifier} \opt{noexcept-specifier} \opt{attribute-specifier-seq} \end{ncsimplebnf} where the \grammarterm{ptr-declarator} consists solely of an \grammarterm{id-expression}, @@ -2779,9 +2777,8 @@ \end{note} \pnum -\indextext{bit-field!unnamed}% A declaration for a bit-field that omits the \grammarterm{identifier} -declares an \defn{unnamed bit-field}. Unnamed bit-fields are not +declares an \defnadj{unnamed}{bit-field}. Unnamed bit-fields are not members and cannot be initialized. An unnamed bit-field shall not be declared with a cv-qualified type. \begin{note} @@ -3161,7 +3158,10 @@ In an assignment expression of the form \tcode{E1 = E2} that uses either the built-in assignment operator\iref{expr.ass} or a trivial assignment operator\iref{class.copy.assign}, -for each element \tcode{X} of $S($\tcode{E1}$)$, +for each element \tcode{X} of $S($\tcode{E1}$)$ and +each anonymous union member \tcode{X}\iref{class.union.anon} that +is a member of a union and +has such an element as an immediate subobject (recursively), if modification of \tcode{X} would have undefined behavior under~\ref{basic.life}, an object of the type of \tcode{X} is implicitly created in the nominated storage; @@ -3257,11 +3257,12 @@ \pnum \indextext{\idxcode{union}!global anonymous}% \indextext{scope!anonymous \tcode{union} at namespace}% -Anonymous unions declared in the scope of a namespace with external linkage -shall be declared \keyword{static}. Anonymous unions declared at -block scope shall be declared with any storage class allowed for a -block variable, or with no storage class. A storage class is not -allowed in a declaration of an anonymous union in a class scope. +An anonymous union declared in the scope of a namespace with external linkage +shall use the \grammarterm{storage-class-specifier} \keyword{static}. +Anonymous unions declared at block scope shall not use a \grammarterm{storage-class-specifier} +that is not permitted in the declaration of a block variable. +An anonymous union declaration at class scope shall not have +a \grammarterm{storage-class-specifier}. \pnum \begin{note} @@ -4855,7 +4856,7 @@ a \grammarterm{template-declaration}\iref{temp.pre,temp.friend}. \end{note} If the -type specifier in a \keyword{friend} declaration designates a (possibly +type specifier in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend declaration is ignored. \begin{example} @@ -5823,9 +5824,16 @@ were used to initialize the \tcode{D} object and each base class subobject from which the constructor was inherited, except that the \tcode{B} subobject is initialized -by the invocation of the inherited constructor. +by the inherited constructor +if the base class subobject were to be initialized +as part of the \tcode{D} object\iref{class.base.init}. +The invocation of the inherited constructor, +including the evaluation of any arguments, +is omitted if the \tcode{B} subobject is not to be initialized +as part of the \tcode{D} object. The complete initialization is considered to be a single function call; -in particular, the initialization of the inherited constructor's parameters +in particular, unless omitted, +the initialization of the inherited constructor's parameters is sequenced before the initialization of any part of the \tcode{D} object. \begin{example} \begin{codeblock} @@ -5875,6 +5883,23 @@ whenever an object of class \tcode{Log} is destroyed. \end{example} +\begin{example} +\begin{codeblock} +struct V { V() = default; V(int); }; +struct Q { Q(); }; +struct A : virtual V, Q { + using V::V; + A() = delete; +}; +int bar() { return 42; } +struct B : A { + B() : A(bar()) {} // OK +}; +struct C : B {}; +void foo() { C c; } // \tcode{bar} is not invoked, because the \tcode{V} subobject is not initialized as part of \tcode{B} +\end{codeblock} +\end{example} + \pnum If the constructor was inherited from multiple base class subobjects of type \tcode{B}, the program is ill-formed. @@ -6232,8 +6257,8 @@ corresponding parameter if the meaning of the program will be unchanged except for the execution of a constructor and destructor for the parameter copy object -\item when the \grammarterm{exception-declaration} of an -exception handler\iref{except.pre} declares an object of the same +\item when the \grammarterm{exception-declaration} of a +\grammarterm{handler}\iref{except.handle} declares an object of the same type (except for cv-qualification) as the exception object\iref{except.throw}, the copy operation can be omitted by treating the \grammarterm{exception-declaration} as an alias for the exception @@ -6508,7 +6533,7 @@ is usable\iref{class.compare.default}. \pnum -The return value \tcode{V} of a defaulted \tcode{==} operator function +The return value of a defaulted \tcode{==} operator function with parameters \tcode{x} and \tcode{y} is determined by comparing corresponding elements $\tcode{x}_i$ and $\tcode{y}_i$ in the expanded lists of subobjects for \tcode{x} and \tcode{y} @@ -6516,8 +6541,8 @@ until the first index $i$ where $\tcode{x}_i\tcode{ == }\tcode{y}_i$ yields a result value which, when contextually converted to \tcode{bool}, yields \tcode{false}. -If no such index exists, \tcode{V} is \tcode{true}. -Otherwise, \tcode{V} is \tcode{false}. +The return value is \tcode{false} if such an index exists +and \tcode{true} otherwise. \pnum \begin{example} @@ -6616,7 +6641,7 @@ \end{itemize} \pnum -The return value \tcode{V} of type \tcode{R} +The return value of type \tcode{R} of the defaulted three-way comparison operator function with parameters \tcode{x} and \tcode{y} of the same type is determined by comparing corresponding elements @@ -6627,10 +6652,10 @@ the synthesized three-way comparison of type \tcode{R} between $\tcode{x}_i$ and $\tcode{y}_i$ yields a result value $\tcode{v}_i$ where $\tcode{v}_i \mathrel{\tcode{!=}} 0$, -contextually converted to \tcode{bool}, yields \tcode{true}; -\tcode{V} is a copy of $\tcode{v}_i$. -If no such index exists, \tcode{V} is -\tcode{static_cast(std::strong_ordering::equal)}. +contextually converted to \tcode{bool}, yields \tcode{true}. +The return value is a copy of $\tcode{v}_i$ +if such an index exists and +\tcode{static_cast(std::strong_ordering::equal)} otherwise. \pnum The \defn{common comparison type} \tcode{U} diff --git a/source/compatibility.tex b/source/compatibility.tex index 185dc4f835..4e1948add1 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -13,6 +13,27 @@ \rSec2[diff.cpp23.expr]{\ref{expr}: expressions} +\diffref{expr.arith.conv} +\change +Operations mixing a value of an enumeration type and a value of a different +enumeration type or of a floating-point type are no longer valid. +\rationale +Reinforcing type safety. +\effect +A valid \CppXXIII{} program that performs operations mixing a value of an +enumeration type and a value of a different enumeration type or of a +floating-point type is ill-formed. +For example: +\begin{codeblock} +enum E1 { e }; +enum E2 { f }; +bool b = e <= 3.7; // ill-formed; previously well-formed +int k = f - e; // ill-formed; previously well-formed +auto x = true ? e : f; // ill-formed; previously well-formed +\end{codeblock} + +\rSec2[diff.cpp23.dcl.dcl]{\ref{dcl.dcl}: Declarations} + \diffref{dcl.init.list} \change Pointer comparisons between \tcode{initializer_list} objects' backing arrays @@ -31,6 +52,44 @@ bool b = ne({2,3}, {1,2,3}); // unspecified result; previously \tcode{false} \end{codeblock} +\diffref{dcl.array} +\change +Previously, \tcode{T...[n]} would declare a pack of function parameters. +\tcode{T...[n]} is now a \grammarterm{pack-index-specifier}. +\rationale +Improve the handling of packs. +\effect +Valid \CppXXIII{} code that declares a pack of parameters +without specifying a \grammarterm{declarator-id} becomes ill-formed. +For example: +\begin{codeblock} +template +void f(T... [1]); +template +void g(T... ptr[1]); +int main() { + f(nullptr, nullptr); // ill-formed, previously \tcode{void f(int [1], double [1])} + g(nullptr, nullptr); // ok +} +\end{codeblock} + +\rSec2[diff.cpp23.library]{\ref{library}: library introduction} + +\diffref{headers} +\change +New headers. +\rationale +New functionality. +\effect +The following \Cpp{} headers are new: +\libheaderref{debugging}, +\libheaderrefx{hazard_pointer}{hazard.pointer.syn}, +\libheaderref{linalg}, +\libheaderref{rcu}, and +\libheaderrefx{text_encoding}{text.encoding.syn}. +Valid \CppXXIII{} code that \tcode{\#include}{s} headers with these names may be +invalid in this revision of \Cpp{}. + \rSec2[diff.cpp23.strings]{\ref{strings}: strings library} \diffref{string.conversions} @@ -49,6 +108,88 @@ // changed according to the global C locale \end{codeblock} +\rSec2[diff.cpp23.containers]{\ref{containers}: containers library} + +\diffref{span.overview} +\change +\tcode{span} is constructible from \tcode{initializer_list}. +\rationale +Permit passing a braced initializer list to a function taking \tcode{span}. +\effect +Valid \CppXXIII{} code that relies on the lack of this constructor +may refuse to compile, or change behavior in this revision of \Cpp{}. +For example: +\begin{codeblock} +void one(pair); // \#1 +void one(span); // \#2 +void t1() { one({1, 2}); } // ambiguous between \#1 and \#2; previously called \#1 + +void two(span); +void t2() { two({{1, 2}}); } // ill-formed; previously well-formed + +void *a[10]; +int x = span{a, 0}.size(); // \tcode{x} is \tcode{2}; previously \tcode{0} +any b[10]; +int y = span{b, b + 10}.size(); // \tcode{y} is \tcode{2}; previously \tcode{10} +\end{codeblock} + +\rSec2[diff.cpp23.depr]{\ref{depr}: compatibility features} + +\nodiffref +\change +Remove the type alias \tcode{allocator::is_always_equal}. +\rationale +Non-empty allocator classes derived from \tcode{allocator} needed to explicitly +define an \tcode{is_always_equal} member type so that \tcode{allocator_traits} +would not use the one from the allocator base class. +\effect +It is simpler to correctly define an allocator class with an allocator base +class. For example: +\begin{codeblock} +template +struct MyAlloc : allocator { + int tag; +}; + +static_assert(!allocator_traits>::is_always_equal); // Error in \CppXXIII{}, + // OK in \CppXXVI{} +\end{codeblock} + +\nodiffref +\change +Remove the \tcode{basic_string::reserve()} overload with no parameters. +\rationale +The overload of \tcode{reserve} with no parameters is redundant. +The \tcode{shrink_to_fit} member function can be used instead. +\effect +A valid \CppXXIII{} program that calls \tcode{reserve()} +on a \tcode{basic_string} object may fail to compile. +The old functionality can be achieved by calling \tcode{shrink_to_fit()} instead, +or the function call can be safely eliminated with no side effects. + +\nodiffref +\change +Remove header \libnoheader{codecvt} and all its contents. +\rationale +The header has been deprecated for the previous three editions of this standard +and no longer implements the current Unicode standard, supporting only the +obsolete UCS-2 encoding. +Ongoing support is at implementer's discretion, +exercising freedoms granted by \ref{zombie.names}. +\effect +A valid \CppXXIII{} program \tcode{\#include}-ing the header or importing the +header unit may fail to compile. Code that uses any of the following names by +importing the standard library modules may fail to compile: +\begin{itemize} +\item \tcode{codecvt_mode}, +\item \tcode{codecvt_utf16}, +\item \tcode{codecvt_utf8}, +\item \tcode{codecvt_utf8_utf16}, +\item \tcode{consume_header}, +\item \tcode{generate_header}, and +\item \tcode{little_endian}. +\end{itemize} + \rSec1[diff.cpp20]{\Cpp{} and ISO \CppXX{}} \rSec2[diff.cpp20.general]{General} @@ -202,10 +343,12 @@ \libheaderrefx{flat_map}{flat.map.syn}, \libheaderrefx{flat_set}{flat.set.syn}, \libheaderref{generator}, +\libheaderref{mdspan}, \libheaderref{print}, \libheaderref{spanstream}, -\libheaderref{stacktrace}, and -\libheaderref{stdatomic.h}. +\libheaderref{stacktrace}, +\libheaderref{stdatomic.h}, and +\libheaderref{stdfloat}. Valid \CppXX{} code that \tcode{\#include}{s} headers with these names may be invalid in this revision of \Cpp{}. @@ -1809,6 +1952,27 @@ revision of \Cpp{} because \tcode{double} to \tcode{int} is a narrowing conversion. +\diffref{dcl.link} +\change +Names declared in an anonymous namespace +changed from external linkage to internal linkage; +language linkage applies to names with external linkage only. +\rationale +Alignment with user expectations. +\effect +Valid \CppIII{} code may violate the one-definition rule\iref{basic.def.odr} +in this revision of \Cpp{}. +For example: +\begin{codeblock} +namespace { extern "C" { extern int x; } } // \#1, previously external linkage and C language linkage, + // now internal linkage and \Cpp{} language linkage +namespace A { extern "C" int x = 42; } // \#2, external linkage and C language linkage +int main(void) { return x; } +\end{codeblock} +This code is valid in \CppIII{}, +but \tcode{\#2} is not a definition for \tcode{\#1} +in this revision of \Cpp{}, violating the one-definition rule. + \rSec2[diff.cpp03.class]{\ref{class}: classes} \diffref{class.default.ctor,class.dtor,class.copy.ctor,class.copy.assign} @@ -1899,11 +2063,10 @@ \libheaderref{array}, \libheaderrefx{atomic}{atomics.syn}, \libheaderrefx{chrono}{time.syn}, -\libdeprheaderref{codecvt}, \libheaderrefx{condition_variable}{condition.variable.syn}, \libheaderrefx{forward_list}{forward.list.syn}, \libheaderref{future}, -\libheaderrefx{initializer_list}{initializer.list.syn}, +\libheaderrefx{initiali\-zer_list}{initializer.list.syn}, \libheaderref{mutex}, \libheaderrefx{random}{rand.synopsis}, \libheaderref{ratio}, @@ -2461,6 +2624,35 @@ Some ISO C translators will give a warning if the cast is not used. +\diffref{expr.arith.conv} +\change +Operations mixing a value of an enumeration type and a value of a different +enumeration type or of a floating-point type are not valid. +For example: +\begin{codeblock} +enum E1 { e }; +enum E2 { f }; +int b = e <= 3.7; // valid in C; ill-formed in \Cpp{} +int k = f - e; // valid in C; ill-formed in \Cpp{} +int x = 1 ? e : f; // valid in C; ill-formed in \Cpp{} +\end{codeblock} +\rationale +Reinforcing type safety in \Cpp{}. +\effect +Well-formed C code will not compile with this International Standard. +\difficulty +Violations will be diagnosed by the \Cpp{} translator. +The original behavior can be restored with a cast or integral promotion. +For example: +\begin{codeblock} +enum E1 { e }; +enum E2 { f }; +int b = (int)e <= 3.7; +int k = +f - e; +\end{codeblock} +\howwide +Uncommon. + \diffref{expr.post.incr,expr.pre.incr} \change Decrement operator is not allowed with \keyword{bool} operand. @@ -2768,7 +2960,7 @@ \rationale In \Cpp{}, members are destroyed in reverse construction order and the elements of an initializer list are evaluated in lexical order, -so field initializers must be specified in order. +so member initializers must be specified in order. Array designators conflict with \grammarterm{lambda-expression} syntax. Nested designators are seldom used. \effect diff --git a/source/config.tex b/source/config.tex index 40e1c26954..e80dc71ea2 100644 --- a/source/config.tex +++ b/source/config.tex @@ -1,8 +1,8 @@ %!TEX root = std.tex %%-------------------------------------------------- %% Version numbers -\newcommand{\docno}{N4964} -\newcommand{\prevdocno}{N4958} +\newcommand{\docno}{N4971} +\newcommand{\prevdocno}{N4964} \newcommand{\cppver}{202302L} %% Release date diff --git a/source/containers.tex b/source/containers.tex index 00e07cefd0..3644b97916 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -856,6 +856,26 @@ then the operations described below are implemented by constexpr functions. +% Local command to index a name as a member of all containers. +\renewcommand{\indexcont}[1]{% +\indexlibrarymisc{\idxcode{#1}}{optional container requirements}% +\indexlibrarymemberx{array}{#1}% +\indexlibrarymemberx{deque}{#1}% +\indexlibrarymemberx{forward_list}{#1}% +\indexlibrarymemberx{list}{#1}% +\indexlibrarymemberx{vector}{#1}% +\indexlibrarymemberx{map}{#1}% +\indexlibrarymemberx{set}{#1}% +\indexlibrarymemberx{multiset}{#1}% +\indexlibrarymemberx{multimap}{#1}% +\indexlibrarymemberx{flat_map}{#1}% +\indexlibrarymemberx{flat_set}{#1}% +\indexlibrarymemberx{flat_multiset}{#1}% +\indexlibrarymemberx{flat_multimap}{#1}% +\indexlibrarymemberx{basic_string}{#1}% +} + +\indexcont{operator<=>}% \begin{itemdecl} a <=> b \end{itemdecl} @@ -867,7 +887,7 @@ \pnum \expects -Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, +Either \tcode{T} models \libconcept{three_way_comparable}, or \tcode{<} is defined for values of type (possibly const) \tcode{T} and \tcode{<} is a total ordering relationship. @@ -888,7 +908,8 @@ \rSec3[container.alloc.reqmts]{Allocator-aware containers} \pnum -All of the containers defined in \ref{containers} and in~\ref{basic.string} except \tcode{array} +Except for \tcode{array}, all of the containers defined in \ref{containers}, +\ref{stacktrace.basic}, \ref{basic.string}, and \ref{re.results} meet the additional requirements of an \defnadj{allocator-aware}{container}, as described below. @@ -898,7 +919,9 @@ and an \tcode{allocator_type} identical to \tcode{allocator_traits::rebind_alloc} and given an lvalue \tcode{m} of type \tcode{A}, a pointer \tcode{p} of type \tcode{T*}, -an expression \tcode{v} of type \tcode{T} or \tcode{const T}, +an expression \tcode{v} that denotes +an lvalue of type \tcode{T} or \tcode{const T} or +an rvalue of type \tcode{const T}, and an rvalue \tcode{rv} of type \tcode{T}, the following terms are defined. If \tcode{X} is not allocator-aware or is a specialization of \tcode{basic_string}, @@ -1253,24 +1276,6 @@ \tcode{flat_multiset}s, out of the basic sequence container kinds (or out of other program-defined sequence containers). -\pnum -\begin{note} -The sequence containers -offer the programmer different complexity trade-offs. -\tcode{vector} -is appropriate in most circumstances. -\tcode{array} -has a fixed size known during translation. -\tcode{list} or \tcode{forward_list} -support frequent insertions and deletions from the -middle of the sequence. -\tcode{deque} -supports efficient insertions and deletions taking place at the beginning or at the -end of the sequence. -When choosing a container, remember \tcode{vector} is best; -leave a comment to explain if you choose from the rest! -\end{note} - \pnum In this subclause, \begin{itemize} @@ -5970,12 +5975,13 @@ \indexheader{array}% \begin{codeblock} +// mostly freestanding #include // see \ref{compare.syn} #include // see \ref{initializer.list.syn} namespace std { // \ref{array}, class template \tcode{array} - template struct array; + template struct array; // partially freestanding template constexpr bool operator==(const array& x, const array& y); @@ -6206,7 +6212,7 @@ for operations where there is additional semantic information. \pnum -\tcode{array} is a structural type\iref{temp.param} if +\tcode{array} is a structural type\iref{term.structural.type} if \tcode{T} is a structural type. Two values \tcode{a1} and \tcode{a2} of type \tcode{array} are template-argument-equivalent\iref{temp.type} if and only if @@ -6268,8 +6274,8 @@ // element access constexpr reference operator[](size_type n); constexpr const_reference operator[](size_type n) const; - constexpr reference at(size_type n); - constexpr const_reference at(size_type n) const; + constexpr reference at(size_type n); // freestanding-deleted + constexpr const_reference at(size_type n) const; // freestanding-deleted constexpr reference front(); constexpr const_reference front() const; constexpr reference back(); @@ -13682,6 +13688,10 @@ template struct uses_allocator, Alloc>; + // \ref{container.adaptors.format}, formatter specialization for \tcode{queue} + template Container> + struct formatter, charT>; + // \ref{priority.queue}, class template \tcode{priority_queue} template, class Compare = less> @@ -13692,6 +13702,10 @@ priority_queue& y) noexcept(noexcept(x.swap(y))); template struct uses_allocator, Alloc>; + + // \ref{container.adaptors.format}, formatter specialization for \tcode{priority_queue} + template Container, class Compare> + struct formatter, charT>; } \end{codeblock} @@ -13726,6 +13740,10 @@ void swap(stack& x, stack& y) noexcept(noexcept(x.swap(y))); template struct uses_allocator, Alloc>; + + // \ref{container.adaptors.format}, formatter specialization for \tcode{stack} + template Container> + struct formatter, charT>; } \end{codeblock} @@ -18203,13 +18221,16 @@ \indexheader{span}% \begin{codeblock} +#include // see \ref{initializer.list.syn} + +// mostly freestanding namespace std { // constants inline constexpr size_t @\libglobal{dynamic_extent}@ = numeric_limits::max(); // \ref{views.span}, class template \tcode{span} template - class span; + class span; // partially freestanding template constexpr bool ranges::@\libspec{enable_view}{span}@> = true; @@ -18274,6 +18295,7 @@ constexpr span(const array& arr) noexcept; template constexpr explicit(extent != dynamic_extent) span(R&& r); + constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); constexpr span(const span& other) noexcept = default; template constexpr explicit(@\seebelow@) span(const span& s) noexcept; @@ -18300,6 +18322,7 @@ // \ref{span.elem}, element access constexpr reference operator[](size_type idx) const; + constexpr reference at(size_type idx) const; // freestanding-deleted constexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; @@ -18340,6 +18363,12 @@ \tcode{ElementType} is required to be a complete object type that is not an abstract class type. +\pnum +For a \tcode{span} \tcode{s}, +any operation that invalidates a pointer in +the range \range{s.data()}{s.data() + s.size()} +invalidates pointers, iterators, and references to elements of \tcode{s}. + \rSec4[span.cons]{Constructors, copy, and assignment} \indexlibraryctor{span}% @@ -18450,7 +18479,7 @@ \begin{itemdescr} \pnum \constraints -Let \tcode{U} be \tcode{remove_pointer_t}. +Let \tcode{U} be \tcode{remove_pointer_t}. \begin{itemize} \item \tcode{extent == dynamic_extent || N == extent} is \tcode{true}, and \item \tcode{is_convertible_v} is \tcode{true}. @@ -18469,7 +18498,7 @@ \pnum \ensures -\tcode{size() == N \&\& data() == data(arr)} is \tcode{true}. +\tcode{size() == N \&\& data() == std::data(arr)} is \tcode{true}. \end{itemdescr} \indexlibraryctor{span}% @@ -18518,6 +18547,27 @@ What and when \tcode{ranges::data(r)} and \tcode{ranges::size(r)} throw. \end{itemdescr} +\indexlibraryctor{span}% +\begin{itemdecl} +constexpr explicit(extent != dynamic_extent) span(std::initializer_list il); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_const_v} is \tcode{true}. + +\pnum +\expects +If \tcode{extent} is not equal to \tcode{dynamic_extent}, then +\tcode{il.size()} is equal to \tcode{extent}. + +\pnum +\effects +Initializes \exposid{data_} with \tcode{il.begin()} and +\exposid{size_} with \tcode{il.size()}. +\end{itemdescr} + \indexlibraryctor{span}% \begin{itemdecl} constexpr span(const span& other) noexcept = default; @@ -18791,6 +18841,21 @@ Equivalent to: \tcode{return *(data() + idx);} \end{itemdescr} +\indexlibrarymember{span}{at}% +\begin{itemdecl} +constexpr reference at(size_type idx) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{*(data() + idx)}. + +\pnum +\throws +\tcode{out_of_range} if \tcode{idx >= size()} is \tcode{true}. +\end{itemdescr} + \indexlibrarymember{span}{front}% \begin{itemdecl} constexpr reference front() const; @@ -18973,6 +19038,7 @@ \indexheader{mdspan}% \begin{codeblock} +// all freestanding namespace std { // \ref{mdspan.extents}, class template \tcode{extents} template @@ -19003,6 +19069,9 @@ template struct submdspan_mapping_result; + struct full_extent_t { explicit full_extent_t() = default; }; + inline constexpr full_extent_t full_extent{}; + template constexpr auto submdspan_extents(const extents&, SliceSpecifiers...); @@ -21447,7 +21516,7 @@ is \tcode{true}. Equivalent to: \begin{codeblock} -return operator[](as_const(indices[P])...); +return operator[](extents_type::@\exposid{index-cast}@(as_const(indices[P]))...); \end{codeblock} \end{itemdescr} diff --git a/source/declarations.tex b/source/declarations.tex index 8951eb2715..709ee00a69 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -77,7 +77,7 @@ \begin{bnf} \nontermdef{static_assert-message}\br unevaluated-string\br - conditional-expression + constant-expression \end{bnf} \begin{bnf} @@ -291,7 +291,7 @@ the program is ill-formed, and \item if the \grammarterm{static_assert-message} is -a \grammarterm{conditional-expression} $M$, +a \grammarterm{constant-expression} $M$, \begin{itemize} \item \tcode{$M$.size()} shall be a converted constant expression of @@ -331,8 +331,8 @@ } void g(char c) { - f(0); // OK - f(c); // error on implementations where \tcode{sizeof(int) > 1}: must be \tcode{int}-sized + f(0); // OK + f(c); // error on implementations where \tcode{sizeof(int) > 1}: must be \tcode{int}-sized } \end{codeblock} \end{example} @@ -813,6 +813,7 @@ the declaration of a function or function template. A function or static data member declared with the \keyword{constexpr} or \keyword{consteval} specifier +on its first declaration is implicitly an inline function or variable\iref{dcl.inline}. If any declaration of a function or function template has a \keyword{constexpr} or \keyword{consteval} specifier, @@ -1285,7 +1286,7 @@ \nontermdef{simple-type-specifier}\br \opt{nested-name-specifier} type-name\br nested-name-specifier \keyword{template} simple-template-id\br - decltype-specifier\br + computed-type-specifier\br placeholder-type-specifier\br \opt{nested-name-specifier} template-name\br \keyword{char}\br @@ -1311,6 +1312,12 @@ typedef-name \end{bnf} +\begin{bnf} +\nontermdef{computed-type-specifier}\br + decltype-specifier\br + pack-index-specifier +\end{bnf} + \pnum \indextext{component name} The component names of a \grammarterm{simple-type-specifier} are those of its @@ -1382,6 +1389,7 @@ \grammarterm{type-name} & the type named \\ \grammarterm{simple-template-id} & the type as defined in~\ref{temp.names}\\ \grammarterm{decltype-specifier} & the type as defined in~\ref{dcl.type.decltype}\\ +\grammarterm{pack-index-specifier} & the type as defined in~\ref{dcl.type.pack.index}\\ \grammarterm{placeholder-type-specifier} & the type as defined in~\ref{dcl.spec.auto}\\ \grammarterm{template-name} & the type as defined in~\ref{dcl.type.class.deduct}\\ @@ -1431,6 +1439,32 @@ forces \tcode{char} objects to be signed; it is redundant in other contexts. \end{note} +\rSec3[dcl.type.pack.index]{Pack indexing specifier} + +\begin{bnf} +\nontermdef{pack-index-specifier}\br + typedef-name \terminal{...} \terminal{[} constant-expression \terminal{]} +\end{bnf} + +\pnum +The \grammarterm{typedef-name} $P$ in a \grammarterm{pack-index-specifier} +shall denote a pack. + +\pnum +The \grammarterm{constant-expression} shall be +a converted constant expression\iref{expr.const} of type \tcode{std::size_t} +whose value $V$, termed the index, +is such that $0 \le V < \tcode{sizeof...($P$)}$. + +\pnum +A \grammarterm{pack-index-specifier} is a pack expansion\iref{temp.variadic}. + +\pnum +\begin{note} +The \grammarterm{pack-index-specifier} denotes +the type of the $V^\text{th}$ element of the pack. +\end{note} + \rSec3[dcl.type.elab]{Elaborated type specifiers}% \indextext{type specifier!elaborated}% \indextext{\idxcode{typename}}% @@ -1604,6 +1638,13 @@ decltype(i) x2; // type is \tcode{int} decltype(a->x) x3; // type is \tcode{double} decltype((a->x)) x4 = x3; // type is \tcode{const double\&} + +void f() { + [](auto ...pack) { + decltype(pack...[0]) x5; // type is \tcode{int} + decltype((pack...[0])) x6; // type is \tcode{int\&} + }(0); +} \end{codeblock} \end{example} \begin{note} @@ -2162,7 +2203,7 @@ it is as if a unique identifier were included in the appropriate place\iref{dcl.name}. The preceding specifiers indicate -the type, storage class or other properties +the type, storage duration, linkage, or other properties of the entity or entities being declared. Each declarator specifies one entity and (optionally) names it and/or @@ -2366,7 +2407,6 @@ \begin{bnf} \nontermdef{noptr-abstract-pack-declarator}\br noptr-abstract-pack-declarator parameters-and-qualifiers\br - noptr-abstract-pack-declarator \terminal{[} \opt{constant-expression} \terminal{]} \opt{attribute-specifier-seq}\br \terminal{...} \end{bnf} @@ -2402,8 +2442,11 @@ \end{example} \pnum -A type can also be named (often more easily) by using a -\tcode{typedef}\iref{dcl.typedef}. +\begin{note} +A type can also be named by a \grammarterm{typedef-name}, +which is introduced by a typedef declaration +or \grammarterm{alias-declaration}\iref{dcl.typedef}. +\end{note} \rSec2[dcl.ambig.res]{Ambiguity resolution}% \indextext{ambiguity!declaration versus cast}% @@ -2754,7 +2797,8 @@ \tcode{D} where \tcode{D} -is an unadorned name, the type of the declared entity is +is an unadorned \grammarterm{declarator-id}, +the type of the declared entity is ``\tcode{T}''. \pnum @@ -4022,9 +4066,7 @@ of a function declaration or \grammarterm{lambda-declarator} or in a -\grammarterm{template-parameter}\iref{temp.param}; -in the latter case, the \grammarterm{initializer-clause} shall be an -\grammarterm{assignment-expression}. +\grammarterm{template-parameter}\iref{temp.param}. A default argument shall not be specified for a template parameter pack or a function parameter pack. @@ -4477,7 +4519,10 @@ \item If \tcode{T} -is an array type, each element is default-initialized. +is an array type, +the semantic constraints of default-initializing a hypothetical element +shall be met and +each element is default-initialized. \item Otherwise, @@ -4516,9 +4561,10 @@ an object of type \tcode{T} means: + \begin{itemize} \item -if +If \tcode{T} is a (possibly cv-qualified) class type\iref{class}, then \begin{itemize} @@ -4530,15 +4576,19 @@ otherwise, the object is zero-initialized and the semantic constraints for default-initialization are checked, and if \tcode{T} has a -non-trivial default constructor, the object is default-initialized; +non-trivial default constructor, the object is default-initialized. \end{itemize} + \item -if +If \tcode{T} -is an array type, then each element is value-initialized; +is an array type, +the semantic constraints of value-initializing a hypothetical element +shall be met and +each element is value-initialized. \item -otherwise, the object is zero-initialized. +Otherwise, the object is zero-initialized. \end{itemize} \pnum @@ -5084,6 +5134,7 @@ \pnum The destructor for each element of class type +other than an anonymous union member is potentially invoked\iref{class.dtor} from the context where the aggregate initialization occurs. \begin{note} @@ -5656,11 +5707,10 @@ \end{example} \item -Otherwise: +Otherwise, \tcode{T1} shall not be reference-related to \tcode{T2}. \begin{itemize} \item -If \tcode{T1} or \tcode{T2} is a class type and -\tcode{T1} is not reference-related to \tcode{T2}, +If \tcode{T1} or \tcode{T2} is a class type, user-defined conversions are considered using the rules for copy-initialization of an object of type ``\cvqual{cv1} \tcode{T1}'' by @@ -5679,24 +5729,6 @@ and the reference is bound to the result. \end{itemize} -If -\tcode{T1} -is reference-related to -\tcode{T2}: -\begin{itemize} -\item -\cvqual{cv1} -shall be the same cv-qualification as, or greater cv-qualification than, -\cvqual{cv2}; and -\item -if the reference is an rvalue reference, -the initializer expression shall not be an lvalue. -\begin{note} -This can be affected by -whether the initializer expression is move-eligible\iref{expr.prim.id.unqual}. -\end{note} -\end{itemize} - \begin{example} \begin{codeblock} struct Banana { }; @@ -5717,9 +5749,10 @@ const int& r3 = a; // error: cv-qualifier dropped // from result of conversion function double d2 = 1.0; -double&& rrd2 = d2; // error: initializer is lvalue of related type +double&& rrd2 = d2; // error: initializer is lvalue of reference-related type struct X { operator int&(); }; -int&& rri2 = X(); // error: result of conversion function is lvalue of related type +int&& rri2 = X(); // error: result of conversion function is + // lvalue of reference-related type int i3 = 2; double&& rrd3 = i3; // \tcode{rrd3} refers to temporary with value \tcode{2.0} \end{codeblock} @@ -5765,6 +5798,7 @@ \item in a \tcode{return} statement\iref{stmt.return} \item as a \grammarterm{for-range-initializer}\iref{stmt.iter} \item as a function argument\iref{expr.call} +\item as a template argument\iref{temp.arg.nontype} \item as a subscript\iref{expr.sub} \item as an argument to a constructor invocation\iref{dcl.init,expr.type.conv} \item as an initializer for a non-static data member\iref{class.mem} @@ -5909,7 +5943,7 @@ \item Otherwise, if \tcode{T} is an enumeration with a fixed underlying type\iref{dcl.enum} \tcode{U}, -the \grammarterm{initializer-list} has a single element \tcode{v}, +the \grammarterm{initializer-list} has a single element \tcode{v} of scalar type, \tcode{v} can be implicitly converted to \tcode{U}, and the initialization is direct-list-initialization, the object is initialized with the value \tcode{T(v)}\iref{expr.type.conv}; @@ -6055,8 +6089,9 @@ \end{note} If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. -Whether all backing arrays are distinct -(that is, are stored in non-overlapping objects) is unspecified. +\begin{note} +Backing arrays are potentially non-unique objects\iref{intro.object}. +\end{note} \pnum The backing array has the same lifetime as any other temporary @@ -6219,7 +6254,12 @@ \end{bnf} Any informal reference to the body of a function should be interpreted as a reference to -the non-terminal \grammarterm{function-body}. +the non-terminal \grammarterm{function-body}, +including, for a constructor, +default member initializers or default initialization +used to initialize +a base or member subobject in the absence of +a \grammarterm{mem-initializer-id}\iref{class.base.init}. The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{function-definition} appertains to the function. A \grammarterm{virt-specifier-seq} can be part of a \grammarterm{function-definition} @@ -6380,6 +6420,9 @@ is implicitly inline\iref{dcl.inline}, and is implicitly constexpr\iref{dcl.constexpr} if it is constexpr-suitable. +\begin{note} +Other defaulted functions are not implicitly constexpr. +\end{note} \pnum \begin{example} @@ -6602,10 +6645,10 @@ where $\tcode{p}_1$ denotes the object parameter and $\tcode{p}_{i+1}$ denotes the $i^\text{th}$ non-object function parameter -for a non-static member function, and +for an implicit object member function, and $\tcode{p}_i$ denotes the $i^\text{th}$ function parameter otherwise. -For a non-static member function, +For an implicit object member function, $\tcode{q}_1$ is an lvalue that denotes \tcode{*this}; any other $\tcode{q}_i$ is an lvalue that denotes the parameter copy corresponding to $\tcode{p}_i$, @@ -6739,7 +6782,7 @@ the \tcode{::operator new(size_t, nothrow_t)} form is used. The allocation function used in this case shall have a non-throwing \grammarterm{noexcept-specifier}. -If the allocation function returns \keyword{nullptr}, the coroutine returns +If the allocation function returns \keyword{nullptr}, the coroutine transfers control to the caller of the coroutine and the return value is obtained by a call to \tcode{T::get_return_object_on_allocation_failure()}, where \tcode{T} is the promise type. @@ -7101,12 +7144,11 @@ An \grammarterm{enumerator-definition} with \tcode{=} gives the associated \grammarterm{enumerator} the value indicated by the \grammarterm{constant-expression}. -If the first \grammarterm{enumerator} -has no \grammarterm{initializer}, the value of the corresponding constant -is zero. An \grammarterm{enumerator-definition} without an -\grammarterm{initializer} gives the \grammarterm{enumerator} the value -obtained by increasing the value of the previous \grammarterm{enumerator} -by one. +An \grammarterm{enumerator-definition} without \tcode{=} gives the associated +\grammarterm{enumerator} the value zero +if it is the first \grammarterm{enumerator-definition}, +and the value of the previous \grammarterm{enumerator} +increased by one otherwise. \begin{example} \begin{codeblock} enum { a, b, c=0 }; @@ -8483,7 +8525,7 @@ \keyword{extern} specifier\iref{dcl.stc} for the purpose of determining the linkage of the declared name and whether it is a definition. Such a declaration shall -not specify a storage class. +not have a \grammarterm{storage-class-specifier}. \begin{example} \begin{codeblock} extern "C" double f(); @@ -9127,15 +9169,18 @@ \pnum The \grammarterm{attribute-token} \tcode{maybe_unused} -indicates that a name or entity is possibly intentionally unused. +indicates that a name, label, or entity is possibly intentionally unused. No \grammarterm{attribute-argument-clause} shall be present. \pnum The attribute may be applied to the declaration of a class, -a \grammarterm{typedef-name}, -a variable (including a structured binding declaration), -a non-static data member, -a function, an enumeration, or an enumerator. +\grammarterm{typedef-name}, +variable (including a structured binding declaration), +non-static data member, +function, +enumeration, or +enumerator, or +to an \grammarterm{identifier} label\iref{stmt.label}. \pnum A name or entity declared without the \tcode{maybe_unused} attribute @@ -9153,6 +9198,8 @@ For a structured binding declaration not marked \tcode{maybe_unused}, implementations should not emit such a warning unless all of its structured bindings are unused. +For a label to which \tcode{maybe_unused} is applied, +implementations should not emit a warning that the label is used or unused. The value of a \grammarterm{has-attribute-expression} for the \tcode{maybe_unused} attribute should be \tcode{0} @@ -9165,9 +9212,13 @@ [[maybe_unused]] bool thing2) { [[maybe_unused]] bool b = thing1 && thing2; assert(b); +#ifdef NDEBUG + goto x; +#endif + [[maybe_unused]] x: } \end{codeblock} -Implementations should not warn that \tcode{b} is unused, +Implementations should not warn that \tcode{b} or \tcode{x} is unused, whether or not \tcode{NDEBUG} is defined. \end{example} diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 12a3cb75b0..1b4ce24a75 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -451,25 +451,57 @@ \pnum The header \libheaderdef{cassert} provides a macro for documenting \Cpp{} program assertions and a mechanism -for disabling the assertion checks. +for disabling the assertion checks through defining the macro \tcode{NDEBUG}. \rSec2[cassert.syn]{Header \tcode{} synopsis} \indexlibraryglobal{assert}% \begin{codeblock} -#define assert(E) @\seebelow@ +#define assert(...) @\seebelow@ \end{codeblock} +\rSec2[assertions.assert]{The \tcode{assert} macro} + \pnum -\indextext{static_assert@\tcode{static_assert}!not macro}% -The contents are the same as the C standard library header -\libheader{assert.h}, -except that a macro named \keyword{static_assert} -is not defined. +If \tcode{NDEBUG} is defined as a macro name +at the point in the source file where \tcode{} is included, +the \tcode{assert} macro is defined as +\begin{codeblock} +#define assert(...) ((void)0) +\end{codeblock} -\xrefc{7.2} +\pnum +Otherwise, the \tcode{assert} macro puts a diagnostic test into programs; +it expands to an expression of type \keyword{void} which +has the following effects: -\rSec2[assertions.assert]{The \tcode{assert} macro} +\begin{itemize} +\item +\mname{VA_ARGS} is evaluated and contextually converted to \tcode{bool}. +\item +If the evaluation yields \tcode{true} there are no further effects. +\item +Otherwise, the \tcode{assert} macro's expression +creates a diagnostic on the standard error stream in an +\impldef{format of diagnostic created by \tcode{assert} macro's expression} +format and calls \tcode{abort()}. +The diagnostic contains \tcode{\#}\mname{VA_ARGS} and +information on +the name of the source file, +the source line number, and +the name of the enclosing function +(such as provided by \tcode{source_location::current()}). +\end{itemize} + +\pnum +If \mname{VA_ARGS} does not expand to +an \grammarterm{assignment-expression}, +the program is ill-formed. + +\pnum +The macro \tcode{assert} is redefined according to +the current state of \tcode{NDEBUG} each time that +\tcode{} is included. \pnum An expression \tcode{assert(E)} @@ -2400,7 +2432,7 @@ Equivalent to: \tcode{return os << to_string(st);} \end{itemdescr} -\rSec3[stacktrace.format]{Formatting support} +\rSec2[stacktrace.format]{Formatting support} \begin{itemdecl} template<> struct formatter; @@ -2442,7 +2474,7 @@ copying \tcode{to_string(s)} through the output iterator of the context. \end{itemdescr} -\rSec3[stacktrace.basic.hash]{Hash support} +\rSec2[stacktrace.basic.hash]{Hash support} \begin{itemdecl} template<> struct hash; diff --git a/source/exceptions.tex b/source/exceptions.tex index c4cc789ff9..8dc2fcbc05 100644 --- a/source/exceptions.tex +++ b/source/exceptions.tex @@ -421,7 +421,8 @@ \end{note} \indextext{subobject!initialized, known to be}% A subobject is \defn{known to be initialized} -if its initialization is specified +if it is not an anonymous union member and +its initialization is specified \begin{itemize} \item in \ref{class.base.init} for initialization by constructor, \item in \ref{class.copy.ctor} for initialization by defaulted copy/move constructor, diff --git a/source/expressions.tex b/source/expressions.tex index 3229ed4d8b..e4c80eef64 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -272,9 +272,11 @@ applied to convert the expression to an xvalue. \pnum +\begin{note} The discussion of reference initialization in~\ref{dcl.init.ref} and of temporaries in~\ref{class.temporary} indicates the behavior of lvalues and rvalues in other significant contexts. +\end{note} \pnum Unless otherwise indicated\iref{dcl.type.decltype}, @@ -1142,6 +1144,9 @@ \item If either operand is of scoped enumeration type\iref{dcl.enum}, no conversions are performed; if the other operand does not have the same type, the expression is ill-formed. +\item Otherwise, if one operand is of enumeration type and the other operand is +of a different enumeration type or a floating-point type, the expression is +ill-formed. \item Otherwise, if either operand is of floating-point type, the following rules are applied: \begin{itemize} @@ -1195,13 +1200,6 @@ \end{itemize} \end{itemize} -\pnum -If one operand is of enumeration type -and the other operand is of -a different enumeration type or -a floating-point type, -this behavior is deprecated\iref{depr.arith.conv.enum}. - \rSec1[expr.prim]{Primary expressions}% \indextext{expression!primary|(} @@ -1323,7 +1321,8 @@ \begin{bnf} \nontermdef{id-expression}\br unqualified-id\br - qualified-id + qualified-id\br + pack-index-expression \end{bnf} \pnum @@ -1428,7 +1427,7 @@ conversion-function-id\br literal-operator-id\br \terminal{\~} type-name\br - \terminal{\~} decltype-specifier\br + \terminal{\~} computed-type-specifier\br template-id \end{bnf} @@ -1445,7 +1444,7 @@ \grammarterm{conversion-function-id}{s}, see~\ref{class.conv.fct}; for \grammarterm{literal-operator-id}{s}, see~\ref{over.literal}; for \grammarterm{template-id}{s}, see~\ref{temp.names}. -A \grammarterm{type-name} or \grammarterm{decltype-specifier} +A \grammarterm{type-name} or \grammarterm{computed-type-specifier} prefixed by \tcode{\~} denotes the destructor of the type so named; see~\ref{expr.prim.id.dtor}. Within the definition of a non-static member function, an @@ -1593,7 +1592,7 @@ \terminal{::}\br type-name \terminal{::}\br namespace-name \terminal{::}\br - decltype-specifier \terminal{::}\br + computed-type-specifier \terminal{::}\br nested-name-specifier identifier \terminal{::}\br nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::} \end{bnf} @@ -1631,8 +1630,8 @@ \pnum The \grammarterm{nested-name-specifier} \tcode{::} nominates the global namespace. -A \grammarterm{nested-name-specifier} with a \grammarterm{decltype-specifier} -nominates the type denoted by the \grammarterm{decltype-specifier}, +A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier} +nominates the type denoted by the \grammarterm{computed-type-specifier}, which shall be a class or enumeration type. If a \grammarterm{nested-name-specifier} $N$ is declarative and @@ -1664,9 +1663,9 @@ \pnum A \grammarterm{qualified-id} shall not be of the form \grammarterm{nested-name-specifier} \opt{\keyword{template}} \tcode{\~} -\grammarterm{decltype-specifier} +\grammarterm{computed-type-specifier} nor of the form -\grammarterm{decltype-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}. +\grammarterm{computed-type-specifier} \tcode{::} \tcode{\~} \grammarterm{type-name}. \pnum The result of a \grammarterm{qualified-id} $Q$ is @@ -1688,6 +1687,32 @@ \end{itemize} and a prvalue otherwise. +\rSec3[expr.prim.pack.index]{Pack indexing expression} + +\begin{bnf} +\nontermdef{pack-index-expression}\br + id-expression \terminal{...} \terminal{[} constant-expression \terminal{]} +\end{bnf} + +\pnum +The \grammarterm{id-expression} $P$ in a \grammarterm{pack-index-expression} +shall be an \grammarterm{identifier} that denotes a pack. + +\pnum +The \grammarterm{constant-expression} shall be +a converted constant expression\iref{expr.const} of type \tcode{std::size_t} +whose value $V$, termed the index, +is such that $0 \le V < \tcode{sizeof...($P$)}$. + +\pnum +A \grammarterm{pack-index-expression} is a pack expansion\iref{temp.variadic}. + +\pnum +\begin{note} +A \grammarterm{pack-index-expression} denotes +the $V^\text{th}$ element of the pack. +\end{note} + \rSec3[expr.prim.id.dtor]{Destruction} \pnum @@ -1875,7 +1900,7 @@ \pnum The closure type is not an aggregate type\iref{dcl.init.aggr} and -not a structural type\iref{temp.param}. +not a structural type\iref{term.structural.type}. An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing: @@ -2869,8 +2894,10 @@ \pnum The substitution of template arguments into a \grammarterm{requires-expression} -may result in the formation of invalid types or expressions in its -\grammarterm{requirement}s or the violation of the semantic constraints of those \grammarterm{requirement}s. +can result in +the formation of invalid types or expressions in the immediate context of +its \grammarterm{requirement}s\iref{temp.deduct.general} or +the violation of the semantic constraints of those \grammarterm{requirement}s. In such cases, the \grammarterm{requires-expression} evaluates to \keyword{false}; it does not cause the program to be ill-formed. The substitution and semantic constraint checking @@ -2890,7 +2917,7 @@ \begin{codeblock} template concept C = requires { - new int[-(int)sizeof(T)]; // ill-formed, no diagnostic required + new decltype((void)T{}); // ill-formed, no diagnostic required }; \end{codeblock} \end{example} @@ -2938,6 +2965,8 @@ \pnum A \grammarterm{type-requirement} asserts the validity of a type. +The component names of a \grammarterm{type-requirement} are those of its +\grammarterm{nested-name-specifier} (if any) and \grammarterm{type-name}. \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments fails. @@ -3615,6 +3644,8 @@ ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. \item If \tcode{E2} is an overload set, +the expression shall be the (possibly-parenthesized) left-hand operand of +a member function call\iref{expr.call}, and function overload resolution\iref{over.match} is used to select the function to which \tcode{E2} refers. The type of \tcode{E1.E2} is the type of \tcode{E2} @@ -3625,8 +3656,7 @@ \tcode{E1.E2} is an lvalue. \item Otherwise (when \tcode{E2} refers to a non-static member function), -\tcode{E1.E2} is a prvalue. The expression can be used only as the -left-hand operand of a member function call\iref{class.mfct}. +\tcode{E1.E2} is a prvalue. \begin{note} Any redundant set of parentheses surrounding the expression is ignored\iref{expr.prim.paren}. @@ -4359,7 +4389,7 @@ \indextext{cast!reference}% \indextext{type pun}% A glvalue of type \tcode{T1}, -designating an object \placeholder{x}, +designating an object or function \placeholder{x}, can be cast to the type ``reference to \tcode{T2}'' if an expression of type ``pointer to \tcode{T1}'' can be explicitly converted to the type ``pointer to \tcode{T2}'' @@ -4553,8 +4583,10 @@ \indextext{dereferencing|see{indirection}}% Its operand shall be a prvalue of type ``pointer to \tcode{T}'', where \tcode{T} is an object or function type. -The operator yields an lvalue of type \tcode{T} -denoting the object or function to which the operand points. +The operator yields an lvalue of type \tcode{T}. +If the operand points to an object or function, +the result denotes that object or function; +otherwise, the behavior is undefined except as specified in \ref{expr.typeid}. \begin{note} \indextext{type!incomplete}% Indirection through a pointer to an incomplete type (other than @@ -4687,14 +4719,14 @@ \end{note} There is an ambiguity in the grammar when \tcode{\~{}} is followed by -a \grammarterm{type-name} or \grammarterm{decltype-specifier}. +a \grammarterm{type-name} or \grammarterm{computed-type-specifier}. The ambiguity is resolved by treating \tcode{\~{}} as the operator rather than as the start of an \grammarterm{unqualified-id} naming a destructor. \begin{note} Because the grammar does not permit an operator to follow the \tcode{.}, \tcode{->}, or \tcode{::} tokens, a \tcode{\~{}} followed by -a \grammarterm{type-name} or \grammarterm{decltype-specifier} in a +a \grammarterm{type-name} or \grammarterm{computed-type-specifier} in a member access expression or \grammarterm{qualified-id} is unambiguously parsed as a destructor name. \end{note} @@ -4742,6 +4774,8 @@ The \keyword{co_await} expression is used to suspend evaluation of a coroutine\iref{dcl.fct.def.coroutine} while awaiting completion of the computation represented by the operand expression. +Suspending the evaluation of a coroutine +transfers control to its caller or resumer. \begin{bnf} \nontermdef{await-expression}\br @@ -5002,7 +5036,7 @@ \begin{codeblock} template struct count { - static const std::size_t value = sizeof...(Types); + static constexpr std::size_t value = sizeof...(Types); }; \end{codeblock} \end{example} @@ -5046,31 +5080,29 @@ \rSec3[expr.unary.noexcept]{\tcode{noexcept} operator} -\pnum \indextext{\idxcode{noexcept}}% \indextext{expression!\idxcode{noexcept}}% -The \keyword{noexcept} operator determines whether the evaluation of its operand, -which is an unevaluated operand\iref{term.unevaluated.operand}, can throw an -exception\iref{except.throw}. \begin{bnf} \nontermdef{noexcept-expression}\br \keyword{noexcept} \terminal{(} expression \terminal{)} \end{bnf} +\pnum +The operand of the \keyword{noexcept} operator +is an unevaluated operand\iref{term.unevaluated.operand}. +If the operand is a prvalue, +the temporary materialization conversion\iref{conv.rval} is applied. + \pnum The result of the \keyword{noexcept} operator is a prvalue of type \keyword{bool}. +The result is \tcode{false} if +the full-expression of the operand is potentially-throwing\iref{except.spec}, and +\tcode{true} otherwise. \begin{note} A \grammarterm{noexcept-expression} is an integral constant expression\iref{expr.const}. \end{note} - -\pnum -If the operand is a prvalue, -the temporary materialization conversion\iref{conv.rval} is applied. -The result of the \keyword{noexcept} operator is \keyword{true} -unless the full-expression of the operand -is potentially-throwing\iref{except.spec}. \indextext{expression!unary|)} \rSec3[expr.new]{New} @@ -5137,7 +5169,9 @@ \end{bnf} \pnum -If a placeholder type\iref{dcl.spec.auto} appears in the +If a placeholder type\iref{dcl.spec.auto} or +a placeholder for a deduced class type\iref{dcl.type.class.deduct} +appears in the \grammarterm{type-specifier-seq} of a \grammarterm{new-type-id} or \grammarterm{type-id} of a \grammarterm{new-expression}, the allocated type is deduced as follows: @@ -5285,6 +5319,21 @@ When the value of the \grammarterm{expression} is zero, the allocation function is called to allocate an array with no elements. +\pnum +If the allocated type is an array, +the \grammarterm{new-initializer} is a \grammarterm{braced-init-list}, and +the \grammarterm{expression} +is potentially-evaluated and not a core constant expression, +the semantic constraints of copy-initializing a hypothetical element of +the array from an empty initializer list +are checked\iref{dcl.init.list}. +\begin{note} +The array can contain more elements than there are +elements in the \grammarterm{braced-init-list}, +requiring initialization of the remainder of the array elements from +an empty initializer list. +\end{note} + \pnum \indextext{storage duration!dynamic}% Objects created by a \grammarterm{new-expression} have dynamic storage @@ -5583,10 +5632,6 @@ \grammarterm{new-expression}. \pnum -If the \grammarterm{new-expression} creates an object or an array of -objects of class type, access and ambiguity control are done for the -allocation function, the deallocation function\iref{basic.stc.dynamic.deallocation}, and -the constructor\iref{class.ctor} selected for the initialization (if any). If the \grammarterm{new-expression} creates an array of objects of class type, the destructor is potentially invoked\iref{class.dtor}. @@ -5636,6 +5681,9 @@ ill-formed. For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function\iref{expr.delete}. +In any case, +the matching deallocation function (if any) shall be non-deleted and +accessible from the point where the \grammarterm{new-expression} appears. \begin{example} \begin{codeblock} struct S { @@ -5769,9 +5817,12 @@ null pointer value and the selected deallocation function (see below) is not a destroying operator delete, -the \grammarterm{delete-expression} will invoke the +evaluating the \grammarterm{delete-expression} invokes the destructor (if any) for the object or the elements of the array being -deleted. In the case of an array, the elements will be destroyed in +deleted. +The destructor shall be accessible from the point where +the \grammarterm{delete-expression} appears. +In the case of an array, the elements are destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see~\ref{class.base.init}). @@ -5852,8 +5903,7 @@ \end{note} \pnum -If more than one deallocation function is found, -the function to be called is selected as follows: +The deallocation the function to be called is selected as follows: \begin{itemize} \item If any of the deallocation functions is a destroying operator delete, @@ -5882,6 +5932,10 @@ whether a deallocation function with a parameter of type \tcode{std::size_t} is selected. \end{itemize} +Unless the deallocation function is selected +at the point of definition of the dynamic type's virtual destructor, +the selected deallocation function shall be accessible +from the point where the \grammarterm{delete-expression} appears. \pnum For a single-object delete expression, @@ -5935,10 +5989,6 @@ the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} -\pnum -Access and ambiguity control are done for both the deallocation function -and the destructor\iref{class.dtor,class.free}. - \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -6530,8 +6580,10 @@ \pnum The usual arithmetic conversions\iref{expr.arith.conv} are performed on operands of arithmetic -or enumeration type. If both operands are pointers, pointer -conversions\iref{conv.ptr} and qualification conversions\iref{conv.qual} +or enumeration type. If both operands are pointers, +pointer conversions\iref{conv.ptr}, +function pointer conversions\iref{conv.fctptr}, and +qualification conversions\iref{conv.qual} are performed to bring them to their composite pointer type\iref{expr.type}. After conversions, the operands shall have the same type. @@ -6574,8 +6626,10 @@ Otherwise, the result of each of the operators is unspecified. \begin{note} A relational operator applied -to unequal function pointers or to unequal pointers to \tcode{void} +to unequal function pointers yields an unspecified result. +A pointer value of type ``pointer to \cv{}~\keyword{void}'' +can point to an object\iref{basic.compound}. \end{note} \pnum @@ -7229,17 +7283,22 @@ \end{note} \pnum -A \grammarterm{braced-init-list} may appear on the right-hand side of +A \grammarterm{braced-init-list} $B$ may appear on the right-hand side of + \begin{itemize} -\item an assignment to a scalar, in which case the initializer list shall have -at most a single element. The meaning of \tcode{x = \{v\}}, where \tcode{T} is the -scalar type of the expression \tcode{x}, is that of \tcode{x = T\{v\}}. The meaning of -\tcode{x = \{\}} is \tcode{x = T\{\}}. +\item +an assignment to a scalar of type \tcode{T}, in which case $B$ +shall have at most a single element. +The meaning of \tcode{x = $B$} is \tcode{x = t}, +where \tcode{t} is an invented temporary variable +declared and initialized as \tcode{T t = $B$}. -\item an assignment to an object of class type, in which case the initializer -list is passed as the argument to the assignment operator function selected by +\item +an assignment to an object of class type, in which case $B$ +is passed as the argument to the assignment operator function selected by overload resolution\iref{over.ass,over.match}. \end{itemize} + \begin{example} \begin{codeblock} complex z; @@ -7422,7 +7481,7 @@ \item an operation that would have undefined behavior as specified in \ref{intro} through \ref{cpp}, -excluding \ref{dcl.attr.assume}; +excluding \ref{dcl.attr.assume} and \ref{dcl.attr.noreturn}; \begin{footnote} This includes, for example, signed integer overflow\iref{expr.pre}, certain @@ -7498,7 +7557,8 @@ \item a conversion from a prvalue \tcode{P} of type ``pointer to \cv{}~\keyword{void}'' -to a pointer-to-object type \tcode{T} +to a type ``\cvqual{cv1} pointer to \tcode{T}'', +where \tcode{T} is not \cvqual{cv2}~\keyword{void}, unless \tcode{P} points to an object whose type is similar to \tcode{T}; \item @@ -7578,6 +7638,7 @@ \end{note} \end{itemize} +\pnum It is unspecified whether $E$ is a core constant expression if $E$ satisfies the constraints of a core constant expression, but evaluation of $E$ would evaluate @@ -7586,7 +7647,12 @@ an operation that has undefined behavior as specified in \ref{library} through \ref{\lastlibchapter}, \item -an invocation of the \tcode{va_start} macro\iref{cstdarg.syn}, or +an invocation of the \tcode{va_start} macro\iref{cstdarg.syn}, +\item +a call to a function +that was previously declared +with the \tcode{noreturn} attribute\iref{dcl.attr.noreturn} and +that call returns to its caller, or \item a statement with an assumption\iref{dcl.attr.assume} whose converted \grammarterm{conditional-expression}, @@ -7957,6 +8023,11 @@ whose function body contains an immediate-escalating expression \tcode{\placeholder{E}} such that \tcode{\placeholder{E}}'s innermost enclosing non-block scope is \tcode{\placeholder{F}}'s function parameter scope. +\begin{tailnote} +Default member initializers used to initialize +a base or member subobject\iref{class.base.init} +are considered to be part of the function body\iref{dcl.fct.def.general}. +\end{tailnote} \end{itemize} \begin{example} \begin{codeblock} @@ -8055,7 +8126,8 @@ \end{example} \end{itemize} \begin{note} -A manifestly constant-evaluated expression +Except for a \grammarterm{static_assert-message}, +a manifestly constant-evaluated expression is evaluated even in an unevaluated operand\iref{term.unevaluated.operand}. \end{note} diff --git a/source/future.tex b/source/future.tex index 450109745c..34173964ff 100644 --- a/source/future.tex +++ b/source/future.tex @@ -16,27 +16,6 @@ An implementation may declare library names and entities described in this Clause with the \tcode{deprecated} attribute\iref{dcl.attr.deprecated}. -\rSec1[depr.arith.conv.enum]{Arithmetic conversion on enumerations} - -\pnum -The ability to apply the usual arithmetic conversions\iref{expr.arith.conv} -on operands where one is of enumeration type -and the other is of a different enumeration type -or a floating-point type -is deprecated. -\begin{note} -Three-way comparisons\iref{expr.spaceship} between such operands are ill-formed. -\end{note} -\begin{example} -\begin{codeblock} -enum E1 { e }; -enum E2 { f }; -bool b = e <= 3.7; // deprecated -int k = f - e; // deprecated -auto cmp = e <=> f; // error -\end{codeblock} -\end{example} - \rSec1[depr.capture.this]{Implicit capture of \tcode{*this} by reference} \pnum @@ -1404,22 +1383,6 @@ is the same as the value of the \libheader{cerrno} macro shown in the above synopsis. -\rSec1[depr.default.allocator]{The default allocator} - -\pnum -The following member is defined in addition to those -specified in \ref{default.allocator}: - -\indexlibrarymember{is_always_equal}{allocator}% -\begin{codeblock} -namespace std { - template class allocator { - public: - using is_always_equal = true_type; - }; -} -\end{codeblock} - \rSec1[depr.mem.poly.allocator.mem]{Deprecated \tcode{polymorphic_allocator} member function} \pnum @@ -2032,39 +1995,6 @@ The weak form may fail spuriously. See~\ref{atomics.types.operations}. \end{itemdescr} -\rSec1[depr.string.capacity]{Deprecated \tcode{basic_string} capacity} - -\pnum -The following member is declared in addition to those members specified -in \ref{string.capacity}: - -\indexlibraryglobal{basic_string}% -\begin{codeblock} -namespace std { - template, - class Allocator = allocator> - class basic_string { - public: - void reserve(); - }; -} -\end{codeblock} - -\indexlibrarymember{reserve}{basic_string}% -\begin{itemdecl} -void reserve(); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -After this call, \tcode{capacity()} has an unspecified value -greater than or equal to \tcode{size()}. -\begin{note} -This is a non-binding shrink to fit request. -\end{note} -\end{itemdescr} - \rSec1[depr.format]{Deprecated formatting} \rSec2[depr.format.syn]{Header \tcode{} synopsis} @@ -2093,127 +2023,6 @@ Equivalent to: \tcode{return visit(std::forward(vis), arg.value);} \end{itemdescr} -\rSec1[depr.locale.stdcvt]{Deprecated standard code conversion facets} - -\rSec2[depr.locale.stdcvt.general]{General} - -\pnum -The header \libheaderdef{codecvt} provides -code conversion facets for various character encodings. - -\rSec2[depr.codecvt.syn]{Header \tcode{} synopsis} - -\indexlibraryglobal{codecvt_mode}% -\indexlibraryglobal{codecvt_utf8}% -\indexlibraryglobal{codecvt_utf16}% -\indexlibraryglobal{codecvt_utf8_utf16}% -\begin{codeblock} -namespace std { - enum codecvt_mode { - consume_header = 4, - generate_header = 2, - little_endian = 1 - }; - - template - class codecvt_utf8 : public codecvt { - public: - explicit codecvt_utf8(size_t refs = 0); - ~codecvt_utf8(); - }; - - template - class codecvt_utf16 : public codecvt { - public: - explicit codecvt_utf16(size_t refs = 0); - ~codecvt_utf16(); - }; - - template - class codecvt_utf8_utf16 : public codecvt { - public: - explicit codecvt_utf8_utf16(size_t refs = 0); - ~codecvt_utf8_utf16(); - }; -} -\end{codeblock} - -\rSec2[depr.locale.stdcvt.req]{Requirements} - -\pnum -For each of the three code conversion facets \tcode{codecvt_utf8}, -\tcode{codecvt_utf16}, and \tcode{codecvt_utf8_utf16}: -\begin{itemize} -\item - \tcode{Elem} is the wide-character type, such as - \keyword{wchar_t}, \keyword{char16_t}, or \keyword{char32_t}. -\item - \tcode{Maxcode} is the largest wide-character code that the facet - will read or write without reporting a conversion error. -\item - If \tcode{(Mode \& consume_header)}, the facet shall consume an - initial header sequence, if present, when reading a multibyte sequence - to determine the endianness of the subsequent multibyte sequence to be read. -\item - If \tcode{(Mode \& generate_header)}, the facet shall generate an - initial header sequence when writing a multibyte sequence to advertise - the endianness of the subsequent multibyte sequence to be written. -\item - If \tcode{(Mode \& little_endian)}, the facet shall generate a - multibyte sequence in little-endian order, - as opposed to the default big-endian order. -\item - UCS-2 is the same encoding as UTF-16, - except that it encodes scalar values in the range - \ucode{0000}--\ucode{ffff} (Basic Multilingual Plane) only. -\end{itemize} - -\pnum -\indextext{UTF-8}% -\indextext{UCS-2}% -\indextext{UTF-32}% -For the facet \tcode{codecvt_utf8}\indexlibraryglobal{codecvt_utf8}: -\begin{itemize} -\item - The facet shall convert between UTF-8 multibyte sequences - and UCS-2 or UTF-32 (depending on the size of \tcode{Elem}). -\item - Endianness shall not affect how multibyte sequences are read or written. -\item - The multibyte sequences may be written as either a text or a binary file. -\end{itemize} - -\pnum -\indextext{UTF-16}% -\indextext{UCS-2}% -\indextext{UTF-32}% -For the facet \tcode{codecvt_utf16}\indexlibraryglobal{codecvt_utf16}: -\begin{itemize} -\item - The facet shall convert between UTF-16 multibyte sequences - and UCS-2 or UTF-32 (depending on the size of \tcode{Elem}). -\item - Multibyte sequences shall be read or written - according to the \tcode{Mode} flag, as set out above. -\item - The multibyte sequences may be written only as a binary file. - Attempting to write to a text file produces undefined behavior. -\end{itemize} - -\pnum -\indextext{UTF-8}% -\indextext{UTF-16}% -For the facet \tcode{codecvt_utf8_utf16}\indexlibraryglobal{codecvt_utf8_utf16}: -\begin{itemize} -\item - The facet shall convert between UTF-8 multibyte sequences - and UTF-16 (one or two 16-bit codes) within the program. -\item - Endianness shall not affect how multibyte sequences are read or written. -\item - The multibyte sequences may be written as either a text or a binary file. -\end{itemize} - \rSec1[depr.conversions]{Deprecated convenience conversion interfaces} \rSec2[depr.conversions.general]{General} @@ -2242,12 +2051,12 @@ (like class template \tcode{codecvt}) to perform the conversions, without affecting any streams or locales. \begin{example} -If you want to use the code -conversion facet \tcode{codecvt_utf8} to output to \tcode{cout} a UTF-8 +If you want to use a code +conversion facet, \tcode{codecvt_for_utf8}, to output to \tcode{cout} a UTF-8 multibyte sequence corresponding to a wide string, but you don't want to alter the locale for \tcode{cout}, you can write something like: \begin{codeblock} -std::wstring_convert> myconv; +std::wstring_convert> myconv; std::string mbstring = myconv.to_bytes(L"Hello\n"); std::cout << mbstring; \end{codeblock} diff --git a/source/intro.tex b/source/intro.tex index b241e4fd36..a4fff15300 100644 --- a/source/intro.tex +++ b/source/intro.tex @@ -34,8 +34,7 @@ \begin{itemize} % ISO documents in numerical order. \item ISO/IEC 2382, \doccite{Information technology --- Vocabulary} -\item ISO 8601:2004, \doccite{Data elements and interchange formats --- -Information interchange --- Representation of dates and times} +\item ISO 8601-1:2019, \doccite{Date and time --- Representations for information interchange --- Part 1: Basic rules} \item \IsoC{}, \doccite{Information technology --- Programming languages --- C} \item ISO/IEC/IEEE 9945:2009, \doccite{Information Technology --- Portable Operating System Interface (POSIX @@ -69,14 +68,6 @@ The Unicode Consortium. \doccite{The Unicode Standard}. Available from: \url{https://www.unicode.org/versions/latest/} \end{itemize} - -\pnum -The operating system interface described in ISO/IEC 9945:2009 is -hereinafter called \defn{POSIX}. - -\pnum -The ECMAScript Language Specification described in Standard Ecma-262 is -hereinafter called \defn{ECMA-262}. \indextext{references!normative|)} \rSec0[intro.defs]{Terms and definitions} @@ -85,9 +76,7 @@ \indextext{definitions|(}% For the purposes of this document, the terms and definitions -given in ISO/IEC 2382, -the terms, definitions, and symbols -given in ISO 80000-2:2009, +given in ISO/IEC 2382 and ISO 80000-2:2009, and the following apply. \pnum @@ -188,22 +177,23 @@ \defncontext{library} \indexdefn{type!character container}% class or a type used to -represent a character +represent a \termref{defns.character}{character}{} \begin{defnote} -It is used for one of the template parameters of the string, -iostream, and regular expression class templates. +It is used for one of the template parameters of \tcode{char_traits} +and the class templates which use that, +such as the string, iostream, and regular expression class templates. \end{defnote} \definition{collating element}{defns.regex.collating.element} \indexdefn{collating element}% -sequence of one or more characters within the +sequence of one or more \termref{defns.character}{character}{s} within the current locale that collate as if they were a single character \definition{component}{defns.component} \defncontext{library} \indexdefn{component}% -group of library entities directly related as members, parameters, or +group of library entities directly related as members, \termref{defns.parameter}{parameter}{s}, or return types \begin{defnote} @@ -233,13 +223,13 @@ \indexdefn{deadlock}% situation wherein one or more threads are unable to continue execution because each is -blocked waiting for one or more of the others to satisfy some condition +\termref{defns.block}{block}{ed} waiting for one or more of the others to satisfy some condition \definition{default behavior}{defns.default.behavior.impl} \indexdefn{behavior!default}% \defncontext{library implementation} specific behavior provided by the implementation, -within the scope of the required behavior +within the scope of the \termref{defns.required.behavior}{required behavior}{} \indexdefn{message!diagnostic}% \definition{diagnostic message}{defns.diagnostic} @@ -261,7 +251,7 @@ \indexdefn{type!dynamic}% \definition{dynamic type}{defns.dynamic.type.prvalue} -\defncontext{prvalue} static type of the prvalue expression +\defncontext{prvalue} \termref{defns.static.type}{static type}{} of the prvalue expression \definition{expression-equivalent}{defns.expression.equivalent} \defncontext{library} @@ -272,7 +262,7 @@ are all not potentially-throwing, and either -are all constant subexpressions or +are all \termref{defns.const.subexpr}{constant subexpression}{s} or are all not constant subexpressions \begin{example} @@ -290,14 +280,14 @@ \defncontext{regular expression} \indexdefn{finite state machine}% unspecified data structure that is used to -represent a regular expression, and which permits efficient matches +represent a \termref{defns.regex.regular.expression}{regular expression}{}, and which permits efficient matches against the regular expression to be obtained \definition{format specifier}{defns.regex.format.specifier} \defncontext{regular expression} \indexdefn{format specifier}% -sequence of one or more characters that is to be -replaced with some part of a regular expression match +sequence of one or more \termref{defns.character}{character}{s} that is to be +replaced with some part of a \termref{defns.regex.regular.expression}{regular expression}{} match \definition{handler function}{defns.handler} \defncontext{library} @@ -316,7 +306,7 @@ \indexdefn{behavior!implementation-defined}% \definition{implementation-defined behavior}{defns.impl.defined} -behavior, for a well-formed program construct and correct data, that +behavior, for a \termref{defns.well.formed}{well-formed program}{} construct and correct data, that depends on the implementation and that each implementation documents \definition{implementation-defined strict total order over pointers} @@ -342,7 +332,7 @@ \defncontext{regular expression} \indexdefn{matched}% \indexdefn{regular expression!matched}% -condition when a sequence of zero or more characters +condition when a sequence of zero or more \termref{defns.character}{character}{s} correspond to a sequence of characters defined by the pattern \definition{modifier function}{defns.modifier} @@ -373,7 +363,7 @@ \indexdefn{NTCTS}% \indexdefn{string!null-terminated character type}% sequence of values that have -character type +\termref{defns.character}{character}{} type that precede the terminating null character type value \tcode{charT()} @@ -413,7 +403,7 @@ \definition{primary equivalence class}{defns.regex.primary.equivalence.class} \defncontext{regular expression} \indexdefn{primary equivalence class}% -set of one or more characters which +set of one or more \termref{defns.character}{character}{s} which share the same primary sort key: that is the sort key weighting that depends only upon character shape, and not accents, case, or locale specific tailorings @@ -432,7 +422,7 @@ that is not part of the \Cpp{} standard library and not defined by the implementation, or a closure type of a non-implementation-provided lambda expression, -or an instantiation of a program-defined specialization +or an instantiation of a \termref{defns.prog.def.spec}{program-defined specialization}{} \begin{defnote} Types defined by the implementation include @@ -469,7 +459,7 @@ \definition{regular expression}{defns.regex.regular.expression} pattern that selects specific strings -from a set of character strings +from a set of \termref{defns.character}{character}{} strings \definition{replacement function}{defns.replacement} \defncontext{library} @@ -486,7 +476,8 @@ \definition{required behavior}{defns.required.behavior} \defncontext{library} \indexdefn{behavior!required}% -description of replacement function and handler function semantics +description of \termref{defns.replacement}{replacement function}{} +and \termref{defns.handler}{handler function}{} semantics applicable to both the behavior provided by the implementation and the behavior of any such function definition in the program @@ -535,7 +526,7 @@ parameter-type-list, enclosing namespace, return type, -signature of the \grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) @@ -546,14 +537,14 @@ parameter-type-list, return type, enclosing class, -signature of the \grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) \indexdefn{signature}% \definition{signature}{defns.signature.spec} -\defncontext{function template specialization} signature of the template of which it is a specialization -and its template arguments (whether explicitly specified or deduced) +\defncontext{function template specialization} \termref{defns.signature.templ}{signature}{} of the template of which it is a specialization +and its template \termref{defns.argument.templ}{argument}{s} (whether explicitly specified or deduced) \indexdefn{signature}% \definition{signature}{defns.signature.member} @@ -575,20 +566,20 @@ \cv-qualifiers (if any), \grammarterm{ref-qualifier} (if any), return type (if any), -signature of the \grammarterm{template-head}, +\termref{defns.signature.template.head}{signature}{} of the \grammarterm{template-head}, and trailing \grammarterm{requires-clause} (if any) \indexdefn{signature}% \definition{signature}{defns.signature.member.spec} -\defncontext{class member function template specialization} signature of the member function template +\defncontext{class member function template specialization} \termref{defns.signature.member.templ}{signature}{} of the member function template of which it is a specialization and its template arguments (whether explicitly specified or deduced) \indexdefn{signature}% \definition{signature}{defns.signature.template.head} \defncontext{\grammarterm{template-head}} -template parameter list, -excluding template parameter names and default arguments, +template \termref{defns.parameter.templ}{parameter}{} list, +excluding template parameter names and default \termref{defns.argument.templ}{argument}{s}, and \grammarterm{requires-clause} (if any) @@ -617,7 +608,7 @@ \definition{sub-expression}{defns.regex.subexpression} \defncontext{regular expression} \indexdefn{sub-expression!regular expression}% -subset of a regular expression that has +subset of a \termref{defns.regex.regular.expression}{regular expression}{} that has been marked by parentheses \definition{traits class}{defns.traits} @@ -628,7 +619,7 @@ \indexdefn{unblock}% \definition{unblock}{defns.unblock} -satisfy a condition that one or more blocked threads of execution are waiting for +satisfy a condition that one or more \termref{defns.block}{block}{ed} threads of execution are waiting for \indexdefn{behavior!undefined}% \definition{undefined behavior}{defns.undefined} @@ -643,7 +634,7 @@ from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a -diagnostic message), to terminating a translation or execution (with the +\termref{defns.diagnostic}{diagnostic message}{}), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression\iref{expr.const} never exhibits behavior explicitly @@ -652,7 +643,7 @@ \indexdefn{behavior!unspecified}% \definition{unspecified behavior}{defns.unspecified} -behavior, for a well-formed program construct and correct data, that +behavior, for a \termref{defns.well.formed}{well-formed program}{} construct and correct data, that depends on the implementation \begin{defnote} @@ -856,7 +847,7 @@ \pnum \indextext{behavior!implementation-defined}% Certain aspects and operations of the abstract machine are described in this -document as implementation-defined (for example, +document as implementation-defined behavior (for example, \tcode{sizeof(int)}). These constitute the parameters of the abstract machine. Each implementation shall include documentation describing its characteristics and behavior in these respects. @@ -872,7 +863,7 @@ \pnum \indextext{behavior!unspecified}% Certain other aspects and operations of the abstract machine are -described in this document as unspecified (for example, +described in this document as unspecified behavior (for example, order of evaluation of arguments in a function call\iref{expr.call}). Where possible, this document defines a set of allowable behaviors. These @@ -883,7 +874,7 @@ \pnum \indextext{behavior!undefined}% Certain other operations are described in this document as -undefined (for example, the effect of +undefined behavior (for example, the effect of attempting to modify a const object). \begin{note} This document imposes no requirements on the @@ -961,7 +952,7 @@ \pnum \indextext{notation!syntax|(}% In the syntax notation used in this document, syntactic -categories are indicated by \fakegrammarterm{italic} type, and literal words +categories are indicated by \fakegrammarterm{italic, sans-serif} type, and literal words and characters in \tcode{constant} \tcode{width} type. Alternatives are listed on separate lines except in a few cases where a long set of alternatives is marked by the phrase ``one of''. If the text of an alternative is too long to fit on a line, the text is continued on subsequent lines indented from the first one. diff --git a/source/iostreams.tex b/source/iostreams.tex index 7e1b661fdb..39833d60d3 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -128,8 +128,9 @@ \pnum In the classes of \ref{input.output}, a template parameter with name \tcode{charT} represents a member of the set of types containing \tcode{char}, \keyword{wchar_t}, -and any other \impldef{set of character types that iostreams templates can be instantiated for} -character types that meet the requirements for a character on which any of +and any other \impldef{set of character container types that iostreams templates can be instantiated for} +character container types\iref{defns.character.container} +that meet the requirements for a character on which any of the iostream components can be instantiated. \rSec2[iostreams.threadsafety]{Thread safety} @@ -3096,7 +3097,7 @@ \pnum The class template \tcode{basic_streambuf} -serves as an abstract base class for deriving various +serves as a base class for deriving various \term{stream buffers} whose objects each control two \term{character sequences}: @@ -6361,7 +6362,7 @@ If a formatted output function of a stream \tcode{os} determines padding, it does so as follows. Given a \tcode{charT} character sequence \tcode{seq} where -\tcode{charT} is the character type of the stream, if +\tcode{charT} is the character container type of the stream, if the length of \tcode{seq} is less than \tcode{os.width()}, then enough copies of \tcode{os.fill()} are added to this sequence as necessary to pad to a width of \tcode{os.width()} characters. If @@ -6705,7 +6706,7 @@ of \tcode{out}. Constructs a character sequence \tcode{seq}. If \tcode{c} has type \tcode{char} -and the character type of the stream is not +and the character container type of the stream is not \tcode{char}, then \tcode{seq} consists of \tcode{out.widen(c)}; @@ -6789,11 +6790,11 @@ \effects If the ordinary literal encoding\iref{lex.charset} is UTF-8, equivalent to: \begin{codeblock} -vprint_unicode(os, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_unicode(os, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} Otherwise, equivalent to: \begin{codeblock} -vprint_nonunicode(os, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_nonunicode(os, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -7698,11 +7699,11 @@ \effects If the ordinary literal encoding\iref{lex.charset} is UTF-8, equivalent to: \begin{codeblock} -vprint_unicode(stream, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_unicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} Otherwise, equivalent to: \begin{codeblock} -vprint_nonunicode(stream, fmt.@\exposid{str}@, make_format_args(std::forward(args)...)); +vprint_nonunicode(stream, fmt.@\exposid{str}@, make_format_args(args...)); \end{codeblock} \end{itemdescr} @@ -9588,7 +9589,7 @@ void str(const T& t); private: - basic_stringbuf sb; // \expos + basic_stringbuf sb; // \expos }; } \end{codeblock} diff --git a/source/iterators.tex b/source/iterators.tex index ae0947e7f2..1a7b67109a 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -694,8 +694,9 @@ do not specify complexity. \pnum -Destruction of a non-forward iterator may invalidate pointers and references -previously obtained from that iterator. +Destruction of an iterator may invalidate pointers and references previously +obtained from that iterator if its type does not meet the +\oldconcept{ForwardIterator} requirements and does not model \libconcept{forward_iterator}. \pnum An \defnadj{invalid}{iterator} @@ -2213,7 +2214,7 @@ \pnum A class or pointer type \tcode{X} -meets the requirements of a forward iterator if +meets the \oldconcept{ForwardIterator} requirements if \begin{itemize} \item \tcode{X} meets the \oldconcept{InputIterator} requirements\iref{input.iterators}, @@ -4287,6 +4288,13 @@ template<@\libconcept{sentinel_for}@ S> constexpr bool operator==(const S& s) const; + template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ + constexpr operator CI() const &; + template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ + constexpr operator CI() &&; + constexpr bool operator<(const basic_const_iterator& y) const requires @\libconcept{random_access_iterator}@; constexpr bool operator>(const basic_const_iterator& y) const @@ -4589,6 +4597,30 @@ Equivalent to: \tcode{return \exposid{current_} == s;} \end{itemdescr} +\begin{itemdecl} +template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ +constexpr operator CI() const &; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\exposid{current_}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{not-a-const-iterator}@ CI> + requires @\exposconcept{constant-iterator}@ && @\libconcept{convertible_to}@ +constexpr operator CI() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{std::move(\exposid{current_})}. +\end{itemdescr} + \indexlibrarymember{operator<}{basic_const_iterator}% \indexlibrarymember{operator>}{basic_const_iterator}% \indexlibrarymember{operator<=}{basic_const_iterator}% @@ -5457,7 +5489,7 @@ friend constexpr iter_difference_t operator-( const common_iterator& x, const common_iterator& y); - friend constexpr iter_rvalue_reference_t iter_move(const common_iterator& i) + friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval()))) requires @\libconcept{input_iterator}@; template<@\libconcept{indirectly_swappable}@ I2, class S2> @@ -5476,7 +5508,7 @@ template<@\libconcept{input_iterator}@ I, class S> struct iterator_traits> { using iterator_concept = @\seebelow@; - using iterator_category = @\seebelow@; + using iterator_category = @\seebelow@; // not always present using value_type = iter_value_t; using difference_type = iter_difference_t; using pointer = @\seebelow@; @@ -5488,22 +5520,25 @@ \rSec3[common.iter.types]{Associated types} \pnum -The nested \grammarterm{typedef-name}s of the specialization of -\tcode{iterator_traits} for \tcode{common_iterator} are defined as follows. +The nested \grammarterm{typedef-name} \tcode{iterator_category} of +the specialization of \tcode{iterator_traits} for \tcode{common_iterator} +is defined if and only if \tcode{iter_difference_t} is an integral type. +In that case, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag} if +the \grammarterm{qualified-id} \tcode{iterator_traits::iterator_category} +is valid and denotes a type that +models \tcode{\libconcept{derived_from}}; +otherwise it denotes \tcode{input_iterator_tag}. + +\pnum +The remaining nested \grammarterm{typedef-name}s of the specialization of +\tcode{iterator_traits} for \tcode{common_iterator} are defined as follows: \begin{itemize} \item \tcode{iterator_concept} denotes \tcode{forward_iterator_tag} if \tcode{I} models \libconcept{forward_iterator}; otherwise it denotes \tcode{input_iterator_tag}. -\item -\tcode{iterator_category} denotes -\tcode{forward_iterator_tag} -if the \grammarterm{qualified-id} \tcode{iterator_traits::iter\-ator_category} -is valid and denotes a type that -models \tcode{\libconcept{derived_from}}; -otherwise it denotes \tcode{input_iterator_tag}. - \item Let \tcode{a} denote an lvalue of type \tcode{const common_iterator}. If the expression \tcode{a.operator->()} is well-formed, @@ -5796,7 +5831,7 @@ \indexlibrarymember{iter_move}{common_iterator}% \begin{itemdecl} -friend constexpr iter_rvalue_reference_t iter_move(const common_iterator& i) +friend constexpr decltype(auto) iter_move(const common_iterator& i) noexcept(noexcept(ranges::iter_move(declval()))) requires @\libconcept{input_iterator}@; \end{itemdecl} @@ -5955,7 +5990,7 @@ friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator& y); - friend constexpr iter_rvalue_reference_t iter_move(const counted_iterator& i) + friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires @\libconcept{input_iterator}@; template<@\libconcept{indirectly_swappable}@ I2> @@ -6383,7 +6418,7 @@ \indexlibrarymember{iter_move}{counted_iterator}% \begin{itemdecl} -friend constexpr iter_rvalue_reference_t +friend constexpr decltype(auto) iter_move(const counted_iterator& i) noexcept(noexcept(ranges::iter_move(i.current))) requires @\libconcept{input_iterator}@; @@ -7211,6 +7246,8 @@ headers are included: \libheaderref{array}, \libheaderref{deque}, +\libheaderrefx{flat_map}{flat.map.syn}, +\libheaderrefx{flat_set}{flat.set.syn}, \libheaderrefx{forward_list}{forward.list.syn}, \libheaderref{list}, \libheaderrefx{map}{associative.map.syn}, diff --git a/source/lex.tex b/source/lex.tex index b4b81cf407..41d0e4702d 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -112,8 +112,8 @@ Line splicing can form a \grammarterm{universal-character-name}\iref{lex.charset}. \end{note} -A source file that is not empty and that does not end in a new-line -character, or that ends in a splice, +A source file that is not empty and that (after splicing) +does not end in a new-line character shall be processed as if an additional new-line character were appended to the file. @@ -1955,11 +1955,12 @@ \pnum Evaluating a \grammarterm{string-literal} results in a string literal object with static storage duration\iref{basic.stc}. -\indextext{string!distinct}% -Whether all \grammarterm{string-literal}s are distinct (that is, are stored in -nonoverlapping objects) and whether successive evaluations of a +\begin{note} +String literal objects are potentially non-unique\iref{intro.object}. +Whether successive evaluations of a \grammarterm{string-literal} yield the same or a different object is unspecified. +\end{note} \begin{note} \indextext{literal!string!undefined change to}% The effect of attempting to modify a string literal object is undefined. diff --git a/source/lib-intro.tex b/source/lib-intro.tex index fb8f7eee5a..0594db6039 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -45,6 +45,10 @@ \ref{thread} & Concurrency support library \\ \end{floattable} +\pnum +The operating system interface described in ISO/IEC/IEEE 9945:2009 is +hereinafter called \defn{POSIX}. + \pnum The language support library\iref{support} provides components that are required by certain parts of the \Cpp{} language, @@ -897,29 +901,62 @@ Unless otherwise specified, the requirements on freestanding items for a freestanding implementation are the same as the corresponding requirements for a hosted implementation, -except that not all of the members of the namespaces are required to be present. +except that not all of the members of those items are required to be present. + +\pnum +Function declarations and function template declarations +followed by a comment that include \textit{freestanding-deleted} are +\defnadjx{freestanding deleted}{functions}{function}. +On freestanding implementations, +it is \impldef{whether a freestanding deleted function is a deleted function} +whether each entity introduced by a freestanding deleted function +is a deleted function\iref{dcl.fct.def.delete} or +whether the requirements are the same as +the corresponding requirements for a hosted implementation. \begin{note} -This implies that freestanding item enumerations have the same enumerators on -freestanding implementations and hosted implementations. -Furthermore, class types have the same members and -class templates have the same deduction guides -on freestanding implementations and hosted implementations. +Deleted definitions reduce the chance of overload resolution silently changing +when migrating from a freestanding implementation to a hosted implementation. \end{note} +\begin{example} +\begin{codeblock} +double abs(double j); // freestanding-deleted +\end{codeblock} +\end{example} \pnum \indextext{declaration!freestanding item}% -A declaration in a header synopsis is a freestanding item if +A declaration in a synopsis is a freestanding item if \begin{itemize} -\item it is followed by a comment that includes \textit{freestanding}, or -\item the header synopsis begins with a comment that includes \textit{all freestanding}. +\item it is followed by a comment that includes \textit{freestanding}, +\item it is followed by a comment that includes \textit{freestanding-deleted}, or +\item the header synopsis begins with a comment +that includes \textit{freestanding} and +the declaration is not followed by a comment that includes \textit{hosted}. +\begin{note} +Declarations followed by \textit{hosted} in freestanding headers are +not freestanding items. +As a result, looking up the name of such functions can vary +between hosted and freestanding implementations. +\end{note} \end{itemize} +\begin{example} +\begin{codeblock} +// all freestanding +namespace std { +\end{codeblock} +\end{example} \pnum \indextext{entity!freestanding item}% +\indextext{deduction guide!freestanding item}% \indextext{\idxgram{typedef-name}!freestanding item}% -An entity or \grammarterm{typedef-name} is a freestanding item if it is: +An entity, deduction guide, or \grammarterm{typedef-name} is +a freestanding item if it is: \begin{itemize} \item introduced by a declaration that is a freestanding item, +\item a member of a freestanding item other than a namespace, +\item an enumerator of a freestanding item, +\item a deduction guide of a freestanding item, \item an enclosing namespace of a freestanding item, \item a friend of a freestanding item, \item denoted by a \grammarterm{typedef-name} that is a freestanding item, or @@ -930,35 +967,40 @@ \indextext{macro!freestanding item}% A macro is a freestanding item if it is defined in a header synopsis and \begin{itemize} -\item the definition is followed by a comment that includes \textit{freestanding}, or -\item the header synopsis begins with a comment that includes \textit{all freestanding}. +\item the definition is followed by a comment +that includes \textit{freestanding}, or +\item the header synopsis begins with a comment +that includes \textit{freestanding} and +the definition is not followed by a comment that includes \textit{hosted}. \end{itemize} - -\pnum \begin{example} \begin{codeblock} #define NULL @\seebelow@ // freestanding \end{codeblock} \end{example} -\begin{example} -\begin{codeblock} -// all freestanding -namespace std { -\end{codeblock} -\end{example} - \pnum -Function declarations and function template declarations -followed by a comment that include \textit{freestanding-deleted} are -\defnadjx{freestanding deleted}{functions}{function}. -On freestanding implementations, -it is \impldef{whether a freestanding deleted function is a freestanding item or a deleted function} -whether each function definition introduced by a freestanding deleted function -is a freestanding item or a deleted function\iref{dcl.fct.def.delete}. +\begin{note} +Freestanding annotations follow some additional exposition conventions +that do not impose any additional normative requirements. +Header synopses that begin with a comment containing "all freestanding" +contain no hosted items and no freestanding deleted functions. +Header synopses that begin with a comment containing "mostly freestanding" +contain at least one hosted item or freestanding deleted function. +Classes and class templates followed by a comment +containing "partially freestanding" +contain at least one hosted item or freestanding deleted function. +\end{note} \begin{example} \begin{codeblock} -double abs(double j); // freestanding-deleted +template struct array; // partially freestanding +template +struct array { + constexpr reference operator[](size_type n); + constexpr const_reference operator[](size_type n) const; + constexpr reference at(size_type n); // freestanding-deleted + constexpr const_reference at(size_type n) const; // freestanding-deleted +}; \end{codeblock} \end{example} @@ -1084,12 +1126,12 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1097,8 +1139,8 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ -\tcode{} \\ \columnbreak +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1114,6 +1156,7 @@ \tcode{} \\ \tcode{} \\ \tcode{} \\ +\tcode{} \\ \tcode{} \\ \tcode{} \\ \tcode{} \\ @@ -1481,15 +1524,24 @@ \ref{ratio} & Compile-time rational arithmetic & \tcode{} \\ \rowsep \ref{utility} & Utility components & \tcode{} \\ \rowsep \ref{tuple} & Tuples & \tcode{} \\ \rowsep +\ref{optional} & Optional objects & \tcode{} \\ \rowsep +\ref{variant} & Variants & \tcode{} \\ \rowsep +\ref{expected} & Expected objects & \tcode{} \\ \rowsep \ref{function.objects} & Function objects & \tcode{} \\ \rowsep \ref{charconv} & Primitive numeric conversions & \tcode{} \\ \rowsep \ref{bit} & Bit manipulation & \tcode{} \\ \rowsep +\ref{string.view} & String view classes & \tcode{} \\ \rowsep \ref{string.classes} & String classes & \tcode{} \\ \rowsep \ref{c.strings} & Null-terminated sequence utilities & \tcode{}, \tcode{} \\ \rowsep +\ref{array} & Class template \tcode{array} & \tcode{} \\ \rowsep +\ref{views.contiguous} & Contiguous access & \tcode{} \\ \rowsep +\ref{views.multidim} & Multidimensional access & \tcode{} \\ \rowsep \ref{iterators} & Iterators library & \tcode{} \\ \rowsep \ref{ranges} & Ranges library & \tcode{} \\ \rowsep +\ref{algorithms} & Algorithms library & \tcode{}, \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & \tcode{} \\ \rowsep \ref{atomics} & Atomics & \tcode{} \\ \rowsep +\ref{debugging} & Debugging & \tcode{} \\ \rowsep \end{libsumtab} \pnum @@ -2568,7 +2620,7 @@ \end{itemdescr} \begin{itemdecl} -a.construct(c, args) +a.construct(c, args...) \end{itemdecl} \begin{itemdescr} @@ -2840,10 +2892,11 @@ any standard library class template to namespace \tcode{std} provided that -(a) the added declaration -depends on at least one program-defined type -and -(b) the specialization meets the standard library requirements +\begin{itemize} +\item the added declaration +depends on at least one program-defined type, and + +\item the specialization meets the standard library requirements for the original template. \begin{footnote} Any @@ -2851,6 +2904,7 @@ must be prepared to work adequately with any user-supplied specialization that meets the minimum requirements of this document. \end{footnote} +\end{itemize} \pnum The behavior of a \Cpp{} program is undefined @@ -2881,10 +2935,12 @@ A program may explicitly instantiate a class template defined in the standard library only if the declaration -(a) depends on the name of at least one program-defined type -and -(b) the instantiation meets the standard library requirements for the +\begin{itemize} +\item depends on the name of at least one program-defined type, and + +\item the instantiation meets the standard library requirements for the original template. +\end{itemize} \pnum Let \tcode{\placeholder{F}} denote @@ -2975,18 +3031,25 @@ \item \indexlibraryzombie{bind2nd} \tcode{bind2nd}, \item \indexlibraryzombie{binder1st} \tcode{binder1st}, \item \indexlibraryzombie{binder2nd} \tcode{binder2nd}, +\item \indexlibraryzombie{codecvt_mode} \tcode{codecvt_mode}, +\item \indexlibraryzombie{codecvt_utf16} \tcode{codecvt_utf16}, +\item \indexlibraryzombie{codecvt_utf8} \tcode{codecvt_utf8}, +\item \indexlibraryzombie{codecvt_utf8_utf16} \tcode{codecvt_utf8_utf16}, \item \indexlibraryzombie{const_mem_fun1_ref_t} \tcode{const_mem_fun1_ref_t}, \item \indexlibraryzombie{const_mem_fun1_t} \tcode{const_mem_fun1_t}, \item \indexlibraryzombie{const_mem_fun_ref_t} \tcode{const_mem_fun_ref_t}, \item \indexlibraryzombie{const_mem_fun_t} \tcode{const_mem_fun_t}, +\item \indexlibraryzombie{consume_header} \tcode{consume_header}, \item \indexlibraryzombie{declare_no_pointers} \tcode{declare_no_pointers}, \item \indexlibraryzombie{declare_reachable} \tcode{declare_reachable}, +\item \indexlibraryzombie{generate_header} \tcode{generate_header}, \item \indexlibraryzombie{get_pointer_safety} \tcode{get_pointer_safety}, \item \indexlibraryzombie{get_temporary_buffer} \tcode{get_temporary_buffer}, \item \indexlibraryzombie{get_unexpected} \tcode{get_unexpected}, \item \indexlibraryzombie{gets} \tcode{gets}, \item \indexlibraryzombie{is_literal_type} \tcode{is_literal_type}, \item \indexlibraryzombie{is_literal_type_v} \tcode{is_literal_type_v}, +\item \indexlibraryzombie{little_endian} \tcode{little_endian}, \item \indexlibraryzombie{mem_fun1_ref_t} \tcode{mem_fun1_ref_t}, \item \indexlibraryzombie{mem_fun1_t} \tcode{mem_fun1_t}, \item \indexlibraryzombie{mem_fun_ref_t} \tcode{mem_fun_ref_t}, @@ -3038,6 +3101,7 @@ The header names \libnoheader{ccomplex}, \libnoheader{ciso646}, +\libnoheader{codecvt}, \libnoheader{cstdalign}, \libnoheader{cstdbool}, and \libnoheader{ctgmath} @@ -3352,7 +3416,7 @@ \item If a function argument is bound to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument, -except that the argument passed to a move-assignment operator may be +except that the argument passed to a move assignment operator may be a reference to \tcode{*this}\iref{lib.types.movedfrom}. \begin{note} If the type of a parameter is a forwarding reference\iref{temp.deduct.call} diff --git a/source/locales.tex b/source/locales.tex index e36f215d68..b196816b96 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -394,9 +394,9 @@ respectively\iref{iterator.requirements}. A template parameter with name \tcode{C} represents the set of types containing \keyword{char}, \keyword{wchar_t}, and any other -\impldef{set of character types +\impldef{set of character container types that iostreams templates can be instantiated for} -character types +character container types\iref{defns.character.container} that meet the requirements for a character on which any of the iostream components can be instantiated. A template parameter with name \tcode{International} @@ -4296,7 +4296,8 @@ \begin{note} For specializations where the second template parameter is \tcode{true}, this is typically four characters long: -a three-letter code as specified by ISO 4217 followed by a space. +a three-letter code as specified by ISO 4217\supercite{iso4217} +followed by a space. \end{note} \end{itemdescr} @@ -4676,7 +4677,7 @@ \pnum The class \tcode{text_encoding} describes an interface -for accessing the IANA Character Sets registry. +for accessing the IANA Character Sets registry\supercite{iana-charset}. \indexlibraryglobal{text_encoding}% \begin{codeblock} @@ -5002,7 +5003,7 @@ \begin{note} This comparison is identical to the ``Charset Alias Matching'' algorithm -described in the Unicode Technical Standard 22. +described in the Unicode Technical Standard 22\supercite{unicode-charmap}. \end{note} \begin{example} diff --git a/source/macros.tex b/source/macros.tex index fd5293136d..079b61a329 100644 --- a/source/macros.tex +++ b/source/macros.tex @@ -64,6 +64,7 @@ %% Cross-references. %%-------------------------------------------------- \newcommand{\addxref}[1]{% + \hypertarget{#1}{}% \glossary[xrefindex]{\indexescape{#1}}{(\ref{\indexescape{#1}})}% } @@ -92,6 +93,7 @@ % defines a first-level section whose name is "Scope" and whose short % tag is intro.scope. The square brackets are mandatory. \def\Sec#1[#2]#3{% +\addxref{#2}% \ifcase#1\let\s=\chapter\let\l=\clauselabel \or\let\s=\section\let\l=\label \or\let\s=\subsection\let\l=\label @@ -99,7 +101,7 @@ \or\let\s=\paragraph\let\l=\label \or\let\s=\subparagraph\let\l=\label \fi% -\s[#3]{#3\hfill[#2]}\l{#2}\addxref{#2}% +\s[#3]{#3\hfill[#2]}\l{#2}% } % A convenience feature (mostly for the convenience of the Project @@ -118,6 +120,11 @@ \addtocounter{SectionDepth}{\value{SectionDepthBase}} \Sec{\arabic{SectionDepth}}[#2]{#3}} +%%-------------------------------------------------- +% Bibliography +%%-------------------------------------------------- +\newcommand{\supercite}[1]{\textsuperscript{\cite{#1}}} + %%-------------------------------------------------- % Indexing %%-------------------------------------------------- @@ -366,6 +373,7 @@ %% Cross-reference \newcommand{\xref}{\textsc{See also:}\space} \newcommand{\xrefc}[1]{\xref{} \IsoC{}, #1} +\newcommand{\termref}[3]{\textit{#2}{#3}\iref{#1}} % in Clause 3 %% Inline comma-separated parenthesized references \ExplSyntaxOn diff --git a/source/memory.tex b/source/memory.tex index 890f431d45..a24a3b4973 100644 --- a/source/memory.tex +++ b/source/memory.tex @@ -570,19 +570,19 @@ // \ref{out.ptr.t}, class template \tcode{out_ptr_t} template - class out_ptr_t; + class out_ptr_t; // freestanding // \ref{out.ptr}, function template \tcode{out_ptr} template - auto out_ptr(Smart& s, Args&&... args); + auto out_ptr(Smart& s, Args&&... args); // freestanding // \ref{inout.ptr.t}, class template \tcode{inout_ptr_t} template - class inout_ptr_t; + class inout_ptr_t; // freestanding // \ref{inout.ptr}, function template \tcode{inout_ptr} template - auto inout_ptr(Smart& s, Args&&... args); + auto inout_ptr(Smart& s, Args&&... args); // freestanding } \end{codeblock} @@ -881,7 +881,7 @@ \begin{itemdescr} \pnum \mandates -\tcode{T} is an implicit-lifetime type\iref{basic.types.general} +\tcode{T} is an implicit-lifetime type\iref{term.implicit.lifetime.type} and not an incomplete type\iref{term.incomplete.type}. \pnum @@ -5451,10 +5451,8 @@ % pretend to \item that there is real text here, but undo the vertical spacing \mbox{}\vspace{-\baselineskip}\vspace{-\parskip} \begin{codeblock} -if (p) { - apply([&](auto&&... args) { - s = Smart( static_cast(p), std::forward(args)...); }, std::move(a)); -} +apply([&](auto&&... args) { + s = Smart(static_cast(p), std::forward(args)...); }, std::move(a)); \end{codeblock} if \tcode{is_pointer_v} is \tcode{true}; \item @@ -6310,7 +6308,7 @@ is greater than an \impldef{largest supported value to configure the maximum number of blocks to replenish a pool} limit, that limit is used instead. The implementation -may choose to use a smaller value than is specified in this field and +may choose to use a smaller value than is specified in this member and may use different values for different pools. \end{itemdescr} @@ -6329,7 +6327,7 @@ is greater than an \impldef{largest supported value to configure the largest allocation satisfied directly by a pool} limit, that limit is used instead. The implementation may choose a pass-through threshold -larger than specified in this field. +larger than specified in this member. \end{itemdescr} \rSec3[mem.res.pool.ctor]{Constructors and destructors} diff --git a/source/meta.tex b/source/meta.tex index 27a2b7b868..17cbbf91dd 100644 --- a/source/meta.tex +++ b/source/meta.tex @@ -1209,7 +1209,7 @@ \indexlibraryglobal{is_implicit_lifetime}% \tcode{template}\br \tcode{struct is_implicit_lifetime;} & - \tcode{T} is an implicit-lifetime type\iref{basic.types.general}. & + \tcode{T} is an implicit-lifetime type\iref{term.implicit.lifetime.type}. & \tcode{T} shall be an array type, a complete type, or \cv{}~\keyword{void}. \\ \rowsep @@ -1407,9 +1407,9 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert(rank_v == 0); -assert(rank_v == 1); -assert(rank_v == 2); +static_assert(rank_v == 0); +static_assert(rank_v == 1); +static_assert(rank_v == 2); \end{codeblock} \end{example} @@ -1417,14 +1417,14 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert(extent_v == 0); -assert(extent_v == 2); -assert(extent_v == 2); -assert(extent_v == 0); -assert((extent_v) == 0); -assert((extent_v) == 0); -assert((extent_v) == 4); -assert((extent_v) == 4); +static_assert(extent_v == 0); +static_assert(extent_v == 2); +static_assert(extent_v == 2); +static_assert(extent_v == 0); +static_assert(extent_v == 0); +static_assert(extent_v == 0); +static_assert(extent_v == 4); +static_assert(extent_v == 4); \end{codeblock} \end{example} @@ -1823,10 +1823,10 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int[3]>)); -assert((is_same_v, int[3]>)); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int[3]>); +static_assert(is_same_v, int[3]>); \end{codeblock} \end{example} @@ -1834,10 +1834,10 @@ \begin{example} \begin{codeblock} // the following assertions hold: -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); -assert((is_same_v, int>)); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); +static_assert(is_same_v, int>); \end{codeblock} \end{example} diff --git a/source/modules.tex b/source/modules.tex index 3d299b553c..52873a37ae 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -639,14 +639,13 @@ \item $D$ is decl-reachable from $M$, or \item -$D$ redeclares the entity declared by $M$ or -$M$ redeclares the entity declared by $D$, +$D$ and $M$ declare the same entity, and $D$ neither is a friend declaration nor inhabits a block scope, or \item $D$ declares a namespace $N$ and $M$ is a member of $N$, or \item -one of $M$ and $D$ declares a class or class template $C$ +one of $D$ and $M$ declares a class or class template $C$ and the other declares a member or friend of $C$, or \item one of $D$ and $M$ declares an enumeration $E$ @@ -659,11 +658,14 @@ \end{footnote} or \item -one of $M$ and $D$ declares a template and the other declares +one of $D$ and $M$ declares a template and the other declares a partial or explicit specialization or an implicit or explicit instantiation of that template, or \item -one of $M$ and $D$ declares a class or enumeration type +$M$ declares a class template +and $D$ is a deduction guide for that template, or +\item +one of $D$ and $M$ declares a class or enumeration type and the other introduces a typedef name for linkage purposes for that type. \end{itemize} \end{itemize} diff --git a/source/numerics.tex b/source/numerics.tex index ae66b727ce..61c871082f 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -24,7 +24,8 @@ \ref{numarray} & Numeric arrays & \tcode{} \\ \rowsep \ref{c.math} & Mathematical functions for floating-point types & \tcode{}, \tcode{} \\ \rowsep -\ref{numbers} & Numbers & \tcode{} \\ +\ref{numbers} & Numbers & \tcode{} \\ \rowsep +\ref{linalg} & Linear algebra & \tcode{} \\ \end{libsumtab} \rSec1[numeric.requirements]{Numeric type requirements} @@ -289,6 +290,20 @@ template constexpr complex tan (const complex&); template constexpr complex tanh (const complex&); + // \ref{complex.tuple}, tuple interface + template struct tuple_size; + template struct tuple_element; + template struct tuple_size>; + template struct tuple_element>; + template + constexpr T& get(complex&) noexcept; + template + constexpr T&& get(complex&&) noexcept; + template + constexpr const T& get(const complex&) noexcept; + template + constexpr const T&& get(const complex&&) noexcept; + // \ref{complex.literals}, complex literals inline namespace literals { inline namespace complex_literals { @@ -1121,6 +1136,49 @@ The complex hyperbolic tangent of \tcode{x}. \end{itemdescr} +\rSec2[complex.tuple]{Tuple interface} + +\indexlibraryglobal{tuple_size}% +\indexlibraryglobal{tuple_element}% +\begin{itemdecl} +template +struct tuple_size> : integral_constant {}; + +template +struct tuple_element> { + using type = T; +}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{I < 2} is \tcode{true}. +\end{itemdescr} + +\indexlibrarymember{get}{complex}% +\begin{itemdecl} +template + constexpr T& get(complex& z) noexcept; +template + constexpr T&& get(complex&& z) noexcept; +template + constexpr const T& get(const complex& z) noexcept; +template + constexpr const T&& get(const complex&& z) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{I < 2} is \tcode{true}. + +\pnum +\returns +A reference to the real part of \tcode{z} if \tcode{I == 0} is \tcode{true}, +otherwise a reference to the imaginary part of \tcode{z}. +\end{itemdescr} + \rSec2[cmplx.over]{Additional overloads} \pnum @@ -1371,7 +1429,7 @@ class seed_seq; // \ref{rand.util.canonical}, function template \tcode{generate_canonical} - template + template RealType generate_canonical(URBG& g); // \ref{rand.dist.uni.int}, class template \tcode{uniform_int_distribution} @@ -2885,13 +2943,13 @@ static constexpr size_t long_lag = r; static constexpr result_type min() { return 0; } static constexpr result_type max() { return @$m - 1$@; } - static constexpr result_type default_seed = 19780503u; + static constexpr uint_least32_t default_seed = 19780503u; // constructors and seeding functions - subtract_with_carry_engine() : subtract_with_carry_engine(default_seed) {} + subtract_with_carry_engine() : subtract_with_carry_engine(0u) {} explicit subtract_with_carry_engine(result_type value); template explicit subtract_with_carry_engine(Sseq& q); - void seed(result_type value = default_seed); + void seed(result_type value = 0u); template void seed(Sseq& q); // equality operators @@ -2946,7 +3004,7 @@ first construct \tcode{e}, a \tcode{linear_congruential_engine} object, as if by the following definition: \begin{codeblock} -linear_congruential_engine e(value == 0u ? default_seed : value); \end{codeblock} Then, to set each $X_k$, @@ -3971,28 +4029,47 @@ \indexlibraryglobal{generate_canonical}% \begin{itemdecl} -template +template RealType generate_canonical(URBG& g); \end{itemdecl} \begin{itemdescr} \pnum -\effects - Invokes \tcode{g()} $k$ times - to obtain values $g_0, \dotsc, g_{k-1}$, respectively. - Calculates a quantity +Let +\begin{itemize} +\item $r$ be \tcode{numeric_limits::radix}, +\item $R$ be $\tcode{g.max()} - \tcode{g.min()} + 1$, +\item $d$ be the smaller of + \tcode{digits} and \tcode{numeric_limits::digits}, + \begin{footnote} + $d$ is introduced to avoid any attempt + to produce more bits of randomness + than can be held in \tcode{RealType}. + \end{footnote} +\item $k$ be the smallest integer such that $R^k \ge r^d$, and +\item $x$ be $\left\lfloor R^k / r^d \right\rfloor$. +\end{itemize} +An \defn{attempt} is $k$ invocations of \tcode{g()} +to obtain values $g_0, \dotsc, g_{k-1}$, respectively, +and the calculation of a quantity \[ S = \sum_{i=0}^{k-1} (g_i - \tcode{g.min()}) \cdot R^i \] - using arithmetic of type - \tcode{RealType}. + +\pnum +\effects +Attempts are made until $S < xr^d$. +\begin{note} +When $R$ is a power of $r$, precisely one attempt is made. +\end{note} \pnum \returns -$S / R^k$. +$\left\lfloor S / x \right\rfloor / r^d$. \begin{note} -$0 \leq S / R^k < 1$. +The return value $c$ satisfies +$0 \leq c < 1$. \end{note} \pnum @@ -4001,21 +4078,7 @@ \pnum \complexity -Exactly - $k = \max(1, \left\lceil b / \log_2 R \right\rceil)$ - invocations - of \tcode{g}, - where $b$ -\begin{footnote} -$b$ is introduced - to avoid any attempt - to produce more bits of randomness - than can be held in \tcode{RealType}. -\end{footnote} - is the lesser of \tcode{numeric_limits::digits} - and \tcode{bits}, - and - $R$ is the value of $\tcode{g.max()} - \tcode{g.min()} + 1$. +Exactly $k$ invocations of \tcode{g} per attempt. \pnum \begin{note} @@ -4028,6 +4091,13 @@ into a value that can be delivered by a random number distribution. \end{note} + +\pnum +\begin{note} +When $R$ is a power of $r$, +an implementation can avoid using an arithmetic type that is wider +than the output when computing $S$. +\end{note} \end{itemdescr} \indextext{random number generation!utilities|)} @@ -9193,13 +9263,13 @@ constexpr long double fminl(long double x, long double y); constexpr @\placeholder{floating-point-type}@ fma(@\placeholder{floating-point-type}@ x, @\placeholder{floating-point-type}@ y, - @\placeholder{floating-point-type}@ z); + @\placeholder{floating-point-type}@ z); constexpr float fmaf(float x, float y, float z); constexpr long double fmal(long double x, long double y, long double z); // \ref{c.math.lerp}, linear interpolation constexpr @\placeholder{floating-point-type}@ lerp(@\placeholder{floating-point-type}@ a, @\placeholder{floating-point-type}@ b, - @\placeholder{floating-point-type}@ t) noexcept; + @\placeholder{floating-point-type}@ t) noexcept; // \ref{c.math.fpclass}, classification / comparison functions constexpr int fpclassify(@\placeholder{floating-point-type}@ x); @@ -10397,3 +10467,5100 @@ \pnum A program that instantiates a primary template of a mathematical constant variable template is ill-formed. + +\rSec1[linalg]{Basic linear algebra algorithms} + +\rSec2[linalg.overview]{Overview} + +\pnum +Subclause \ref{linalg} defines basic linear algebra algorithms. +The algorithms that access the elements of arrays +view those elements through \tcode{mdspan}\iref{views.multidim}. + +\rSec2[linalg.syn]{Header \tcode{} synopsis} + +\begin{codeblock} +namespace std::linalg { + // \ref{linalg.tags.order}, storage order tags + struct column_major_t; + inline constexpr column_major_t column_major; + struct row_major_t; + inline constexpr row_major_t row_major; + + // \ref{linalg.tags.triangle}, triangle tags + struct upper_triangle_t; + inline constexpr upper_triangle_t upper_triangle; + struct lower_triangle_t; + inline constexpr lower_triangle_t lower_triangle; + + // \ref{linalg.tags.diagonal}, diagonal tags + struct implicit_unit_diagonal_t; + inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal; + struct explicit_diagonal_t; + inline constexpr explicit_diagonal_t explicit_diagonal; + + // \ref{linalg.layout.packed}, class template layout_blas_packed + template + class layout_blas_packed; + + // \ref{linalg.helpers}, exposition-only helpers + + // \ref{linalg.helpers.concepts}, linear algebra argument concepts + template + constexpr bool @\exposid{is-mdspan}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-vector}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{possibly-packed-inout-matrix}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{in-object}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{out-object}@ = @\seebelow@; // \expos + + template + concept @\exposconcept{inout-object}@ = @\seebelow@; // \expos + + // \ref{linalg.scaled}, scaled in-place transformation + + // \ref{linalg.scaled.scaledaccessor}, class template \tcode{scaled_accessor} + template + class scaled_accessor; + + // \ref{linalg.scaled.scaled}, function template \tcode{scaled} + template + constexpr auto scaled(ScalingFactor alpha, mdspan x); + + // \ref{linalg.conj}, conjugated in-place transformation + + // \ref{linalg.conj.conjugatedaccessor}, class template \tcode{conjugated_accessor} + template + class conjugated_accessor; + + // \ref{linalg.conj.conjugated}, function template \tcode{conjugated} + template + constexpr auto conjugated(mdspan a); + + // \ref{linalg.transp}, transpose in-place transformation + + // \ref{linalg.transp.layout.transpose}, class template \tcode{layout_transpose} + template + class layout_transpose; + + // \ref{linalg.transp.transposed}, function template \tcode{transposed} + template + constexpr auto transposed(mdspan a); + + // \ref{linalg.conjtransposed}, conjugated transpose in-place transformation + template + constexpr auto conjugate_transposed(mdspan a); + + // \ref{linalg.algs.blas1}, BLAS 1 algorithms + + // \ref{linalg.algs.blas1.givens}, Givens rotations + + // \ref{linalg.algs.blas1.givens.lartg}, compute Givens rotation + + template + struct setup_givens_rotation_result { + Real c; + Real s; + Real r; + }; + template + struct setup_givens_rotation_result> { + Real c; + complex s; + complex r; + }; + + template + setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; + + template + setup_givens_rotation_result> + setup_givens_rotation(complex a, complex b) noexcept; + + // \ref{linalg.algs.blas1.givens.rot}, apply computed Givens rotation + template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); + template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, Real s); + template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); + template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, complex s); + + // \ref{linalg.algs.blas1.swap}, swap elements + template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2> + void swap_elements(InOutObj1 x, InOutObj2 y); + template + void swap_elements(ExecutionPolicy&& exec, + InOutObj1 x, InOutObj2 y); + + // \ref{linalg.algs.blas1.scal}, multiply elements by scalar + template + void scale(Scalar alpha, InOutObj x); + template + void scale(ExecutionPolicy&& exec, + Scalar alpha, InOutObj x); + + // \ref{linalg.algs.blas1.copy}, copy elements + template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj> + void copy(InObj x, OutObj y); + template + void copy(ExecutionPolicy&& exec, + InObj x, OutObj y); + + // \ref{linalg.algs.blas1.add}, add elementwise + template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj> + void add(InObj1 x, InObj2 y, OutObj z); + template + void add(ExecutionPolicy&& exec, + InObj1 x, InObj2 y, OutObj z); + + // \ref{linalg.algs.blas1.dot}, dot product of two vectors + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dot(InVec1 v1, InVec2 v2, Scalar init); + template + Scalar dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dot(InVec1 v1, InVec2 v2); + template + auto dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); + template + Scalar dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dotc(InVec1 v1, InVec2 v2); + template + auto dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); + + // \ref{linalg.algs.blas1.ssq}, scaled sum of squares of a vector's elements + template + struct sum_of_squares_result { + Scalar scaling_factor; + Scalar scaled_sum_of_squares; + }; + template<@\exposconcept{in-vector}@ InVec, class Scalar> + sum_of_squares_result + vector_sum_of_squares(InVec v, sum_of_squares_result init); + template + sum_of_squares_result + vector_sum_of_squares(ExecutionPolicy&& exec, + InVec v, sum_of_squares_result init); + + // \ref{linalg.algs.blas1.nrm2}, Euclidean norm of a vector + template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_two_norm(InVec v, Scalar init); + template + Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); + template<@\exposconcept{in-vector}@ InVec> + auto vector_two_norm(InVec v); + template + auto vector_two_norm(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.asum}, sum of absolute values of vector elements + template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_abs_sum(InVec v, Scalar init); + template + Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); + template<@\exposconcept{in-vector}@ InVec> + auto vector_abs_sum(InVec v); + template + auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.iamax}, index of maximum absolute value of vector elements + template<@\exposconcept{in-vector}@ InVec> + typename InVec::extents_type vector_idx_abs_max(InVec v); + template + typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); + + // \ref{linalg.algs.blas1.matfrobnorm}, Frobenius norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_frob_norm(InMat A, Scalar init); + template + Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_frob_norm(InMat A); + template + auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas1.matonenorm}, one norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_one_norm(InMat A, Scalar init); + template + Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_one_norm(InMat A); + template + auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas1.matinfnorm}, infinity norm of a matrix + template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_inf_norm(InMat A, Scalar init); + template + Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); + template<@\exposconcept{in-matrix}@ InMat> + auto matrix_inf_norm(InMat A); + template + auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); + + // \ref{linalg.algs.blas2}, BLAS 2 algorithms + + // \ref{linalg.algs.blas2.gemv}, general matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec x, OutVec y); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.symv}, symmetric matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); + template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.hemv}, Hermitian matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); + template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.trmv}, triangular matrix-vector product + + // Overwriting triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, + @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, + OutVec y); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec x, + OutVec y); + + // In-place triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec y); + + // Updating triangular matrix-vector product + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); + template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); + + // \ref{linalg.algs.blas2.trsv}, solve a triangular linear system + + // Solve a triangular linear system, not in place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x); + + // Solve a triangular linear system, in place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec b); + + // \ref{linalg.algs.blas2.rank1}, nonsymmetric rank-1 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); + template + void matrix_rank_1_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A); + + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); + template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A); + + // \ref{linalg.algs.blas2.symherrank1}, symmetric or Hermitian rank-1 matrix update + template + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + InVec x, InOutMat A, Triangle t); + + template + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); + template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + InVec x, InOutMat A, Triangle t); + + // \ref{linalg.algs.blas2.rank2}, symmetric and Hermitian rank-2 matrix updates + + // symmetric rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); + template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); + + // Hermitian rank-2 matrix update + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); + template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); + + // \ref{linalg.algs.blas3}, BLAS 3 algorithms + + // \ref{linalg.algs.blas3.gemm}, general matrix-matrix product + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, OutMat C); + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InMat3 E, OutMat C); + + // \ref{linalg.algs.blas3.xxmm}, symmetric, Hermitian, and triangular matrix-matrix product + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); + + // \ref{linalg.algs.blas3.trmm}, in-place triangular matrix-matrix product + + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); + template + void triangular_matrix_left_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); + + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); + template + void triangular_matrix_right_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); + + // \ref{linalg.algs.blas3.rankk}, rank-k update of a symmetric or Hermitian matrix + + // rank-k symmetric matrix update + template + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); + + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); + + // rank-k Hermitian matrix update + template + void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); + + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); + + // \ref{linalg.algs.blas3.rank2k}, rank-2k update of a symmetric or Hermitian matrix + + // rank-2k symmetric matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); + + // rank-2k Hermitian matrix update + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); + template + void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); + + // \ref{linalg.algs.blas3.trsm}, solve multiple triangular linear systems + + // solve multiple triangular systems on the left, not-in-place + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + + // solve multiple triangular systems on the right, not-in-place + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); + + // solve multiple triangular systems on the left, in-place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + + // solve multiple triangular systems on the right, in-place + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); + template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +} +\end{codeblock} + +\rSec2[linalg.general]{General} + +\pnum +For the effects of all functions in \ref{linalg}, +when the effects are described as +``computes $R = E$'' or ``compute $R = E$'' +(for some $R$ and mathematical expression $E$), +the following apply: +\begin{itemize} +\item +$E$ has + the conventional mathematical meaning as written. +\item +The pattern $x^T$ should be read as + ``the transpose of $x$.'' +\item +The pattern $x^H$ should be read as + ``the conjugate transpose of $x$.'' +\item +When $R$ is the same name as a function parameter + whose type is a template parameter with \tcode{Out} in its name, + the intent is that the result of the computation + is written to the elements of the function parameter \tcode{R}. +\end{itemize} + +\pnum +Some of the functions and types in \ref{linalg} distinguish between +the ``rows'' and the ``columns'' of a matrix. +For a matrix \tcode{A} and a multidimensional index \tcode{i, j} in \tcode{A.extents()}, +\begin{itemize} +\item +\term{row} \tcode{i} of \tcode{A} is the set of elements \tcode{A[i, k1]} + for all \tcode{k1} such that \tcode{i, k1} is in \tcode{A.extents()}; and +\item +\term{column} \tcode{j} of \tcode{A} is the set of elements \tcode{A[k0, j]} + for all \tcode{k0} such that \tcode{k0, j} is in \tcode{A.extents()}. +\end{itemize} + +\pnum +Some of the functions in \ref{linalg} distinguish between +the ``upper triangle,'' ``lower triangle,'' and ``diagonal'' of a matrix. +\begin{itemize} +\item +The \defn{diagonal} is the set of all elements of \tcode{A} accessed by + \tcode{A[i,i]} for 0 $\le$ \tcode{i} < min(\tcode{A.extent(0)}, \tcode{A.extent(1)}). +\item +The \defnadj{upper}{triangle} of a matrix \tcode{A} is the set of all elements of + \tcode{A} accessed by \tcode{A[i,j]} with \tcode{i} $\le$ \tcode{j}. It includes the diagonal. +\item +The \defnadj{lower}{triangle} of \tcode{A} is the set of all elements of \tcode{A} + accessed by \tcode{A[i,j]} with \tcode{i} $\ge$ \tcode{j}. It includes the diagonal. +\end{itemize} + +\pnum +For any function \tcode{F} that takes +a parameter named \tcode{t}, +\tcode{t} applies to accesses done through the parameter preceding \tcode{t} in the parameter list of \tcode{F}. +Let \tcode{m} be such an access-modified function parameter. +\tcode{F} will only access the triangle of \tcode{m} specified by \tcode{t}. +For accesses \tcode{m[i, j]} outside the triangle specified by \tcode{t}, +\tcode{F} will use the value +\begin{itemize} +\item +\tcode{\exposid{conj-if-needed}(m[j, i])} if the name of \tcode{F} starts with \tcode{hermitian}, +\item +\tcode{m[j, i]} if the name of \tcode{F} starts with \tcode{symmetric}, or +\item +the additive identity if the name of \tcode{F} starts with \tcode{triangular}. +\end{itemize} +\begin{example} +Small vector product accessing only specified triangle. +It would not be a precondition violation for the non-accessed +matrix element to be non-zero. +\begin{codeblock} +template +void triangular_matrix_vector_2x2_product( + mdspan> m, + Triangle t, + mdspan> x, + mdspan> y) { + + static_assert(is_same_v || + is_same_v); + + if constexpr (is_same_v) { + y[0] = m[0,0] * x[0]; // \tcode{+ 0 * x[1]} + y[1] = m[1,0] * x[0] + m[1,1] * x[1]; + } else { // upper_triangle_t + y[0] = m[0,0] * x[0] + m[0,1] * x[1]; + y[1] = /* 0 * x[0] + */ m[1,1] * x[1]; + } +} +\end{codeblock} +\end{example} + +\pnum +For any function \tcode{F} that takes a parameter named \tcode{d}, +\tcode{d} applies to accesses done through +the previous-of-the-previous parameter of \tcode{d} +in the parameter list of \tcode{F}. +Let \tcode{m} be such an access-modified function parameter. +If \tcode{d} specifies that an implicit unit diagonal is to be assumed, then +\begin{itemize} +\item +\tcode{F} will not access the diagonal of \tcode{m}; and +\item +the algorithm will interpret \tcode{m} as if it has a unit diagonal, that is, +a diagonal each of whose elements behaves as a two-sided multiplicative identity +(even if \tcode{m}'s value type does not have +a two-sided multiplicative identity). +\end{itemize} +Otherwise, +if \tcode{d} specifies that an explicit diagonal is to be assumed, +then \tcode{F} will access the diagonal of \tcode{m}. + +\pnum +Within all the functions in \ref{linalg}, +any calls to \tcode{abs}, \tcode{conj}, \tcode{imag}, and \tcode{real} +are unqualified. + +\pnum +Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{alias} each other, +if they have the same extents \tcode{e}, and +for every pack of integers \tcode{i} +which is a multidimensional index in \tcode{e}, +\tcode{x[i...]} and \tcode{y[i...]} refer to the same element. +\begin{note} +This means that +\tcode{x} and \tcode{y} view the same elements in the same order. +\end{note} + +\pnum +Two \tcode{mdspan} objects \tcode{x} and \tcode{y} \term{overlap} each other, +if for some pack of integers \tcode{i} +that is a multidimensional index in \tcode{x.extents()}, +there exists a pack of integers \tcode{j} +that is a multidimensional index in \tcode{y.extents()}, +such that \tcode{x[i....]} and \tcode{y[j...]} refer to the same element. +\begin{note} +Aliasing is a special case of overlapping. +If \tcode{x} and \tcode{y} do not overlap, +then they also do not alias each other. +\end{note} + +\rSec2[linalg.reqs]{Requirements} + +\rSec3[linalg.reqs.val]{Linear algebra value types} + +\pnum +Throughout \ref{linalg}, +the following types are +\defnadjx{linear algebra}{value type}{linear algebra value types}: +\begin{itemize} +\item +the \tcode{value_type} type alias of +any input or output \tcode{mdspan} parameter(s) of +any function in \ref{linalg}; and +\item +the \tcode{Scalar} template parameter (if any) of +any function or class in \ref{linalg}. +\end{itemize} + +\pnum +Linear algebra value types shall model \libconcept{semiregular}. + +\pnum +A value-initialized object of linear algebra value type +shall act as the additive identity. + +\rSec3[linalg.reqs.alg]{Algorithm and class requirements} + +\pnum +\ref{linalg.reqs.alg} lists common requirements for +all algorithms and classes in \ref{linalg}. + +\pnum +All of the following statements presume +that the algorithm's asymptotic complexity requirements, if any, are satisfied. +\begin{itemize} +\item +The function may make arbitrarily many objects of any linear algebra value type, +value-initializing or direct-initializing them +with any existing object of that type. +\item +The \term{triangular solve algorithms} in +\ref{linalg.algs.blas2.trsv}, +\ref{linalg.algs.blas3.trmm}, +\ref{linalg.algs.blas3.trsm}, and +\ref{linalg.algs.blas3.inplacetrsm} +either have +a \tcode{BinaryDi\-videOp} template parameter (see \ref{linalg.algs.reqs}) and +a binary function object parameter \tcode{divide} of that type, +or they have effects equivalent to invoking such an algorithm. +Triangular solve algorithms interpret \tcode{divide(a, b)} as +\tcode{a} times the multiplicative inverse of \tcode{b}. +Each triangular solve algorithm uses a sequence of evaluations of +\tcode{*}, \tcode{*=}, \tcode{divide}, +unary \tcode{+}, binary \tcode{+}, \tcode{+=}, +unary \tcode{-}, binary \tcode{-}, \tcode{-=}, +and \tcode{=} operators +that would produce the result +specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks} +when operating on elements of a field with noncommutative multiplication. +It is a precondition of the algorithm that +any addend, +any subtrahend, +any partial sum of addends in any order +(treating any difference as a sum with the second term negated), +any factor, +any partial product of factors respecting their order, +any numerator (first argument of \tcode{divide}), +any denominator (second argument of \tcode{divide}), +and any assignment +is a well-formed expression. +\item +Each function in +\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3} +that is not a triangular solve algorithm +will use a sequence of evaluations of +\tcode{*}, \tcode{*=}, \tcode{+}, \tcode{+=}, and \tcode{=} operators +that would produce the result +specified by the algorithm's \Fundescx{Effects} and \Fundescx{Remarks} +when operating on elements of a semiring with noncommutative multiplication. +It is a precondition of the algorithm that +any addend, +any partial sum of addends in any order, +any factor, +any partial product of factors respecting their order, +and any assignment +is a well-formed expression. +\item +If the function has an output \tcode{mdspan}, +then all addends, +subtrahends (for the triangular solve algorithms), +or results of the \tcode{divide} parameter on intermediate terms +(if the function takes a \tcode{divide} parameter) +are assignable and convertible to +the output \tcode{mdspan}'s \tcode{value_type}. +\item +The function may reorder addends and partial sums arbitrarily. +\begin{note} +Factors in each product are not reordered; +multiplication is not necessarily commutative. +\end{note} +\end{itemize} +\begin{note} +The above requirements do not prohibit +implementation approaches and optimization techniques +which are not user-observable. +In particular, if for all input and output arguments +the \tcode{value_type} is a floating-point type, +implementers are free to leverage approximations, +use arithmetic operations not explicitly listed above, and +compute floating point sums in any way that improves their accuracy. +\end{note} + +\pnum +\begin{note} +For all functions in \ref{linalg}, +suppose that all input and output \tcode{mdspan} have as \tcode{value_type} +a floating-point type, and +any \tcode{Scalar} template argument has a floating-point type. +Then, functions can do all of the following: +\begin{itemize} +\item +compute floating-point sums in any way +that improves their accuracy for arbitrary input; +\item +perform additional arithmetic operations +(other than those specified by the function's wording and \ref{linalg.reqs.alg}) +in order to improve performance or accuracy; and +\item +use approximations +(that might not be exact even if computing with real numbers), +instead of computations that would be exact +if it were possible to compute without rounding error; +\end{itemize} +as long as +\begin{itemize} +\item +the function satisfies the complexity requirements; and +\item +the function is logarithmically stable, +as defined in Demmel 2007\supercite{linalg-stable}. +Strassen's algorithm for matrix-matrix multiply +is an example of a logarithmically stable algorithm. +\end{itemize} +\end{note} + +\rSec2[linalg.tags]{Tag classes} + +\rSec3[linalg.tags.order]{Storage order tags} + +\pnum +The storage order tags describe +the order of elements in an \tcode{mdspan} with +\tcode{layout_blas_packed}\iref{linalg.layout.packed} layout. +\begin{itemdecl} +struct column_major_t { + explicit column_major_t() = default; +}; +inline constexpr column_major_t column_major{}; + +struct row_major_t { + explicit row_major_t() = default; +}; +inline constexpr row_major_t row_major{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\tcode{column_major_t} indicates a column-major order, +and \tcode{row_major_t} indicates a row-major order. +\end{itemdescr} + +\rSec3[linalg.tags.triangle]{Triangle tags} + +\begin{itemdecl} +struct upper_triangle_t { + explicit upper_triangle_t() = default; +}; +inline constexpr upper_triangle_t upper_triangle{}; + +struct lower_triangle_t { + explicit lower_triangle_t() = default; +}; +inline constexpr lower_triangle_t lower_triangle{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These tag classes specify whether +algorithms and other users of a matrix (represented as an \tcode{mdspan}) +access the +upper triangle (\tcode{upper_triangle_t}) or +lower triangle (\tcode{lower_triangle_t}) +of the matrix (see also \ref{linalg.general}). +This is also subject to the restrictions of \tcode{implicit_unit_diagonal_t} +if that tag is also used as a function argument; see below. +\end{itemdescr} + +\rSec3[linalg.tags.diagonal]{Diagonal tags} + +\begin{itemdecl} +struct implicit_unit_diagonal_t { + explicit implicit_unit_diagonal_t() = default; +}; +inline constexpr implicit_unit_diagonal_t + implicit_unit_diagonal{}; + +struct explicit_diagonal_t { + explicit explicit_diagonal_t() = default; +}; +inline constexpr explicit_diagonal_t explicit_diagonal{}; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These tag classes specify whether algorithms +access the matrix's diagonal entries, and if not, +then how algorithms interpret +the matrix's implicitly represented diagonal values. + +\pnum +The \tcode{implicit_unit_diagonal_t} tag indicates that +an implicit unit diagonal is to be assumed\iref{linalg.general}. + +\pnum +The \tcode{explicit_diagonal_t} tag indicates that +an explicit diagonal is used\iref{linalg.general}. +\end{itemdescr} + +\rSec2[linalg.layout.packed]{Layouts for packed matrix types} + +\rSec3[linalg.layout.packed.overview]{Overview} + +\pnum +\tcode{layout_blas_packed} is an \tcode{mdspan} layout mapping policy +that represents a square matrix that stores only the entries in one +triangle, in a packed contiguous format. +Its \tcode{Triangle} template parameter determines +whether an \tcode{mdspan} with this layout +stores the upper or lower triangle of the matrix. +Its \tcode{StorageOrder} template parameter determines +whether the layout packs the matrix's elements +in column-major or row-major order. + +\pnum +A \tcode{StorageOrder} of \tcode{column_major_t} +indicates column-major ordering. +This packs matrix elements +starting with the leftmost (least column index) column, and +proceeding column by column, from the top entry (least row index). + +\pnum +A \tcode{StorageOrder} of \tcode{row_major_t} +indicates row-major ordering. +This packs matrix elements +starting with the topmost (least row index) row, and +proceeding row by row, from the leftmost (least column index) entry. + +\pnum +\begin{note} +\tcode{layout_blas_packed} describes the data layout used by +the BLAS' +Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP) +matrix types. +\end{note} +\begin{codeblock} +namespace std::linalg { + template + class layout_blas_packed { + public: + using triangle_type = Triangle; + using storage_order_type = StorageOrder; + + template + struct mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_blas_packed; + + // \ref{linalg.layout.packed.cons}, constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template + constexpr explicit(!is_convertible_v) + mapping(const mapping& other) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // \ref{linalg.layout.packed.obs}, observers + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + + constexpr index_type required_span_size() const noexcept; + + template + constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; + + static constexpr bool is_always_unique() noexcept { + return (extents_type::static_extent(0) != dynamic_extent && + extents_type::static_extent(0) < 2) || + (extents_type::static_extent(1) != dynamic_extent && + extents_type::static_extent(1) < 2); + } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept + { return is_always_unique(); } + + constexpr bool is_unique() const noexcept { + return @\exposid{extents_}@.extent(0) < 2; + } + constexpr bool is_exhaustive() const noexcept { return true; } + constexpr bool is_strided() const noexcept { + return @\exposid{extents_}@.extent(0) < 2; + } + + constexpr index_type stride(rank_type) const noexcept; + + template + friend constexpr bool operator==(const mapping&, const mapping&) noexcept; + + private: + extents_type @\exposid{extents_}@{}; // \expos + }; + }; +} +\end{codeblock} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t}, +\item +\tcode{StorageOrder} is either \tcode{column_major_t} or \tcode{row_major_t}, +\item +\tcode{Extents} is a specialization of \tcode{std::extents}, +\item +\tcode{Extents::rank()} equals 2, +\item +one of +\begin{codeblock} +extents_type::static_extent(0) == dynamic_extent@\textrm{,}@ +extents_type::static_extent(1) == dynamic_extent@\textrm{, or}@ +extents_type::static_extent(0) == extents_type::static_extent(1) +\end{codeblock} +is \tcode{true}, and +\item +if \tcode{Extents::rank_dynamic() == 0} is \tcode{true}, +let $N_s$ be equal to \tcode{Extents::static_extent(0)}; then, +$N_s \times (N_s + 1)$ is representable as a value of type \tcode{index_type}. +\end{itemize} + +\pnum +\tcode{layout_blas_packed::mapping} is a trivially copyable type +that models \libconcept{regular} for each \tcode{T}, \tcode{SO}, and \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.layout.packed.cons]{Constructors} + +\begin{itemdecl} +constexpr mapping(const extents_type& e) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +Let $N$ be equal to \tcode{e.extent(0)}. +Then, $N \times (N+1)$ is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. +\item +\tcode{e.extent(0)} equals \tcode{e.extent(1)}. +\end{itemize} + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{e}. +\end{itemdescr} + +\begin{itemdecl} +template + explicit(!is_convertible_v) + constexpr mapping(const mapping& other) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\expects +Let $N$ be \tcode{other.extents().extent(0)}. +Then, $N \times (N+1)$ is representable as +a value of type \tcode{index_type}\iref{basic.fundamental}. + +\pnum +\effects +Direct-non-list-initializes \exposid{extents_} with \tcode{other.extents()}. +\end{itemdescr} + +\rSec3[linalg.layout.packed.obs]{Observers} + +\begin{itemdecl} +constexpr index_type required_span_size() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{extents_}.extent(0) * (\exposid{extents_}.extent(0) + 1)/2}. +\begin{note} +For example, a 5 x 5 packed matrix +only stores 15 matrix elements. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template + constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_convertible_v} is \tcode{true}, +\item +\tcode{is_convertible_v} is \tcode{true}, +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}, and +\item +\tcode{is_nothrow_constructible_v} is \tcode{true}. +\end{itemize} + +\pnum +Let \tcode{i} be \tcode{extents_type::\exposid{index-cast}(ind0)}, and +let \tcode{j} be \tcode{extents_type::\exposid{index-cast}(ind1)}. + +\pnum +\expects +\tcode{i, j} +is a multidimensional index in \exposid{extents_}\iref{mdspan.overview}. + +\pnum +\returns +Let \tcode{N} be \tcode{\exposid{extents_}.extent(0)}. +Then +\begin{itemize} +\item +\tcode{(*this)(j, i)} if \tcode{i > j} is \tcode{true}; otherwise +\item +\tcode{i + j * (j + 1)/2} if +\begin{codeblock} +is_same_v && is_same_v +\end{codeblock} +is \tcode{true} or +\begin{codeblock} +is_same_v && is_same_v +\end{codeblock} +is \tcode{true}; otherwise +\item +\tcode{j + N * i - i * (i + 1)/2}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type stride(rank_type r) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\begin{itemize} +\item +\tcode{is_strided()} is \tcode{true}, and +\item +\tcode{r < extents_type::rank()} is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{1}. +\end{itemdescr} + +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.extents() == y.extents();} +\end{itemdescr} + +\rSec2[linalg.helpers]{Exposition-only helpers} + +\rSec3[linalg.helpers.abs]{\exposid{abs-if-needed}} + +\pnum +The name \exposid{abs-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{abs-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{E} if \tcode{T} is an unsigned integer; +\item +otherwise, \tcode{std::abs(E)} if \tcode{T} is an arithmetic type, +\item +otherwise, \tcode{abs(E)}, +if that expression is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template T abs(T) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the absolute value of its input, +the program is ill-formed, no diagnostic required. +\end{itemize} + +\rSec3[linalg.helpers.conj]{\exposid{conj-if-needed}} + +\pnum +The name \exposid{conj-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{conj-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{conj(E)}, +if \tcode{T} is not an arithmetic type and +the expression \tcode{conj(E)} is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template T conj(const T&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the complex conjugate of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{E}. +\end{itemize} + +\rSec3[linalg.helpers.real]{\exposid{real-if-needed}} + +\pnum +The name \exposid{real-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{real-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{real(E)}, +if \tcode{T} is not an arithmetic type and +the expression \tcode{real(E)} is valid, +with overload resolution performed in a context that includes the declaration +\begin{codeblock} +template T real(const T&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the real part of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{E}. +\end{itemize} + +\rSec3[linalg.helpers.imag]{\exposid{imag-if-needed}} + +\pnum +The name \exposid{imag-if-needed} denotes an exposition-only function object. +The expression \tcode{\exposid{imag-if-needed}(E)} for a subexpression \tcode{E} +whose type is \tcode{T} is expression-equivalent to: +\begin{itemize} +\item +\tcode{imag(E)}, +if \tcode{T} is not an arithmetic type and the expression \tcode{imag(E)} +is valid, with overload resolution performed in a context +that includes the declaration +\begin{codeblock} +template T imag(const T&) = delete; +\end{codeblock} +If the function selected by overload resolution +does not return the imaginary part of its input, +the program is ill-formed, no diagnostic required; +\item +otherwise, \tcode{((void)E, T\{\})}. +\end{itemize} + +\rSec3[linalg.helpers.concepts]{Argument concepts} + +\pnum +The exposition-only concepts defined in this section +constrain the algorithms in \ref{linalg}. +\begin{codeblock} +template + constexpr bool @\exposid{is-mdspan}@ = false; + +template + constexpr bool @\exposid{is-mdspan}@> = true; + +template + concept @\defexposconcept{in-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1; + +template + concept @\defexposconcept{out-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-vector}@ = + @\exposid{is-mdspan}@ && T::rank() == 1 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{in-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2; + +template + concept @\defexposconcept{out-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && T::is_always_unique(); + +template + constexpr bool @\exposid{is-layout-blas-packed}@ = false; // \expos + +template + constexpr bool @\exposid{is-layout-blas-packed}@> = true; + +template + concept @\defexposconcept{possibly-packed-inout-matrix}@ = + @\exposid{is-mdspan}@ && T::rank() == 2 && + is_assignable_v && + (T::is_always_unique() || @\exposid{is-layout-blas-packed}@); + +template + concept @\defexposconcept{in-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2); + +template + concept @\defexposconcept{out-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2) && + is_assignable_v && T::is_always_unique(); + +template + concept @\defexposconcept{inout-object}@ = + @\exposid{is-mdspan}@ && (T::rank() == 1 || T::rank() == 2) && + is_assignable_v && T::is_always_unique(); +\end{codeblock} + +\pnum +If a function in \ref{linalg} accesses the elements +of a parameter constrained by +\exposconcept{in-vector}, +\exposconcept{in-matrix}, or +\exposconcept{in-object}, +those accesses will not modify the elements. + +\pnum +Unless explicitly permitted, any +\exposconcept{inout-vector}, +\exposconcept{inout-matrix}, +\exposconcept{inout-object}, +\exposconcept{out-vector}, +\exposconcept{out-matrix}, +\exposconcept{out-object}, or +\exposconcept{possibly-packed-inout-matrix} +parameter of a function in \ref{linalg} +shall not overlap any other \tcode{mdspan} parameter of the function. + +\rSec3[linalg.helpers.mandates]{Mandates} + +\pnum +\begin{note} +These exposition-only helper functions use +the less constraining input concepts even for the output arguments, +because the additional constraint for assignability of elements +is not necessary, and +they are sometimes used in a context +where the third argument is an input type too. +\end{note} + +\begin{codeblock} +template + requires(@\exposid{is-mdspan}@ && @\exposid{is-mdspan}@) + constexpr + bool @\exposid{compatible-static-extents}@(size_t r1, size_t r2) { // \expos + return MDS1::static_extent(r1) == dynamic_extent || + MDS2::static_extent(r2) == dynamic_extent || + MDS1::static_extent(r1) == MDS2::static_extent(r2)); + } + +template<@\exposconcept{in-vector}@ In1, @\exposconcept{in-vector}@ In2, @\exposconcept{in-vector}@ Out> + constexpr bool @\exposid{possibly-addable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(0, 0); + } + +template<@\exposconcept{in-matrix}@ In1, @\exposconcept{in-matrix}@ In2, @\exposconcept{in-matrix}@ Out> + constexpr bool @\exposid{possibly-addable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1); + } + +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{in-vector}@ OutVec> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 0); + } + +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ OutVec> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 1) && + @\exposid{compatible-static-extents}@(0, 0); + } + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ OutMat> + constexpr bool @\exposid{possibly-multipliable}@() { // \expos + return @\exposid{compatible-static-extents}@(0, 0) && + @\exposid{compatible-static-extents}@(1, 1) && + @\exposid{compatible-static-extents}@(1, 0); + } +\end{codeblock} + +\rSec3[linalg.helpers.precond]{Preconditions} + +\pnum +\begin{note} +These exposition-only helper functions use +the less constraining input concepts even for the output arguments, +because the additional constraint for assignability of elements +is not necessary, and +they are sometimes used in a context +where the third argument is an input type too. +\end{note} + +\begin{codeblock} +constexpr bool @\exposid{addable}@( // \expos + const @\exposconcept{in-vector}@ auto& in1, const @\exposconcept{in-vector}@ auto& in2, const @\exposconcept{in-vector}@ auto& out) { + return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0); +} + +constexpr bool @\exposid{addable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in1, const @\exposconcept{in-matrix}@ auto& in2, const @\exposconcept{in-matrix}@ auto& out) { + return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) && + out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-vector}@ auto& out_vec) { + return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-vector}@ auto& in_vec, const @\exposconcept{in-matrix}@ auto& in_mat, const @\exposconcept{in-vector}@ auto& out_vec) { + return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0); +} + +constexpr bool @\exposid{multipliable}@( // \expos + const @\exposconcept{in-matrix}@ auto& in_mat1, const @\exposconcept{in-matrix}@ auto& in_mat2, const @\exposconcept{in-matrix}@ auto& out_mat) { + return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) && + in1_mat.extent(1) == in_mat2.extent(0); +} +\end{codeblock} + +\rSec2[linalg.scaled]{Scaled in-place transformation} + +\rSec3[linalg.scaled.intro]{Introduction} + +\pnum +The \tcode{scaled} function +takes a value \tcode{alpha} and an \tcode{mdspan} \tcode{x}, and +returns a new read-only \tcode{mdspan} +that represents +the elementwise product of \tcode{alpha} with each element of \tcode{x}. +\begin{example} +\begin{codeblock} +using Vec = mdspan>; + +// z = alpha * x + y +void z_equals_alpha_times_x_plus_y(double alpha, Vec x, Vec y, Vec z) { + add(scaled(alpha, x), y, z); +} + +// z = alpha * x + beta * y +void z_equals_alpha_times_x_plus_beta_times_y(double alpha, Vec x, double beta, Vec y, Vec z) { + add(scaled(alpha, x), scaled(beta, y), z); +} +\end{codeblock} +\end{example} + +\rSec3[linalg.scaled.scaledaccessor]{Class template \tcode{scaled_accessor}} + + +\pnum +The class template \tcode{scaled_accessor} is an \tcode{mdspan} accessor policy +which upon access produces scaled elements. +It is part of the implementation of \tcode{scaled}\iref{linalg.scaled.scaled}. +\begin{codeblock} +namespace std::linalg { + template + class scaled_accessor { + public: + using element_type = + add_const_t() * declval())>; + using reference = remove_const_t; + using data_handle_type = NestedAccessor::data_handle_type; + using offset_policy = scaled_accessor; + + constexpr scaled_accessor() = default; + template + explicit(!is_convertible_v) + constexpr scaled_accessor(const scaled_accessor& other); + constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); + + constexpr reference access(data_handle_type p, size_t i) const; + constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; + + constexpr const ScalingFactor& scaling_factor() const noexcept { return @\exposid{scaling-factor}@; } + constexpr const NestedAccessor& nested_accessor() const noexcept { return @\exposid{nested-accessor}@; } + + private: + ScalingFactor @\exposid{scaling-factor}@{}; // \expos + NestedAccessor @\exposid{nested-accessor}@{}; // \expos + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{element_type} is valid and denotes a type, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, +\item +\tcode{is_reference_v} is \tcode{false}, +\item +\tcode{ScalingFactor} models \libconcept{semiregular}, and +\item +\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. +\end{itemize} + +\begin{itemdecl} +template + explicit(!is_convertible_v) + constexpr scaled_accessor(const scaled_accessor& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} is \tcode{true}. + +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{scaling-factor} +with \tcode{other.scaling_factor()}, and +\item +direct-non-list-initializes \exposid{nested-accessor} +with \tcode{other.nested_accessor()}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Direct-non-list-initializes \exposid{scaling-factor} with \tcode{s}, and +\item +direct-non-list-initializes \exposid{nested-accessor} with \tcode{a}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{codeblock} +scaling_factor() * NestedAccessor::element_type(@\exposid{nested-accessor}@.access(p, i)) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{nested-accessor}.offset(p, i)} +\end{itemdescr} + +\rSec3[linalg.scaled.scaled]{Function template \tcode{scaled}} + +\pnum +The \tcode{scaled} function template takes +a scaling factor \tcode{alpha} and +an \tcode{mdspan} \tcode{x}, and +returns a new read-only \tcode{mdspan} with the same domain as \tcode{x}, +that represents the elementwise product of \tcode{alpha} +with each element of \tcode{x}. + +\begin{itemdecl} + template + constexpr auto scaled(ScalingFactor alpha, mdspan x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{SA} be \tcode{scaled_accessor}. + +\pnum +\returns +\begin{codeblock} +mdspan(x.data_handle(), x.mapping(), + SA(alpha, x.accessor())) +\end{codeblock} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_scaled(mdspan> x) +{ + auto x_scaled = scaled(5.0, x); + for(int i = 0; i < x.extent(0); ++i) { + assert(x_scaled[i] == 5.0 * x[i]); + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.conj]{Conjugated in-place transformation} + +\rSec3[linalg.conj.intro]{Introduction} + +\pnum +The \tcode{conjugated} function takes an \tcode{mdspan} \tcode{x}, +and returns a new read-only \tcode{mdspan} \tcode{y} +with the same domain as \tcode{x}, +whose elements are the complex conjugates +of the corresponding elements of \tcode{x}. + +\rSec3[linalg.conj.conjugatedaccessor]{Class template \tcode{conjugated_accessor}} + +\pnum +The class template \tcode{conjugated_accessor} +is an \tcode{mdspan} accessor policy +which upon access produces conjugate elements. +It is part of the implementation of +\tcode{conjugated}\iref{linalg.conj.conjugated}. + +\begin{codeblock} +namespace std::linalg { + template + class conjugated_accessor { + public: + using element_type = + add_const_t()))>; + using reference = remove_const_t; + using data_handle_type = typename NestedAccessor::data_handle_type; + using offset_policy = conjugated_accessor; + + constexpr conjugated_accessor() = default; + template + explicit(!is_convertible_v>) + constexpr conjugated_accessor(const conjugated_accessor& other); + + constexpr reference access(data_handle_type p, size_t i) const; + + constexpr typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const; + + constexpr const Accessor& nested_accessor() const noexcept { return @\exposid{nested-accessor_}@; } + + private: + NestedAccessor @\exposid{nested-accessor_}@{}; // \expos + }; +} +\end{codeblock} + +\pnum +\mandates +\begin{itemize} +\item +\tcode{element_type} is valid and denotes a type, +\item +\tcode{is_copy_constructible_v} is \tcode{true}, +\item +\tcode{is_reference_v} is \tcode{false}, and +\item +\tcode{NestedAccessor} meets the accessor policy requirements\iref{mdspan.accessor.reqmts}. +\end{itemize} + +\begin{itemdecl} +constexpr conjugated_accessor(const NestedAccessor& acc); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Direct-non-list-initializes +\exposid{nested-accessor_} with \tcode{acc}. +\end{itemdescr} + +\begin{itemdecl} +template + explicit(!is_convertible_v>) + constexpr conjugated_accessor(const conjugated_accessor& other); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{is_constructible_v} +is \tcode{true}. + +\pnum +\effects +Direct-non-list-initializes \exposid{nested-accessor_} +with \tcode{other.nested_accessor()}. +\end{itemdescr} + +\begin{itemdecl} +constexpr reference access(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{conj-if-needed}(NestedAccessor::element_type(\exposid{nested-accessor_}.access(p, i)))} +\end{itemdescr} + +\begin{itemdecl} +constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{\exposid{nested-accessor_}.offset(p, i)} +\end{itemdescr} + +\rSec3[linalg.conj.conjugated]{Function template \tcode{conjugated}} + +\begin{itemdecl} + template + constexpr auto conjugated(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{A} be +\tcode{remove_cvref_t} +if \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}, and +otherwise \tcode{conjugated_accessor}. + +\pnum +\returns +\begin{itemize} +\item +If \tcode{Accessor} is a specialization of \tcode{conjugated_accessor}, +\begin{codeblock} +mdspan(a.data_handle(), a.mapping(), + a.accessor().nested_accessor()) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +mdspan(a.data_handle(), a.mapping(), + conjugated_accessor(a.accessor())) +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_conjugated_complex(mdspan, extents> a) { + auto a_conj = conjugated(a); + for(int i = 0; i < a.extent(0); ++i) { + assert(a_conj[i] == conj(a[i]); + } + auto a_conj_conj = conjugated(a_conj); + for(int i = 0; i < a.extent(0); ++i) { + assert(a_conj_conj[i] == a[i]); + } +} + +void test_conjugated_real(mdspan> a) { + auto a_conj = conjugated(a); + for(int i = 0; i < a.extent(0); ++i) { + assert(a_conj[i] == a[i]); + } + auto a_conj_conj = conjugated(a_conj); + for(int i = 0; i < a.extent(0); ++i) { + assert(a_conj_conj[i] == a[i]); + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.transp]{Transpose in-place transformation} + +\rSec3[linalg.transp.intro]{Introduction} + +\pnum +\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy +that swaps the two indices, extents, and strides +of any unique \tcode{mdspan} layout mapping policy. + +\pnum +The \tcode{transposed} function takes an \tcode{mdspan} +representing a matrix, and returns a new \tcode{mdspan} +representing the transpose of the input matrix. + +\rSec3[linalg.transp.helpers]{Exposition-only helpers for \tcode{layout_transpose} and \tcode{transposed}} + +\pnum +The exposition-only \exposid{transpose-extents} function +takes an \tcode{extents} object representing the extents of a matrix, +and returns a new \tcode{extents} object +representing the extents of the transpose of the matrix. + +\pnum +The exposition-only alias template +\tcode{\exposid{transpose-extents-t}} +gives the type of \tcode{\exposid{transpose-ex\-tents}(e)} +for a given \tcode{extents} object \tcode{e} of type \tcode{InputExtents}. +\begin{itemdecl} +template + constexpr extents + @\exposid{transpose-extents}@(const extents& in); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{extents(in.extent(1), in.extent(0))} +\end{itemdescr} + +\begin{codeblock} +template + using @\exposid{transpose-extents-t}@ = + decltype(@\exposid{transpose-extents}@(declval())); // \expos +\end{codeblock} + +\rSec3[linalg.transp.layout.transpose]{Class template \tcode{layout_transpose}} + +\pnum +\tcode{layout_transpose} is an \tcode{mdspan} layout mapping policy +that swaps the two indices, extents, and strides +of any \tcode{mdspan} layout mapping policy. + +\begin{codeblock} +namespace std::linalg { + template + class layout_transpose { + public: + using nested_layout_type = Layout; + + template + struct mapping { + private: + using @\exposid{nested-mapping-type}@ = + typename Layout::template mapping<@\exposid{transpose-extents-t}@>; // \expos + + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_transpose; + + constexpr explicit mapping(const @\exposid{nested-mapping-type}@&); + + constexpr const extents_type& extents() const noexcept { return @\exposid{extents_}@; } + + constexpr index_type required_span_size() const + { return @\exposid{nested-mapping_}@.required_span_size(); + + template + constexpr index_type operator()(Index0 ind0, Index1 ind1) const + { return @\exposid{nested-mapping_}@(ind1, ind0); } + + constexpr const @\exposid{nested-mapping-type}@& nested_mapping() const noexcept + { return @\exposid{nested-mapping_}@; } + + static constexpr bool is_always_unique() noexcept + { return @\exposid{nested-mapping-type}@::is_always_unique(); } + static constexpr bool is_always_exhaustive() noexcept + { return @\exposid{nested-mapping-type}@::is_always_exhaustive(); } + static constexpr bool is_always_strided() noexcept + { return @\exposid{nested-mapping-type}@::is_always_strided(); } + + constexpr bool is_unique() const { return @\exposid{nested-mapping_}@.is_unique(); } + constexpr bool is_exhaustive() const { return @\exposid{nested-mapping_}@.is_exhaustive(); } + constexpr bool is_strided() const { return @\exposid{nested-mapping_}@.is_strided(); } + + constexpr index_type stride(size_t r) const; + + template + friend constexpr bool operator==(const mapping& x, const mapping& y); + }; + + private: + @\exposid{nested-mapping-type}@ @\exposid{nested-mapping_}@; // \expos + extents_type @\exposid{extents_}@; // \expos + }; +} +\end{codeblock} + +\pnum +\tcode{Layout} shall meet +the layout mapping policy requirements\iref{mdspan.layout.policy.reqmts}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{Extents} is a specialization of \tcode{std::extents}, and +\item +\tcode{Extents::rank()} equals 2. +\end{itemize} + +\begin{itemdecl} +constexpr explicit mapping(const @\exposid{nested-mapping-type}@& map); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +\begin{itemize} +\item +Initializes \exposid{nested-mapping_} with \tcode{map}, and +\item +initializes \exposid{extents_} +with \tcode{\exposid{transpose-extents}(map.extents())}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +constexpr index_type stride(size_t r) const; +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\expects +\begin{itemize} +\item +\tcode{is_strided()} is \tcode{true}, and +\item +\tcode{r < 2} is \tcode{true}. +\end{itemize} + +\pnum +\returns +\tcode{\exposid{nested-mapping_}.stride(r == 0 ? 1 : 0)} +\end{itemdescr} + +\begin{itemdecl} +template + friend constexpr bool operator==(const mapping& x, const mapping& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +The expression +\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}} +is well-formed and its result is convertible to \tcode{bool}. + +\pnum +\returns +\tcode{x.\exposid{nested-mapping_} == y.\exposid{nested-mapping_}}. +\end{itemdescr} + +\rSec3[linalg.transp.transposed]{Function template \tcode{transposed}} + +\pnum +The \tcode{transposed} function +takes a rank-2 \tcode{mdspan} representing a matrix, and +returns a new \tcode{mdspan} representing the input matrix's transpose. +The input matrix's data are not modified, and +the returned \tcode{mdspan} accesses the input matrix's data in place. +\begin{itemdecl} + template + constexpr auto transposed(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{Extents::rank() == 2} is \tcode{true}. + +\pnum +Let \tcode{ReturnExtents} be +\tcode{\exposid{transpose-extents-t}}. +Let \tcode{R} be +\tcode{mdspan}, +where \tcode{ReturnLayout} is: +\begin{itemize} +\item +\tcode{layout_right} if \tcode{Layout} is \tcode{layout_left}; +\item +otherwise, \tcode{layout_left} if \tcode{Layout} is \tcode{layout_right}; +\item +otherwise, \tcode{layout_stride} if \tcode{Layout} is \tcode{layout_stride}; +\item +otherwise, +\tcode{layout_blas_packed}, +if \tcode{Layout} is\newline +\tcode{layout_blas_packed} +for some \tcode{Triangle} and \tcode{StorageOrder}, where +\begin{itemize} +\item +\tcode{OppositeTriangle} is +\begin{codeblock} +conditional_t, + lower_triangle_t, upper_triangle_t> +\end{codeblock} +and +\item +\tcode{OppositeStorageOrder} is +\begin{codeblock} +conditional_t, row_major_t, column_major_t> +\end{codeblock} +\end{itemize} +\item +otherwise, \tcode{NestedLayout} +if \tcode{Layout} is \tcode{layout_transpose} +for some \tcode{NestedLay\-out}; +\item +otherwise, \tcode{layout_transpose}. +\end{itemize} + +\pnum +\returns +With \tcode{ReturnMapping} being +the type \tcode{typename ReturnLayout::template mapping}: +\begin{itemize} +\item +if \tcode{Layout} is \tcode{layout_left}, \tcode{layout_right}, or +a specialization of \tcode{layout_blas_packed}, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents())), + a.accessor()) +\end{codeblock} +\item +otherwise, if \tcode{Layout} is \tcode{layout_stride}, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(@\exposid{transpose-extents}@(a.mapping().extents()), + array{a.mapping().stride(1), a.mapping().stride(0)}), + a.accessor()) +\end{codeblock} +\item +otherwise, if \tcode{Layout} is a specialization of \tcode{layout_transpose}, +\begin{codeblock} +R(a.data_handle(), a.mapping().nested_mapping(), a.accessor()) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor()) +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_transposed(mdspan> a) { + const auto num_rows = a.extent(0); + const auto num_cols = a.extent(1); + + auto a_t = transposed(a); + assert(num_rows == a_t.extent(1)); + assert(num_cols == a_t.extent(0)); + assert(a.stride(0) == a_t.stride(1)); + assert(a.stride(1) == a_t.stride(0)); + + for(size_t row = 0; row < num_rows; ++row) { + for(size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_t[col, row]); + } + } + + auto a_t_t = transposed(a_t); + assert(num_rows == a_t_t.extent(0)); + assert(num_cols == a_t_t.extent(1)); + assert(a.stride(0) == a_t_t.stride(0)); + assert(a.stride(1) == a_t_t.stride(1)); + + for(size_t row = 0; row < num_rows; ++row) { + for(size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_t_t[row, col]); + } + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.conjtransposed]{Conjugate transpose in-place transform} + +\pnum +The \tcode{conjugate_transposed} function +returns a conjugate transpose view of an object. +This combines the effects of \tcode{transposed} and \tcode{conjugated}. +\begin{itemdecl} + template + constexpr auto conjugate_transposed(mdspan a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return conjugated(transposed(a));} +\end{itemdescr} + +\pnum +\begin{example} +\begin{codeblock} +void test_conjugate_transposed(mdspan, extents> a) { + const auto num_rows = a.extent(0); + const auto num_cols = a.extent(1); + + auto a_ct = conjugate_transposed(a); + assert(num_rows == a_ct.extent(1)); + assert(num_cols == a_ct.extent(0)); + assert(a.stride(0) == a_ct.stride(1)); + assert(a.stride(1) == a_ct.stride(0)); + + for(size_t row = 0; row < num_rows; ++row) { + for(size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == conj(a_ct[col, row])); + } + } + + auto a_ct_ct = conjugate_transposed(a_ct); + assert(num_rows == a_ct_ct.extent(0)); + assert(num_cols == a_ct_ct.extent(1)); + assert(a.stride(0) == a_ct_ct.stride(0)); + assert(a.stride(1) == a_ct_ct.stride(1)); + + for(size_t row = 0; row < num_rows; ++row) { + for(size_t col = 0; col < num_rows; ++col) { + assert(a[row, col] == a_ct_ct[row, col]); + assert(conj(a_ct[col, row]) == a_ct_ct[row, col]); + } + } +} +\end{codeblock} +\end{example} + +\rSec2[linalg.algs.reqs]{Algorithm requirements based on template parameter name} + +\pnum +Throughout +\ref{linalg.algs.blas1}, \ref{linalg.algs.blas2}, and \ref{linalg.algs.blas3}, +where the template parameters are not constrained, +the names of template parameters are used to express the following constraints. +\begin{itemize} +\item +\tcode{is_execution_policy::value} +is \tcode{true}\iref{execpol.type}. +\item +\tcode{Real} is any type such that \tcode{complex} is specified +\iref{complex.numbers.general}. +\item +\tcode{Triangle} is either \tcode{upper_triangle_t} or \tcode{lower_triangle_t}. +\item +\tcode{DiagonalStorage} is +either \tcode{implicit_unit_diagonal_t} or \tcode{explicit_diagonal_t}. +\end{itemize} +\begin{note} +Function templates that have a template parameter named \tcode{ExecutionPolicy} +are parallel algorithms\iref{algorithms.parallel.defns}. +\end{note} + +\rSec2[linalg.algs.blas1]{BLAS 1 algorithms} + +\rSec3[linalg.algs.blas1.complexity]{Complexity} + +\pnum +\complexity +All algorithms in \ref{linalg.algs.blas1} with \tcode{mdspan} parameters +perform a count of \tcode{mdspan} array accesses +and arithmetic operations that is linear in +the maximum product of extents of any \tcode{mdspan} parameter. + +\rSec3[linalg.algs.blas1.givens]{Givens rotations} + +\rSec4[linalg.algs.blas1.givens.lartg]{Compute Givens rotation} + +\begin{itemdecl} +template + setup_givens_rotation_result setup_givens_rotation(Real a, Real b) noexcept; + +template + setup_givens_rotation_result> + setup_givens_rotation(complex a, complex b) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute the Givens plane rotation +represented by the two values $c$ and $s$ +such that the 2 x 2 system of equations +\begin{equation*} +\left[ \begin{matrix} +c & s \\ +-\overline{s} & c \\ +\end{matrix} \right] +\cdot +\left[ \begin{matrix} +a \\ +b \\ +\end{matrix} \right] += +\left[ \begin{matrix} +r \\ +0 \\ +\end{matrix} \right] +\end{equation*} + +holds, where $c$ is always a real scalar, and $c^2 + |s|^2 = 1$. +That is, $c$ and $s$ represent a 2 x 2 matrix, +that when multiplied by the right by the input vector +whose components are $a$ and $b$, +produces a result vector +whose first component $r$ is the Euclidean norm of the input vector, and +whose second component is zero. +\begin{note} +These functions correspond to the LAPACK function \tcode{xLARTG}\supercite{lapack}. +\end{note} + +\pnum +\returns +\tcode{{c, s, r}}, +where \tcode{c} and \tcode{s} form the Givens plane rotation +corresponding to the input \tcode{a} and \tcode{b}, +and \tcode{r} is the Euclidean norm of the two-component vector +formed by \tcode{a} and \tcode{b}. +\end{itemdescr} + +\rSec4[linalg.algs.blas1.givens.rot]{Apply a computed Givens rotation to vectors} + +\begin{itemdecl} +template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s); +template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, Real s); +template<@\exposconcept{inout-vector}@ InOutVec1, @\exposconcept{inout-vector}@ InOutVec2, class Real> + void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex s); +template + void apply_givens_rotation(ExecutionPolicy&& exec, + InOutVec1 x, InOutVec2 y, Real c, complex s); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xROT}\supercite{blas1}. +\end{note} + +\pnum +\mandates +\tcode{\exposid{compatible-static-extents}(0, 0)} is \tcode{true}. + +\pnum +\expects +\tcode{x.extent(0)} equals \tcode{y.extent(0)}. + +\pnum +\effects +Applies the plane rotation +specified by \tcode{c} and \tcode{s} to +the input vectors \tcode{x} and \tcode{y}, +as if the rotation were a 2 x 2 matrix and +the input vectors were successive rows of a matrix with two rows. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.swap]{Swap matrix or vector elements} + +\begin{itemdecl} +template<@\exposconcept{inout-object}@ InOutObj1, @\exposconcept{inout-object}@ InOutObj2> + void swap_elements(InOutObj1 x, InOutObj2 y); +template + void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xSWAP}\supercite{blas1}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()} equals \tcode{y.rank()}. + +\pnum +\mandates +For all \tcode{r} in the range $[0, \tcode{x.rank()})$, +\begin{codeblock} +@\exposid{compatible-static-extents}@(r, r) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\tcode{x.extents()} equals \tcode{y.extents()}. + +\pnum +\effects +Swaps all corresponding elements of \tcode{x} and \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.scal]{Multiply the elements of an object in place by a scalar} + +\begin{itemdecl} +template + void scale(Scalar alpha, InOutObj x); +template + void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xSCAL}\supercite{blas1}. +\end{note} + +\pnum +\effects +Overwrites $x$ with the result of +computing the elementwise multiplication $\alpha x$, +where the scalar $\alpha$ is \tcode{alpha}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.copy]{Copy elements of one matrix or vector into another} + +\begin{itemdecl} +template<@\exposconcept{in-object}@ InObj, @\exposconcept{out-object}@ OutObj> + void copy(InObj x, OutObj y); +template + void copy(ExecutionPolicy&& exec, InObj x, OutObj y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xCOPY\supercite{blas1}}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()} equals \tcode{y.rank()}. + +\pnum +\mandates +For all \tcode{r} in the range $[ 0, \tcode{x.rank()})$, +\begin{codeblock} +@\exposid{compatible-static-extents}@(r, r) +\end{codeblock} +is \tcode{true}. + +\pnum +\expects +\tcode{x.extents()} equals \tcode{y.extents()}. + +\pnum +\effects +Assigns each element of $x$ to the corresponding element of $y$. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.add]{Add vectors or matrices elementwise} + +\begin{itemdecl} +template<@\exposconcept{in-object}@ InObj1, @\exposconcept{in-object}@ InObj2, @\exposconcept{out-object}@ OutObj> + void add(InObj1 x, InObj2 y, OutObj z); +template + void add(ExecutionPolicy&& exec, + InObj1 x, InObj2 y, OutObj z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xAXPY}\supercite{blas1}. +\end{note} + +\pnum +\constraints +\tcode{x.rank()}, \tcode{y.rank()}, and \tcode{z.rank()} are all equal. + +\pnum +\mandates +\tcode{\exposid{possibly-addable}()} is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{addable}(x,y,z)} is \tcode{true}. + +\pnum +\effects +Computes $z = x + y$. + +\pnum +\remarks +\tcode{z} may alias \tcode{x} or \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.dot]{Dot product of two vectors} + +\pnum +\begin{note} +The functions in this section correspond to the BLAS +functions \tcode{xDOT}, \tcode{xDOTU}, and \tcode{xDOTC}\supercite{blas1}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas1.dot}. + +\pnum +\mandates +\tcode{\exposid{compatible-static-extents}(0, 0)} is \tcode{true}. + +\pnum +\expects +\tcode{v1.extent(0)} equals \tcode{v2.extent(0)}. +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dot(InVec1 v1, InVec2 v2, Scalar init); +template + Scalar dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute a non-conjugated dot product +with an explicitly specified result type. + +\pnum +\returns +Let \tcode{N} be \tcode{v1.extent(0)}. +\begin{itemize} +\item +\tcode{init} if \tcode{N} is zero; +\item +otherwise, +\tcode{\placeholdernc{GENERALIZED_SUM}(plus<>(), init, v1[0]*v2[0], \ldots, v1[N-1]*v2[N-1])}. +\end{itemize} + +\pnum +\remarks +If \tcode{InVec1::value_type}, \tcode{InVec2::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec1::value_type} or \tcode{InVec2::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\begin{itemdecl} + template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dot(InVec1 v1, InVec2 v2); + template + auto dot(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions compute a non-conjugated dot product with a default result type. + +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(declval() * declval())}. +Then, +\begin{itemize} +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return dot(v1, v2, T{}); +\end{codeblock} +and +\item +the three-parameter overload is equivalent to: +\begin{codeblock} +return dot(std::forward(exec), v1, v2, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, class Scalar> + Scalar dotc(InVec1 v1, InVec2 v2, Scalar init); +template + Scalar dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2, Scalar init); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions compute a conjugated dot product +with an explicitly specified result type. + +\pnum +\effects +\begin{itemize} +\item +The three-parameter overload is equivalent to: +\begin{codeblock} +return dot(conjugated(v1), v2, init); +\end{codeblock} +and +\item +the four-parameter overload is equivalent to: +\begin{codeblock} +return dot(std::forward(exec), conjugated(v1), v2, init); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2> + auto dotc(InVec1 v1, InVec2 v2); +template + auto dotc(ExecutionPolicy&& exec, + InVec1 v1, InVec2 v2); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions compute a conjugated dot product with a default result type. + +\pnum +\effects +Let \tcode{T} be \tcode{decltype(\exposid{conj-if-needed}(declval()) * decl\-val())}. +Then, +\begin{itemize} +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return dotc(v1, v2, T{}); +\end{codeblock} +and +\item +the three-parameter overload is equivalent to +\begin{codeblock} +return dotc(std::forward(exec), v1, v2, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.ssq]{Scaled sum of squares of a vector's elements} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + sum_of_squares_result vector_sum_of_squares(InVec v, sum_of_squares_result init); +template + sum_of_squares_result vector_sum_of_squares(ExecutionPolicy&& exec, + InVec v, sum_of_squares_result init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the LAPACK function \tcode{xLASSQ}\supercite{lapack}. +\end{note} + +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} is convertible to \tcode{Scalar}. + +\pnum +\effects +Returns a value \tcode{result} such that +\begin{itemize} +\item +\tcode{result.scaling_factor} is the maximum of \tcode{init.scaling_factor} and +\tcode{\exposid{abs-if-needed}(x[i])} +for all \tcode{i} in the domain of \tcode{v}; and +\item +let \tcode{s2init} be +\begin{codeblock} +init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares +\end{codeblock} +then \tcode{result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares} +equals the sum of \tcode{s2init} and +the squares of \tcode{\exposid{abs-if-needed}(x[i])} +for all \tcode{i} in the domain of \tcode{v}. +\end{itemize} + +\pnum +\remarks +If \tcode{InVec::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\rSec3[linalg.algs.blas1.nrm2]{Euclidean norm of a vector} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_two_norm(InVec v, Scalar init); +template + Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xNRM2}\supercite{blas1}. +\end{note} + +\pnum +\mandates +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Then, \tcode{decltype(\linebreak init + a * a} is convertible to \tcode{Scalar}. + +\pnum +\returns +The square root of the sum of the square of \tcode{init} and the squares of the absolute values of the elements of \tcode{v}. +\begin{note} +For \tcode{init} equal to zero, this is the Euclidean norm +(also called 2-norm) of the vector \tcode{v}. +\end{note} + +\pnum +\remarks +If \tcode{InVec::value_type}, and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\begin{note} +An implementation of this function for floating-point types \tcode{T} +can use the \tcode{scaled_sum_of_squares} result from +\tcode{vector_sum_of_squares(x, \{.scaling_factor=1.0, .scaled_sum_of_squares=init\})}. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + auto vector_two_norm(InVec v); +template + auto vector_two_norm(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Let \tcode{T} be \tcode{decltype(a * a)}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return vector_two_norm(v, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return vector_two_norm(std::forward(exec), v, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.asum]{Sum of absolute values of vector elements} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, class Scalar> + Scalar vector_abs_sum(InVec v, Scalar init); +template + Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{SASUM}, \tcode{DASUM}, \tcode{SCASUM}, and \tcode{DZASUM}\supercite{blas1}. +\end{note} + +\pnum +\mandates +\begin{codeblock} +decltype(init + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval())) + + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval()))) +\end{codeblock} +is convertible to \tcode{Scalar}. + +\pnum +\returns +Let \tcode{N} be \tcode{v.extent(0)}. +\begin{itemize} +\item +\tcode{init} if \tcode{N} is zero; +\item +otherwise, if \tcode{InVec::value_type} is an arithmetic type, +\begin{codeblock} +@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init, @\exposid{abs-if-needed}@(v[0]), @\ldots@, @\exposid{abs-if-needed}@(v[N-1])) +\end{codeblock} +\item +otherwise, +\begin{codeblock} +@\placeholdernc{GENERALIZED_SUM}@(plus<>(), init, + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[0])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[0])), + @\ldots@, + @\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(v[N-1])) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(v[N-1]))) +\end{codeblock} +\end{itemize} + +\pnum +\remarks +If \tcode{InVec::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InVec::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + auto vector_abs_sum(InVec v); +template + auto vector_abs_sum(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{T} be \tcode{typename InVec::value_type}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return vector_abs_sum(v, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return vector_abs_sum(std::forward(exec), v, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.iamax]{Index of maximum absolute value of vector elements} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec> + typename InVec::extents_type vector_idx_abs_max(InVec v); +template + typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{IxAMAX}\supercite{blas1}. +\end{note} + +\pnum +Let \tcode{T} be +\begin{codeblock} +decltype(@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(declval())) + + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(declval()))) +\end{codeblock} + +\pnum +\mandates +\tcode{declval() < declval()} is a valid expression. + +\pnum +\returns +\begin{itemize} +\item +\tcode{numeric_limits::max()} + if \tcode{v} has zero elements; +\item +otherwise, the index of the first element of \tcode{v} +having largest absolute value, +if \tcode{InVec::value_type} is an arithmetic type; +\item +otherwise, the index of the first element $\tcode{v}_e$ of \tcode{v} +for which +\begin{codeblock} +@\exposid{abs-if-needed}@(@\exposid{real-if-needed}@(@$\tcode{v}_e$@)) + @\exposid{abs-if-needed}@(@\exposid{imag-if-needed}@(@$\tcode{v}_e$@)) +\end{codeblock} +has the largest value. +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matfrobnorm]{Frobenius norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_frob_norm(InMat A, Scalar init); +template + Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\mandates +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Then, \tcode{decltype(\linebreak init + a * a)} +is convertible to \tcode{Scalar}. + +\pnum +\returns +The square root of the sum of squares +of \tcode{init} and the absolute values of the elements of \tcode{A}. +\begin{note} +For \tcode{init} equal to zero, +this is the Frobenius norm of the matrix \tcode{A}. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_frob_norm(InMat A); +template + auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{a} be +\tcode{\exposid{abs-if-needed}(declval())}. +Let \tcode{T} be +\tcode{decltype(a * a)}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_frob_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_frob_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matonenorm]{One norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_one_norm(InMat A, Scalar init); +template + Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} +is convertible to \tcode{Scalar}. + +\pnum +\returns +\begin{itemize} +\item +\tcode{init} if \tcode{A.extent(1)} is zero; +\item +otherwise, the sum of \tcode{init} and the one norm of the matrix $A$. +\end{itemize} +\begin{note} +The one norm of the matrix \tcode{A} +is the maximum over all columns of \tcode{A}, +of the sum of the absolute values of the elements of the column. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_one_norm(InMat A); +template + auto matrix_one_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(\exposid{abs-if-needed}(declval())}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_one_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_one_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas1.matinfnorm]{Infinity norm of a matrix} + +\pnum +\begin{note} +These functions exist in the BLAS standard\supercite{blas-std} +but are not part of the reference implementation. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Scalar> + Scalar matrix_inf_norm(InMat A, Scalar init); +template + Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{decltype(\exposid{abs-if-needed}(declval()))} +is convertible to \tcode{Scalar}. + +\pnum +\returns +\begin{itemize} +\item +\tcode{init} if \tcode{A.extent(0)} is zero; +\item +otherwise, +the sum of \tcode{init} and the infinity norm of the matrix \tcode{A}. +\end{itemize} +\begin{note} +The infinity norm of the matrix \tcode{A} +is the maximum over all rows of \tcode{A}, +of the sum of the absolute values +of the elements of the row. +\end{note} + +\pnum +\remarks +If \tcode{InMat::value_type} and \tcode{Scalar} +are all floating-point types or specializations of \tcode{complex}, +and if \tcode{Scalar} has higher precision +than \tcode{InMat::value_type}, +then intermediate terms in the sum use \tcode{Scalar}'s precision or greater. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat> + auto matrix_inf_norm(InMat A); +template + auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +\effects +Let \tcode{T} be +\tcode{decltype(\exposid{abs-if-needed}(declval())}. +Then, +\begin{itemize} +\item +the one-parameter overload is equivalent to: +\begin{codeblock} +return matrix_inf_norm(A, T{}); +\end{codeblock} +and +\item +the two-parameter overload is equivalent to: +\begin{codeblock} +return matrix_inf_norm(std::forward(exec), A, T{}); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec2[linalg.algs.blas2]{BLAS 2 algorithms} + +\rSec3[linalg.algs.blas2.gemv]{General matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xGEMV}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.gemv}. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}, and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x,y,z)} is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec x, OutVec y); +template + void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an overwriting matrix-vector product. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\begin{example} +\begin{codeblock} +constexpr size_t num_rows = 5; +constexpr size_t num_cols = 6; + +// y = 3.0 * A * x +void scaled_matvec_1(mdspan> A, + mdspan> x, mdspan> y) { + matrix_vector_product(scaled(3.0, A), x, y); +} + +// z = 7.0 times the transpose of A, times y +void scaled_transposed_matvec(mdspan> A, + mdspan> y, mdspan> z) { + matrix_vector_product(scaled(7.0, transposed(A)), y, z); +} +\end{codeblock} +\end{example} + +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z); + template + void matrix_vector_product(ExecutionPolicy&& exec, + InMat A, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions performs an updating matrix-vector product. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\begin{example} +\begin{codeblock} +// y = 3.0 * A * x + 2.0 * y +void scaled_matvec_2(mdspan> A, + mdspan> x, mdspan> y) { + matrix_vector_product(scaled(3.0, A), x, scaled(2.0, y), y); +} +\end{codeblock} +\end{example} + +\rSec3[linalg.algs.blas2.symv]{Symmetric matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYMV} and \tcode{xSPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.symv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{\exposid{multipliable}(A,x,y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x,y,z)} is \tcode{true} +for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); +template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform an overwriting symmetric matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the symmetric matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +template + void symmetric_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating symmetric matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the symmetric matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.hemv]{Hermitian matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xHEMV} and \tcode{xHPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.hemv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument +has the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(x, y, z)} is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y); +template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an overwriting Hermitian matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +template + void hermitian_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating Hermitian matrix-vector product, +taking into account the \tcode{Triangle} parameter +that applies to the Hermitian matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.trmv]{Triangular matrix-vector product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xTRMV} and \tcode{xTPMV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.trmv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take an \tcode{x} parameter; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{A.extent(0)} equals \tcode{y.extent(0)}, +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)} for those overloads that take an \tcode{x} parameter, and +\item +\tcode{A.extent(0)} equals \tcode{z.extent(0)} for those overloads that take a \tcode{z} parameter. +\end{itemize} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{in-vector}@ InVec, + @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform +an overwriting triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $y = A x$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec y); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform an in-place triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +Performing this operation in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\effects +Computes a vector $y'$ such that $y' = A y$, +and assigns each element of $y'$ to the corresponding element of $y$. + +\pnum +\complexity +\bigoh{\tcode{y.extent(0)} \times \tcode{A.extent(1)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); +template + void triangular_matrix_vector_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec1 x, InVec2 y, OutVec z); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an updating triangular matrix-vector product, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $z = y + A x$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{A.extent(1)}}. + +\pnum +\remarks +\tcode{z} may alias \tcode{y}. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.trsv]{Solve a triangular linear system} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xTRSV} and \tcode{xTPSV}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.trsv}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true} for those overloads that take an \tcode{x} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{A.extent(0)} equals \tcode{b.extent(0)}, and +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)} +for those overloads that take an \tcode{x} parameter. +\end{itemize} + +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); + template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InVec b, OutVec x, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform +a triangular solve, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a vector $x'$ such that $b = A x'$, +and assigns each element of $x'$ to the corresponding element of $x$. +If no such $x'$ exists, +then the elements of \tcode{x} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{in-vector}@ InVec, @\exposconcept{out-vector}@ OutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(A, t, d, b, x, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(std::forward(exec), + A, t, d, b, x, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-vector}@ InOutVec, class BinaryDivideOp> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutVec b, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform an in-place triangular solve, +taking into account the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\effects +Computes a vector $x'$ such that $b = A x'$, +and assigns each element of $x'$ to the corresponding element of $b$. +If no such $x'$ exists, +then the elements of \tcode{b} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(1)} \times \tcode{b.extent(0)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-vector}@ InOutVec> + void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(A, t, d, b, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + void triangular_matrix_vector_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutVec b); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_vector_solve(std::forward(exec), + A, t, d, b, divides{}); +\end{codeblock} +\end{itemdescr} + +\rSec3[linalg.algs.blas2.rank1]{Rank-1 (outer product) update of a matrix} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A); +template + void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a nonsymmetric nonconjugated rank-1 update. +\begin{note} +These functions correspond to the BLAS functions +\tcode{xGER} (for real element types) and +\tcode{xGERU} (for complex element types)\supercite{blas2}. +\end{note} + +\pnum +\mandates +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{multipliable}(A, y, x)} is \tcode{true}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x y^T$, +and assigns each element of $A'$ to the corresponding element of $A$. + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, @\exposconcept{inout-matrix}@ InOutMat> + void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A); +template + void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a nonsymmetric conjugated rank-1 update. +\begin{note} +These functions correspond to the BLAS functions +\tcode{xGER} (for real element types) and +\tcode{xGERC} (for complex element types)\supercite{blas2}. +\end{note} + +\pnum +\effects +\begin{itemize} +\item +For the overloads without an \tcode{ExecutionPolicy} argument, +equivalent to: +\begin{codeblock} +matrix_rank_1_update(x, conjugated(y), A); +\end{codeblock} +\item +otherwise, equivalent to: +\begin{codeblock} +matrix_rank_1_update(std::forward(exec), x, conjugated(y), A); +\end{codeblock} +\end{itemize} +\end{itemdescr} + +\rSec3[linalg.algs.blas2.symherrank1]{Symmetric or Hermitian Rank-1 (outer product) update of a matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR}, \tcode{xSPR}, \tcode{xHER}, and \tcode{xHPR}\supercite{blas2}. +They have overloads taking a scaling factor \tcode{alpha}, +because it would be impossible to express the update +$A = A - x x^T$ otherwise. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.symherrank1}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\item +\tcode{A.extent(0)} equals \tcode{x.extent(0)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{x.extent(0)}}. + +\begin{itemdecl} +template + void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-1 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that +$A' = A + \alpha x x^T$, where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-1 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x x^T$ +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\begin{itemdecl} +template + void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, + Scalar alpha, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that +$A' = A + \alpha x x^H$, where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-1 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes a matrix $A'$ such that $A' = A + x x^H$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\rSec3[linalg.algs.blas2.rank2]{Symmetric and Hermitian rank-2 matrix updates} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR2},\tcode{xSPR2}, \tcode{xHER2} and \tcode{xHPR2}\supercite{blas2}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas2.rank2}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, and +\item +\tcode{\exposid{multipliable}(A, x, y)} is \tcode{true}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{x.extent(0)} \times \tcode{y.extent(0)}}. + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); +template + void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a symmetric rank-2 update of the symmetric matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that $A' = A + x y^T + y x^T$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-vector}@ InVec1, @\exposconcept{in-vector}@ InVec2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t); +template + void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec, + InVec1 x, InVec2 y, InOutMat A, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a Hermitian rank-2 update of the Hermitian matrix \tcode{A}, +taking into account the \tcode{Triangle} parameter +that applies to \tcode{A}\iref{linalg.general}. + +\pnum +\effects +Computes $A'$ such that $A' = A + x y^H + y x^H$ and +assigns each element of $A'$ to the corresponding element of $A$. +\end{itemdescr} + +\rSec2[linalg.algs.blas3]{BLAS 3 algorithms} + +\rSec3[linalg.algs.blas3.gemm]{General matrix-matrix product} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xGEMM}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply +to all functions in \ref{linalg.algs.blas3.gemm} +in addition to function-specific elements. + +\pnum +\mandates +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. + +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, OutMat C); + template + void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C); +template + void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\tcode{\exposid{possibly-addable}()} is \tcode{true}. + +\pnum +\expects +\tcode{\exposid{addable}(E, E, C)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.xxmm]{Symmetric, Hermitian, and triangular matrix-matrix product} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYMM}, \tcode{xHEMM}, and \tcode{xTRMM}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.xxmm} +in addition to function-specific elements. + +\pnum +\mandates +\begin{itemize} +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}, and +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true} for those overloads that take an \tcode{E} parameter. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, B, C)} is \tcode{true}, and +\item +\tcode{\exposid{addable}(E, E, C)} +is \tcode{true} for those overloads that take an \tcode{E} parameter. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\begin{itemdecl} + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C); + template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, OutMat C); + + template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); + template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform a matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat2} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{B.extent(0) == B.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = A B$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E, + OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a potentially overwriting matrix-matrix multiply-add, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the + layout's \tcode{Triangle} template argument has the same type as + the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); +template + void symmetric_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, @\exposconcept{in-matrix}@ InMat3, + @\exposconcept{out-matrix}@ OutMat> + void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); +template + void hermitian_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C); + +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat3, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); +template + void triangular_matrix_product(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E, + OutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform +a potentially overwriting matrix-matrix multiply-add, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} (if applicable) parameters +that apply to the symmetric, Hermitian, or triangular (respectively) matrix \tcode{B}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat2} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\tcode{B.extent(0) == B.extent(1)} is \tcode{true}. + +\pnum +\effects +Computes $C = E + A B$. + +\pnum +\remarks +\tcode{C} may alias \tcode{E}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.trmm]{In-place triangular matrix-matrix product} + +\pnum +These functions perform +an in-place matrix-matrix multiply, +taking into account +the \tcode{Triangle} and \tcode{Diagonal\-Storage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +These functions correspond to the BLAS function \tcode{xTRMM}\supercite{blas3}. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); +template + void triangular_matrix_left_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, C, C)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes a matrix $C'$ such that $C' = A C$ and +assigns each element of $C'$ to the corresponding element of $C$. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C); +template + void triangular_matrix_right_product(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, InOutMat C); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(C, A, C)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes a matrix $C'$ such that $C' = C A$ and +assigns each element of $C'$ to the corresponding element of $C$. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.rankk]{Rank-k update of a symmetric or Hermitian matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYRK} and \tcode{xHERK}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.rankk}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 0)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}, +\item +\tcode{C.extent(0)} equals \tcode{C.extent(1)}, and +\item +\tcode{A.extent(0)} equals \tcode{C.extent(0)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. + +\begin{itemdecl} + template + void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); + template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + \alpha A A^T$, +where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); +template + void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A A^T$, and +assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\begin{itemdecl} +template + void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + Scalar alpha, InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + \alpha A A^H$, +where the scalar $\alpha$ is \tcode{alpha}, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec, + InMat A, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A A^H$, and +assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.rank2k]{Rank-2k update of a symmetric or Hermitian matrix} + +\pnum +\begin{note} +These functions correspond to the BLAS functions +\tcode{xSYR2K} and \tcode{xHER2K}\supercite{blas3}. +\end{note} + +\pnum +The following elements apply to all functions in \ref{linalg.algs.blas3.rank2k}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InOutMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-addable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{addable}(A, B, C)} is \tcode{true}, and +\item +\tcode{A.extent(0)} equals \tcode{A.extent(1)}. +\end{itemize} + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{C.extent(0)}}. + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); +template + void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A B^T + B A^T$, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, @\exposconcept{in-matrix}@ InMat2, + @\exposconcept{possibly-packed-inout-matrix}@ InOutMat, class Triangle> + void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t); +template + void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec, + InMat1 A, InMat2 B, InOutMat C, Triangle t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Computes a matrix $C'$ such that $C' = C + A B^H + B A^H$, +and assigns each element of $C'$ to the corresponding element of $C$. +\end{itemdescr} + +\rSec3[linalg.algs.blas3.trsm]{Solve multiple triangular linear systems} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, then the + layout's \tcode{Triangle} template argument has the same type as + the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, X, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $AX' = B$, +and assigns each element of $X'$ to the corresponding element of $X$. +If no such $X'$ exists, +then the elements of \tcode{X} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{X.extent(1)} \times \tcode{X.extent(1)}}. +\end{itemdescr} + +\pnum +\begin{note} +Since the triangular matrix is on the left, +the desired \tcode{divide} implementation +in the case of noncommutative multiplication +is mathematically equivalent to $y^{-1} x$, +where $x$ is the first argument and $y$ is the second argument, +and $y^{-1}$ denotes the multiplicative inverse of $y$. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(std::forward(exec), + A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} + +\pnum +These functions perform multiple matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat1} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0,1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(X, A, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $X'A = B$, +and assigns each element of $X'$ to the corresponding element of $X$. +If no such $X'$ exists, +then the elements of \tcode{X} are valid but unspecified. + +\pnum +\complexity +$O($ \tcode{B.extent(0)} $\cdot$ \tcode{B.extent(1)} $\cdot$ \tcode{A.extent(1)} $)$ +\begin{note} +Since the triangular matrix is on the right, +the desired \tcode{divide} implementation +in the case of noncommutative multiplication +is mathematically equivalent to $x y^{-1}$, +where $x$ is the first argument and $y$ is the second argument, +and $y^{-1}$ denotes the multiplicative inverse of $y$. +\end{note} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat1, class Triangle, class DiagonalStorage, + @\exposconcept{in-matrix}@ InMat2, @\exposconcept{out-matrix}@ OutMat> + void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat1 A, Triangle t, DiagonalStorage d, + InMat2 B, OutMat X); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(std::forward(exec), + A, t, d, B, X, divides{}); +\end{codeblock} +\end{itemdescr} + +\rSec3[linalg.algs.blas3.inplacetrsm]{Solve multiple triangular linear systems in-place} + +\pnum +\begin{note} +These functions correspond to the BLAS function \tcode{xTRSM}\supercite{blas3}. +\end{note} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple in-place matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +This algorithm makes it possible +to compute factorizations like Cholesky and LU in place. +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} +is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(A, B, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $AX' = B$, +and assigns each element of $X'$ to the corresponding element of $B$. +If so such $X'$ exists, +then the elements of \tcode{B} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} + template + void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_left_solve(std::forward(exec), + A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, + @\exposconcept{inout-matrix}@ InOutMat, class BinaryDivideOp> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B, BinaryDivideOp divide); +\end{itemdecl} + +\begin{itemdescr} +\pnum +These functions perform multiple in-place matrix solves, +taking into account the \tcode{Triangle} and \tcode{DiagonalStorage} parameters +that apply to the triangular matrix \tcode{A}\iref{linalg.general}. +\begin{note} +This algorithm makes it possible +to compute factorizations like Cholesky and LU in place. +Performing triangular solve in place hinders parallelization. +However, other \tcode{ExecutionPolicy} specific optimizations, +such as vectorization, are still possible. +\end{note} + +\pnum +\mandates +\begin{itemize} +\item +If \tcode{InMat} has \tcode{layout_blas_packed} layout, +then the layout's \tcode{Triangle} template argument has +the same type as the function's \tcode{Triangle} template argument; +\item +\tcode{\exposid{possibly-multipliable}()} +is \tcode{true}; and +\item +\tcode{\exposid{compatible-static-extents}(0, 1)} is \tcode{true}. +\end{itemize} + +\pnum +\expects +\begin{itemize} +\item +\tcode{\exposid{multipliable}(B, A, B)} is \tcode{true}, and +\item +\tcode{A.extent(0) == A.extent(1)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Computes $X'$ such that $X'A = B$, +and assigns each element of $X'$ to the corresponding element of $B$. +If so such $X'$ exists, +then the elements of \tcode{B} are valid but unspecified. + +\pnum +\complexity +\bigoh{\tcode{A.extent(0)} \times \tcode{A.extent(1)} \times \tcode{B.extent(1)}}. +\end{itemdescr} + +\begin{itemdecl} +template<@\exposconcept{in-matrix}@ InMat, class Triangle, class DiagonalStorage, @\exposconcept{inout-matrix}@ InOutMat> + void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +template + void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec, + InMat A, Triangle t, DiagonalStorage d, + InOutMat B); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +triangular_matrix_matrix_right_solve(std::forward(exec), + A, t, d, B, divides{}); +\end{codeblock} +\end{itemdescr} diff --git a/source/overloading.tex b/source/overloading.tex index 2c02f343f8..f46353518e 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -185,7 +185,7 @@ \end{itemize} where \tcode{X} -is the class of which the function is a member and +is the class of which the function is a direct member and \cv{} is the cv-qualification on the member function declaration. @@ -1198,6 +1198,10 @@ by the template parameters (including default template arguments) of the constructor, if any. \item +The associated constraints\iref{temp.constr.decl} are the conjunction of +the associated constraints of \tcode{C} and +the associated constraints of the constructor. +\item The types of the function parameters are those of the constructor. \item The return type is the class template specialization @@ -1782,10 +1786,35 @@ or, if not that, \item -\tcode{F1} and \tcode{F2} are non-template functions with the same -parameter-type-lists, and \tcode{F1} is more constrained than \tcode{F2} +\tcode{F1} and \tcode{F2} are non-template functions and +\begin{itemize} +\item +they have the same non-object-parameter-type-lists\iref{dcl.fct}, and +\item +if they are member functions, both are direct members of the same class, and +\item +if both are non-static member functions, +they have the same types for their object parameters, and +\item +\tcode{F1} is more constrained than \tcode{F2} according to the partial ordering of constraints described in -\ref{temp.constr.order}, or if not that, +\ref{temp.constr.order}, +\end{itemize} +or if not that, +\begin{example} +\begin{codeblock} +template +struct S { + constexpr void f(); // \#1 + constexpr void f(this S&) requires true; // \#2 +}; + +void test() { + S<> s; + s.f(); // calls \#2 +} +\end{codeblock} +\end{example} \item \tcode{F1} is a constructor for a class \tcode{D}, @@ -2001,7 +2030,7 @@ are converted to match the corresponding properties of the parameter. \begin{note} -Other properties, such as the lifetime, storage class, +Other properties, such as the lifetime, storage duration, linkage, alignment, accessibility of the argument, whether the argument is a bit-field, and whether a function is deleted\iref{dcl.fct.def.delete}, are ignored. So, although an implicit diff --git a/source/preface.tex b/source/preface.tex index 1e11dd524f..b77caca873 100644 --- a/source/preface.tex +++ b/source/preface.tex @@ -1,4 +1,19 @@ %!TEX root = std.tex + \chapter{Foreword} [This page is intentionally left blank.] + +\chapter{Introduction} + +Clauses and subclauses in this document are annotated +with a so-called stable name, +presented in square brackets next to the (sub)clause heading +(such as ``[lex.token]'' for subclause \ref{lex.token}, ``Tokens''). +Stable names aid in the discussion and evolution of this document +by serving as stable references to subclauses across editions +that are unaffected by changes of subclause numbering. + +Aspects of the language syntax of \Cpp{} are distinguished typographically +by the use of \fakegrammarterm{italic, sans-serif} type +or \tcode{constant width} type to avoid ambiguities; see \ref{syntax}. diff --git a/source/preprocessor.tex b/source/preprocessor.tex index 1d32a61af0..7ca4deabb0 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -1851,6 +1851,7 @@ \defnxname{cpp_nontype_template_args} & \tcode{201911L} \\ \rowsep \defnxname{cpp_nontype_template_parameter_auto} & \tcode{201606L} \\ \rowsep \defnxname{cpp_nsdmi} & \tcode{200809L} \\ \rowsep +\defnxname{cpp_pack_indexing} & \tcode{202311L} \\ \rowsep \defnxname{cpp_placeholder_variables} & \tcode{202306L} \\ \rowsep \defnxname{cpp_range_based_for} & \tcode{202211L} \\ \rowsep \defnxname{cpp_raw_strings} & \tcode{200710L} \\ \rowsep diff --git a/source/ranges.tex b/source/ranges.tex index 2a455af9e2..b4af1f13d4 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -65,9 +65,9 @@ template<@\libconcept{range}@ R> using sentinel_t = decltype(ranges::end(declval())); // freestanding template<@\libconcept{range}@ R> - using const_iterator_t = const_iterator>; // freestanding + using const_iterator_t = decltype(ranges::cbegin(declval())); // freestanding template<@\libconcept{range}@ R> - using const_sentinel_t = const_sentinel>; // freestanding + using const_sentinel_t = decltype(ranges::cend(declval())); // freestanding template<@\libconcept{range}@ R> using range_difference_t = iter_difference_t>; // freestanding template<@\libconcept{sized_range}@ R> @@ -393,7 +393,7 @@ // \ref{range.as.const}, as const view template<@\libconcept{input_range}@ R> - constexpr auto& @\exposid{possibly-const-range}@(R& r) { // \expos + constexpr auto& @\exposid{possibly-const-range}@(R& r) noexcept { // \expos if constexpr (@\libconcept{constant_range}@ && !@\libconcept{constant_range}@) { return const_cast(r); } else { @@ -600,7 +600,7 @@ \pnum In addition to being available via inclusion of the \libheader{ranges} header, the customization point objects in \ref{range.access} are -available when \libheaderrefx{iterator}{iterator.synopsis} is included. +available when the header \libheaderrefx{iterator}{iterator.synopsis} is included. \pnum Within \ref{range.access}, @@ -1184,7 +1184,7 @@ \begin{codeblock} template -constexpr auto @\exposid{as-const-pointer}@(const T* p) { return p; } // \expos +constexpr auto @\exposid{as-const-pointer}@(const T* p) noexcept { return p; } // \expos \end{codeblock} \pnum @@ -2685,6 +2685,7 @@ constexpr auto end() const; constexpr @\exposid{iterator}@ end() const requires @\libconcept{same_as}@; + constexpr bool empty() const; constexpr auto size() const requires @\seebelow@; }; @@ -2902,6 +2903,17 @@ Equivalent to: \tcode{return \exposid{iterator}\{\exposid{bound_}\};} \end{itemdescr} +\indexlibrarymember{empty}{iota_view}% +\begin{itemdecl} +constexpr bool empty() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{value_} == \exposid{bound_};} +\end{itemdescr} + \indexlibrarymember{size}{iota_view}% \begin{itemdecl} constexpr auto size() const requires @\seebelow@; @@ -11884,7 +11896,7 @@ adjacent_transform_view() = default; constexpr explicit adjacent_transform_view(V base, F fun); - constexpr V base() const & requires @\libconcept{copy_constructible}@<@\exposid{InnerView}@> { return @\exposid{inner_}@.base(); } + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{inner_}@.base(); } constexpr V base() && { return std::move(@\exposid{inner_}@).base(); } constexpr auto begin() { @@ -14982,7 +14994,7 @@ (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && @\exposconcept{cartesian-product-common-arg}@<@\exposid{maybe-const}@>)); - template + template concept @\defexposconcept{cartesian-product-is-common}@ = // \expos @\exposconcept{cartesian-product-common-arg}@; diff --git a/source/regex.tex b/source/regex.tex index eb015cc6ed..f8882f3d83 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -33,6 +33,10 @@ \ref{re.grammar} & Grammar & \\ \end{libsumtab} +\pnum +The ECMAScript Language Specification described in Standard Ecma-262 +is called \defn{ECMA-262} in this Clause. + \rSec1[re.req]{Requirements} \pnum @@ -2131,8 +2135,8 @@ \indextext{requirements!container}% \indextext{requirements!sequence}% The class template \tcode{match_results} meets the requirements of an -allocator-aware container and of -a sequence container\iref{container.alloc.reqmts,sequence.reqmts} +allocator-aware container\iref{container.alloc.reqmts} and of +a sequence container\iref{container.requirements.general,sequence.reqmts} except that only copy assignment, move assignment, and diff --git a/source/statements.tex b/source/statements.tex index 4f0c773c51..70d713e9ef 100644 --- a/source/statements.tex +++ b/source/statements.tex @@ -187,10 +187,9 @@ \indextext{side effects}% side effects from an expression statement are completed before the next statement is executed. -\indextext{statement!null}% \indextext{statement!empty}% An expression statement with the expression missing is called -a \defn{null statement}. +a \defnadj{null}{statement}. \begin{note} Most statements are expression statements --- usually assignments or function calls. A null statement is useful to supply a null body to an @@ -847,7 +846,7 @@ \indextext{function return|see{\tcode{return}}}% \pnum -A function returns to its caller by the \tcode{return} statement. +A function returns control to its caller by the \tcode{return} statement. \pnum The \grammarterm{expr-or-braced-init-list} @@ -916,8 +915,8 @@ \end{bnf} \pnum -A coroutine returns to its caller or resumer\iref{dcl.fct.def.coroutine} -by the \keyword{co_return} statement or when suspended\iref{expr.await}. +A \keyword{co_return} statement transfers control to +the caller or resumer of a coroutine\iref{dcl.fct.def.coroutine}. A coroutine shall not enclose a \tcode{return} statement\iref{stmt.return}. \begin{note} @@ -951,7 +950,8 @@ \end{itemize} \pnum -If \placeholder{p}\tcode{.return_void()} is a valid expression, +If a search for the name \tcode{return_void} in the scope of the promise type +finds any declarations, flowing off the end of a coroutine's \grammarterm{function-body} is equivalent to a \keyword{co_return} with no operand; otherwise flowing off the end of a coroutine's \grammarterm{function-body} diff --git a/source/std.tex b/source/std.tex index f179e402e8..c97d4302bd 100644 --- a/source/std.tex +++ b/source/std.tex @@ -13,6 +13,7 @@ {listings} % code listings \usepackage{longtable} % auto-breaking tables \usepackage{ltcaption} % fix captions for long tables +\usepackage{caption} % caption style \usepackage{relsize} % provide relative font size changes \usepackage{textcomp} % provide \text{l,r}angle \usepackage{underscore} % remove special status of '_' in ordinary text diff --git a/source/strings.tex b/source/strings.tex index 7b5a1aef30..1d786b7099 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -533,12 +533,13 @@ \indexheader{string_view}% \begin{codeblock} +// mostly freestanding #include // see \ref{compare.syn} namespace std { // \ref{string.view.template}, class template \tcode{basic_string_view} template> - class basic_string_view; + class basic_string_view; // partially freestanding template constexpr bool ranges::@\libspec{enable_view}{basic_string_view}@> = true; @@ -559,7 +560,7 @@ template basic_ostream& operator<<(basic_ostream& os, - basic_string_view str); + basic_string_view str); // hosted // \tcode{basic_string_view} \grammarterm{typedef-name}s using string_view = basic_string_view; @@ -663,7 +664,7 @@ // \ref{string.view.access}, element access constexpr const_reference operator[](size_type pos) const; - constexpr const_reference at(size_type pos) const; + constexpr const_reference at(size_type pos) const; // freestanding-deleted constexpr const_reference front() const; constexpr const_reference back() const; constexpr const_pointer data() const noexcept; @@ -674,17 +675,22 @@ constexpr void swap(basic_string_view& s) noexcept; // \ref{string.view.ops}, string operations - constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; + constexpr size_type copy(charT* s, size_type n, + size_type pos = 0) const; // freestanding-deleted - constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const; + constexpr basic_string_view substr(size_type pos = 0, + size_type n = npos) const; // freestanding-deleted constexpr int compare(basic_string_view s) const noexcept; - constexpr int compare(size_type pos1, size_type n1, basic_string_view s) const; + constexpr int compare(size_type pos1, size_type n1, + basic_string_view s) const; // freestanding-deleted constexpr int compare(size_type pos1, size_type n1, basic_string_view s, - size_type pos2, size_type n2) const; + size_type pos2, size_type n2) const; // freestanding-deleted constexpr int compare(const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s) const; - constexpr int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const; + constexpr int compare(size_type pos1, size_type n1, + const charT* s) const; // freestanding-deleted + constexpr int compare(size_type pos1, size_type n1, const charT* s, + size_type n2) const; // freestanding-deleted constexpr bool starts_with(basic_string_view x) const noexcept; constexpr bool starts_with(charT x) const noexcept; @@ -751,10 +757,10 @@ any operation that invalidates a pointer in the range \begin{codeblock} -@\range{str.data()}{\brk{}str.data() + str.size()}@ +@\range{str.data()}{str.data() + str.size()}@ \end{codeblock} invalidates pointers, iterators, and references -returned from \tcode{str}'s member functions. +to elements of \tcode{str}. \pnum The complexity of \tcode{basic_string_view} member functions is \bigoh{1} @@ -1311,9 +1317,12 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}. + \pnum \effects -Equivalent to: \tcode{return substr(0, x.size()) == x;} +Equivalent to: \tcode{return basic_string_view(data(), rlen) == x;} \end{itemdescr} \indexlibrarymember{starts_with}{basic_string_view}% @@ -1344,11 +1353,14 @@ \end{itemdecl} \begin{itemdescr} +\pnum +Let \tcode{rlen} be the smaller of \tcode{size()} and \tcode{x.size()}. + \pnum \effects Equivalent to: \begin{codeblock} -return size() >= x.size() && compare(size() - x.size(), npos, x) == 0; +return basic_string_view(data() + (size() - rlen), rlen) == x; \end{codeblock} \end{itemdescr} @@ -1439,7 +1451,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1466,7 +1478,7 @@ \item \tcode{xpos + str.size() <= size()} \item -\tcode{traits::eq(at(xpos + I), str.at(I))} for all elements \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos + I], str[I])} for all elements \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1493,7 +1505,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1520,7 +1532,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for some element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for some element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1547,7 +1559,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -1573,7 +1585,7 @@ \item \tcode{xpos < size()} \item -\tcode{traits::eq(at(xpos), str.at(I))} for no element \tcode{I} of the string referenced by \tcode{str}. +\tcode{traits::eq(data_[xpos], str[I])} for no element \tcode{I} of the string referenced by \tcode{str}. \end{itemize} \pnum @@ -2378,7 +2390,7 @@ the character traits requirements\iref{char.traits}. \begin{note} Every specialization \tcode{basic_string} is -an allocator-aware container, +an allocator-aware container\iref{container.alloc.reqmts}, but does not use the allocator's \tcode{construct} and \tcode{destroy} member functions\iref{container.requirements.pre}. The program is ill-formed if @@ -3009,8 +3021,8 @@ \effects A directive that informs a \tcode{basic_string} of a planned change in size, so that the storage allocation can be managed accordingly. -After -\tcode{reserve()}, +Following a call to +\tcode{reserve}, \tcode{capacity()} is greater or equal to the argument of \tcode{reserve} @@ -3019,7 +3031,7 @@ \tcode{capacity()} otherwise. Reallocation happens at this point if and only if -the current capacity is less than the argument of \tcode{reserve()}. +the current capacity is less than the argument of \tcode{reserve}. \pnum \throws @@ -5516,7 +5528,7 @@ size_t strspn(const char* s1, const char* s2); // freestanding const char* strstr(const char* s1, const char* s2); // freestanding; see \ref{library.c} char* strstr(char* s1, const char* s2); // freestanding; see \ref{library.c} - char* strtok(char* s1, const char* s2); // freestanding + char* strtok(char* s1, const char* s2); void* memset(void* s, int c, size_t n); // freestanding char* strerror(int errnum); size_t strlen(const char* s); // freestanding diff --git a/source/styles.tex b/source/styles.tex index d77f983b38..8d771e10db 100644 --- a/source/styles.tex +++ b/source/styles.tex @@ -87,8 +87,8 @@ %%-------------------------------------------------- % set heading style for annexes \newcommand{\Annex}[3]{\chapter[#2]{(#3)\protect\\#2\hfill[#1]}\relax\annexlabel{#1}} -\newcommand{\infannex}[2]{\Annex{#1}{#2}{informative}\addxref{#1}} -\newcommand{\normannex}[2]{\Annex{#1}{#2}{normative}\addxref{#1}} +\newcommand{\infannex}[2]{\addxref{#1}\Annex{#1}{#2}{informative}} +\newcommand{\normannex}[2]{\addxref{#1}\Annex{#1}{#2}{normative}} %%-------------------------------------------------- %% set footnote style @@ -113,6 +113,8 @@ %%-------------------------------------------------- %% set caption style \captionstyle{\centering} +\DeclareCaptionLabelSeparator{emdash}{ --- } +\captionsetup{labelsep=emdash,font+=bf} %%-------------------------------------------------- %% set global styles that get reset by \mainmatter diff --git a/source/support.tex b/source/support.tex index 5d76edc882..0148590585 100644 --- a/source/support.tex +++ b/source/support.tex @@ -602,7 +602,7 @@ #define @\defnlibxname{cpp_lib_constexpr_bitset}@ 202207L // also in \libheader{bitset} #define @\defnlibxname{cpp_lib_constexpr_charconv}@ 202207L // also in \libheader{charconv} #define @\defnlibxname{cpp_lib_constexpr_cmath}@ 202306L // also in \libheader{cmath}, \libheader{cstdlib} -#define @\defnlibxname{cpp_lib_constexpr_complex}@ 201711L // also in \libheader{complex} +#define @\defnlibxname{cpp_lib_constexpr_complex}@ 202306L // also in \libheader{complex} #define @\defnlibxname{cpp_lib_constexpr_dynamic_alloc}@ 201907L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_constexpr_functional}@ 201907L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_constexpr_iterator}@ 201811L // freestanding, also in \libheader{iterator} @@ -619,6 +619,7 @@ // \libheader{deque}, \libheader{queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_copyable_function}@ 202306L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} +#define @\defnlibxname{cpp_lib_debugging}@ 202311L // freestanding, also in \libheader{debugging} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // freestanding, also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_endian}@ 201907L // freestanding, also in \libheader{bit} @@ -631,26 +632,35 @@ #define @\defnlibxname{cpp_lib_filesystem}@ 201703L // also in \libheader{filesystem} #define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map} #define @\defnlibxname{cpp_lib_flat_set}@ 202207L // also in \libheader{flat_set} -#define @\defnlibxname{cpp_lib_format}@ 202306L // also in \libheader{format} +#define @\defnlibxname{cpp_lib_format}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_format_ranges}@ 202207L // also in \libheader{format} +#define @\defnlibxname{cpp_lib_format_uchar}@ 202311L // also in \libheader{format} #define @\defnlibxname{cpp_lib_formatters}@ 202302L // also in \libheader{stacktrace}, \libheader{thread} #define @\defnlibxname{cpp_lib_forward_like}@ 202207L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_freestanding_algorithm}@ 202311L // freestanding, also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_freestanding_array}@ 202311L // freestanding, also in \libheader{array} #define @\defnlibxname{cpp_lib_freestanding_char_traits}@ 202306L // freestanding, also in \libheader{string} #define @\defnlibxname{cpp_lib_freestanding_charconv}@ 202306L // freestanding, also in \libheader{charconv} #define @\defnlibxname{cpp_lib_freestanding_cstdlib}@ 202306L // freestanding, also in \libheader{cstdlib}, \libheader{cmath} -#define @\defnlibxname{cpp_lib_freestanding_cstring}@ 202306L // freestanding, also in \libheader{cstring} +#define @\defnlibxname{cpp_lib_freestanding_cstring}@ 202311L // freestanding, also in \libheader{cstring} #define @\defnlibxname{cpp_lib_freestanding_cwchar}@ 202306L // freestanding, also in \libheader{cwchar} #define @\defnlibxname{cpp_lib_freestanding_errc}@ 202306L // freestanding, also in \libheader{cerrno}, \libheader{system_error} +#define @\defnlibxname{cpp_lib_freestanding_expected}@ 202311L // freestanding, also in \libheader{expected} #define @\defnlibxname{cpp_lib_freestanding_feature_test_macros}@ 202306L // freestanding #define @\defnlibxname{cpp_lib_freestanding_functional}@ 202306L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_freestanding_iterator}@ 202306L // freestanding, also in \libheader{iterator} +#define @\defnlibxname{cpp_lib_freestanding_mdspan}@ 202311L // freestanding, also in \libheader{mdspan} #define @\defnlibxname{cpp_lib_freestanding_memory}@ 202306L // freestanding, also in \libheader{memory} +#define @\defnlibxname{cpp_lib_freestanding_numeric}@ 202311L // freestanding, also in \libheader{numeric} #define @\defnlibxname{cpp_lib_freestanding_operator_new}@ @\seebelow@ // freestanding, also in \libheader{new} +#define @\defnlibxname{cpp_lib_freestanding_optional}@ 202311L // freestanding, also in \libheader{optional} #define @\defnlibxname{cpp_lib_freestanding_ranges}@ 202306L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_freestanding_ratio}@ 202306L // freestanding, also in \libheader{ratio} +#define @\defnlibxname{cpp_lib_freestanding_string_view}@ 202311L // freestanding, also in \libheader{string_view} #define @\defnlibxname{cpp_lib_freestanding_tuple}@ 202306L // freestanding, also in \libheader{tuple} #define @\defnlibxname{cpp_lib_freestanding_utility}@ 202306L // freestanding, also in \libheader{utility} +#define @\defnlibxname{cpp_lib_freestanding_variant}@ 202311L // freestanding, also in \libheader{variant} #define @\defnlibxname{cpp_lib_fstream_native_handle}@ 202306L // also in \libheader{fstream} #define @\defnlibxname{cpp_lib_function_ref}@ 202306L // also in \libheader{functional} #define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // also in \libheader{numeric} @@ -687,6 +697,7 @@ #define @\defnlibxname{cpp_lib_jthread}@ 201911L // also in \libheader{stop_token}, \libheader{thread} #define @\defnlibxname{cpp_lib_latch}@ 201907L // also in \libheader{latch} #define @\defnlibxname{cpp_lib_launder}@ 201606L // freestanding, also in \libheader{new} +#define @\defnlibxname{cpp_lib_linalg}@ 202311L // also in \libheader{linalg} #define @\defnlibxname{cpp_lib_list_remove_return_type}@ 201806L // also in \libheader{forward_list}, \libheader{list} #define @\defnlibxname{cpp_lib_logical_traits}@ 201510L // freestanding, also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_make_from_tuple}@ 201606L // freestanding, also in \libheader{tuple} @@ -708,14 +719,14 @@ #define @\defnlibxname{cpp_lib_not_fn}@ 202306L // freestanding, also in \libheader{functional} #define @\defnlibxname{cpp_lib_null_iterators}@ 201304L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_optional}@ 202110L // also in \libheader{optional} -#define @\defnlibxname{cpp_lib_out_ptr}@ 202106L // also in \libheader{memory} +#define @\defnlibxname{cpp_lib_out_ptr}@ 202311L // freestanding, also in \libheader{memory} #define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} #define @\defnlibxname{cpp_lib_print}@ 202207L // also in \libheader{print}, \libheader{ostream} #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} #define @\defnlibxname{cpp_lib_ranges}@ 202302L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} -#define @\defnlibxname{cpp_lib_ranges_as_const}@ 202207L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_as_const}@ 202311L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_as_rvalue}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_cartesian_product}@ 202207L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // freestanding, also in \libheader{ranges} @@ -742,6 +753,7 @@ // freestanding, also in \libheader{functional}, \libheader{type_traits} #define @\defnlibxname{cpp_lib_robust_nonmodifying_seq_ops}@ 201304L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_sample}@ 201603L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_saturation_arithmetic}@ 202311L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_scoped_lock}@ 201703L // also in \libheader{mutex} #define @\defnlibxname{cpp_lib_semaphore}@ 201907L // also in \libheader{semaphore} #define @\defnlibxname{cpp_lib_shared_mutex}@ 201505L // also in \libheader{shared_mutex} @@ -752,7 +764,8 @@ #define @\defnlibxname{cpp_lib_smart_ptr_for_overwrite}@ 202002L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_smart_ptr_owner_equality}@ 202306L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_source_location}@ 201907L // freestanding, also in \libheader{source_location} -#define @\defnlibxname{cpp_lib_span}@ 202002L // also in \libheader{span} +#define @\defnlibxname{cpp_lib_span}@ 202311L // freestanding, also in \libheader{span} +#define @\defnlibxname{cpp_lib_span_initializer_list}@ 202311L // also in \libheader{span} #define @\defnlibxname{cpp_lib_spanstream}@ 202106L // also in \libheader{spanstream} #define @\defnlibxname{cpp_lib_ssize}@ 201902L // freestanding, also in \libheader{iterator} #define @\defnlibxname{cpp_lib_sstream_from_string_view}@ 202306L // also in \libheader{sstream} @@ -777,7 +790,7 @@ #define @\defnlibxname{cpp_lib_transparent_operators}@ 201510L // freestanding, also in \libheader{memory}, \libheader{functional} #define @\defnlibxname{cpp_lib_tuple_element_t}@ 201402L // freestanding, also in \libheader{tuple} -#define @\defnlibxname{cpp_lib_tuple_like}@ 202207L +#define @\defnlibxname{cpp_lib_tuple_like}@ 202311L // also in \libheader{utility}, \libheader{tuple}, \libheader{map}, \libheader{unordered_map} #define @\defnlibxname{cpp_lib_tuples_by_type}@ 201304L // freestanding, also in \libheader{utility}, \libheader{tuple} #define @\defnlibxname{cpp_lib_type_identity}@ 201806L // freestanding, also in \libheader{type_traits} @@ -1069,7 +1082,7 @@ \pnum For floating-point types, the number of \tcode{radix} digits in the -mantissa. +significand. \begin{footnote} Equivalent to \tcode{FLT_MANT_DIG}, \tcode{DBL_MANT_DIG}, \tcode{LDBL_MANT_DIG}. diff --git a/source/templates.tex b/source/templates.tex index 1950689f30..048add70e2 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -306,9 +306,8 @@ called \tcode{T}, rather than an unnamed non-type \grammarterm{template-parameter} of class \tcode{T}. \end{example} -A storage class shall not be specified in a -\grammarterm{template-parameter} -declaration. +A \grammarterm{template-parameter} declaration shall not +have a \grammarterm{storage-class-specifier}. Types shall not be defined in a \grammarterm{template-parameter} declaration. @@ -392,6 +391,7 @@ are ignored when determining its type. \pnum +\label{term.structural.type}% A \defnadj{structural}{type} is one of the following: \begin{itemize} \item a scalar type, or @@ -411,12 +411,11 @@ a non-type \grammarterm{template-parameter} of class type \tcode{T} denotes a static storage duration object of type \tcode{const T}, known as a \defn{template parameter object}, -whose value is that of the corresponding template argument +which is template-argument-equivalent\iref{temp.type} to +the corresponding template argument after it has been converted -to the type of the \grammarterm{template-parameter}. -All such template parameters in the program of the same type -with the same value denote the same template parameter object. -A template parameter object shall have constant destruction\iref{expr.const}. +to the type of the \grammarterm{template-parameter}\iref{temp.arg.nontype}. +No two template parameter objects are template-argument-equivalent. \begin{note} If an \grammarterm{id-expression} names a non-type non-reference \grammarterm{template-parameter}, @@ -483,40 +482,27 @@ for the invented type corresponding to the placeholder\iref{dcl.fct}. \pnum -A -\defnx{default template-argument}{\idxgram{template-argument}!default} -is a -\grammarterm{template-argument}\iref{temp.arg} specified after -\tcode{=} -in a -\grammarterm{template-parameter}. -A default -\grammarterm{template-argument} -may be specified for any kind of -\grammarterm{template-parameter} -(type, non-type, template) +A \defnadj{default}{template argument} is +a template argument \iref{temp.arg} specified after \tcode{=} +in a \grammarterm{template-parameter}. +A default template argument may be specified for +any kind of \grammarterm{template-parameter} (type, non-type, template) that is not a template parameter pack\iref{temp.variadic}. -A default -\grammarterm{template-argument} -may be specified in a template declaration. -A default -\grammarterm{template-argument} -shall not be specified in the -\grammarterm{template-parameter-list}{s} -of the definition of a member of a class template that appears outside -of the member's class. -A default -\grammarterm{template-argument} +A default template argument may be specified in a template declaration. +A default template argument shall not be specified in +the \grammarterm{template-parameter-list}{s} +of the definition of a member of a class template +that appears outside of the member's class. +A default template argument shall not be specified in a friend class template declaration. If a friend function template declaration $D$ -specifies a default \grammarterm{template-argument}, +specifies a default template argument, that declaration shall be a definition and there shall be no other declaration of the function template which is reachable from $D$ or from which $D$ is reachable. \pnum -The set of default -\grammarterm{template-argument}{s} +The set of default template arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are\iref{dcl.fct.default}. @@ -532,29 +518,24 @@ \end{example} \pnum -If a -\grammarterm{template-parameter} -of a class template, variable template, or alias template has a default -\grammarterm{template-argument}, -each subsequent -\grammarterm{template-parameter} -shall either have a default -\grammarterm{template-argument} -supplied -or be a template parameter pack. If a \grammarterm{template-parameter} -of a primary class template, primary variable template, or alias template -is a template parameter pack, it shall be the last -\grammarterm{template-parameter}. -A template parameter pack of a function template shall not be followed by -another -template parameter unless that template parameter can be deduced from the -parameter-type-list\iref{dcl.fct} of the function template or has a -default argument\iref{temp.deduct}. +If a \grammarterm{template-parameter} +of a class template, variable template, or alias template has +a default template argument, +each subsequent \grammarterm{template-parameter} +shall either have a default template argument supplied or +be a template parameter pack. +If a \grammarterm{template-parameter} of +a primary class template, primary variable template, or alias template +is a template parameter pack, +it shall be the last \grammarterm{template-parameter}. +A template parameter pack of a function template +shall not be followed by another template parameter +unless that template parameter can be deduced from the +parameter-type-list\iref{dcl.fct} of the function template or +has a default argument\iref{temp.deduct}. A template parameter of a deduction guide template\iref{temp.deduct.guide} -that does not have a default argument -shall be deducible -from the parameter-type-list -of the deduction guide template. +that does not have a default argument shall be deducible +from the parameter-type-list of the deduction guide template. \begin{example} \begin{codeblock} template class B; // error @@ -567,15 +548,10 @@ \indextext{\idxcode{<}!template and}% \pnum -When parsing a -default -\grammarterm{template-argument} -for a non-type -\grammarterm{template-parameter}, -the first non-nested -\tcode{>} -is taken as the end of the -\grammarterm{template-parameter-list} +When parsing a default template argument +for a non-type \grammarterm{template-parameter}, +the first non-nested \tcode{>} is taken as +the end of the \grammarterm{template-parameter-list} rather than a greater-than operator. \begin{example} \begin{codeblock} @@ -588,16 +564,12 @@ \end{example} \pnum -A -\grammarterm{template-parameter} -of a template -\grammarterm{template-parameter} -is permitted to have a default -\grammarterm{template-argument}. -When such default arguments are specified, they apply to the template -\grammarterm{template-parameter} -in the scope of the template -\grammarterm{template-parameter}. +A \grammarterm{template-parameter} of +a template \grammarterm{template-parameter} +is permitted to have a default template argument. +When such default arguments are specified, +they apply to the template \grammarterm{template-parameter} +in the scope of the template \grammarterm{template-parameter}. \begin{example} \begin{codeblock} template