- This is in answer to Bryce's question about how we should be working towards a Numeric TS.
- It's my (John McF's) frank and personal opinion about the bits I care about.
- Written a day before the Cologne 2019 meeting.
I interpreted from Kona LEWG-I minutes that we're still exploring the design space. Specific work done by me for Cologne:
- P1751R0 is a description of 'numeric families' -- a phrase discussed near the end of the review of P0037/P0554/P0828 in LEWG-I.
- P1050R1 has a new section "Overflow, Reduction and Normalization" which essentially explains why P1050 is not the same type as P1438. This follows review of P1050R0 in SG6.
- P0037R7 changes the top-level API for the type from
fixed_point<Rep, Exponent, Radix>
toscaled_integer<Rep, power<Exponent, Radix>
. Mentioned Ada fixed-point types. Had a stab at describing requirements forRep
parameter. - P0554R1 revived. It's the top-level paper proposing all of the static-ranged types in combination.
P0554 is the nearest thing we have to a TS paper since P0101R0 in 2015. However, I'm not personally interested in dynamic-range types such as P1438 (unbounded rational) or N4038 (unbounded integer). I totally support that work but I think there is limited opportunity for interaction between bounded and unbounded:
- We should be working toward being able to write generic code which can be instantiated on a wide variety of types.
Currently, it's hard enough to write a function template which takes both ints and floats. With good prep, users can at
least write:
a) function templates which take any integer such as:
int
,integral
(the P0106 integer which I break down in P0554), orinteger
(the N4038) type, and b) function templates which take any real number such as:float
negatable
(the P0106 fixed-point whicih I break down in P0554), or- some unbounded library real, and maybe
fraction
andrational
.
- It would be nice if P1050 and P1438 were designed in such a way that P1050 could support implementation of P1438 and even feature in its interface.
Concentrating on bounded (static width) types, I'm afraid there's a lot of detail in there which has barely made it to WG21:
- Important:
wide_integer
and overflow-trapping are not active currently. I talk about both in P0554. I have a half-baked implementation of the former and a half-decent implementation of the latter (as I'd propose them). - Quasi-exact division and multiplication. An type is desired which is essentially identical to P0037 but with multiplication and division that promote in special ways.
- Less important (I think) is
rounding_integer
which has not yet seen the light of day outside. (P0105, P0106 and P0554 all mention rounding.) constant
needs to be defribulated. It's a replacement forintegral_constant
. Enhances the other types.- Free functions (P0105) are also requested a lot. It would be a shame if we specify types which deal with rounding,
overflow etc. and then duplicated all the work with
rounding_integer
,overflow_integer
etc.. It's also extra implementation work and user brain load. To remedy this, I'm currently working on a tag-based system where only a single numeric type is necessary:integer<Rep, BehaviorTag>
separates the concerns of storage and behaviour and taps into a comprehensive set of free functions to get you something likegeneric_operator<rounding<nearest>, divide, int, int>(8, 3) // returns 3
which provides the backing forinteger<rounding<nearest>, int>{8}/integer<rounding<nearest>, int>{3}
. Something equivalent is needed to facilitate user-cusomisation. Work in progress. - Traits: P0102, P0103, P0675 and P1751 all touch upon the area of number traits. They are useful on their own but are also necessary to allow composition.
- Concepts: I was asked in Rapperswil to think about conepts (also semantic requirements). I've pondered this and asked around but am not at all clear on what expectations are.
I think if we're smart about how the components are broken down, a TS is achievable. But some serious guidance is needed to avoid wasted effort here:
- How are numeric types, operators and free functions specified? E.g. what are the concepts for operands? For
Rep
types? Etc.. - How does composition actually happen? Aliases, inheritance, judicious hand-waving in the wording, etc.?
- Reflection and metaclasses may change everything. How do we prepare foir a world where a single metaclass might be capable of producing all of the number types in the TS?
- How much do we care about interop with SIMD pack, linear algebra, , complex, chrono, ML?
- How will units coexist with this work if that ever gets off the ground?
- How are we doing customisation? Aside from one blog post by Eric, I'm struggling to find clear guidance here that matches what numerics needs. Maybe some rules could go here? This could completely change how operators, tags and thus numeric types are designed.
- Generic operators, e.g.
generic_operator<Tag, Operation, ...Operands>(Operands &&...)
- Operator tags, e.g.
multiply
,unary_minus
,bitwise_xor
. (Better alternatives to arithmetic operators.) - Behaviour Tags, e.g.
rounding<nearest>
,overflow<contract>
,power<2, -16>
integer<Rep, BehaviorTag>
(possibly)- The specialised scalar types, e.g.
rounding_integer
,scaled_integer
, etc.. - Odd types:
constant
,fraction
- Numeric traits:
set_signedness<Rep, bool>
,set_digits<Rep, NumDigits>
etc..
- My primary goal remains to introduce P0037 and my related proposals into the IS. This document assumes that a Numerics TS is the only route to achieving that goal. It should not be interpreted as an endorsement of the TS over any other vehicle.