You might simply want to start by saying that the intended user of this library is someone who NEEDS to store and operate with decimal fractions like 0.1. Other than that, decimal arithmetic is not superior in any way. For example on a trinary computer 1.0/3.0 + 2.0/3.0 == 1.0, but on binary or decimal it is not.
That's fair.
1) "Decimal floating point numbers avoid this issue by storing the significand in base-10 (decimal)."
Not true. My understanding from your explanations was that your library internally uses BID - binary encoded decimal. State that.
It's listed here: https://cppalliance.org/decimal/decimal.html#conversions, but I'll move it up towards the top.
2) "The other major difference between binary and decimal floating point types is that the latter allows for multiple representations of the same number. For example 1e5 could also be stored as 0.1e6, 0.01e7, so on and so forth."
Does your library really store 0.01e7 as such? In excel, when I type 535e-6 it immediately changes it into 5.35e-4 -- correct behavior it seems to me.
The IEEE 754 compliant types do because they are required to. The fast types normalize everything in the constructor because then everything is significantly easier to work with.
Related: Wikipedia article on engineering notation states: "Engineering notation or engineering form (also technical notation) is a version of scientific notation in which the exponent of ten is always selected to be divisible by three to match the common metric prefixes" --- I do not know if this is widely used but choosing this option for printing must be within scope for your library. Excel has it with custom formatting ###.0E+00 , this will make the exponent a multiple of three: 535.0E-06, unbelievable but true.
Nothing in the IEEE 754, the TR, or existing STL specify this, nor has anyone ever requested it as a feature.
3) "These are referred to as cohorts which binary does not have as there is only one way to represent each number in binary floating point."
I try 0x11p-5 versus 0x1.1p-1 in my C++17 compiler, it is accepted and printed as the same number. It could be that I misunderstand what you are trying to say here and you mean that the library does not necessarily impose normalized numbers, but a detailed explanation of this must be in the documentation.
To be honest, I would like to require any Boost author to be required to document in detail the algorithms implemented by the library. Maybe you would like to set the good example? What exactly does your library do when it does the four arithmetic operations?
Chris and I are preparing an ACM TOMS paper to answer that question. I don't think it would be useful to detail the inner workings of such things in user docs. Once it's submitted we can add something like an Arxiv link for the motivated to read.
It was added a bit back after your request. See: https://cppalliance.org/decimal/decimal.html#cmath_trunc_to.
trunc is good but round is also essential and highly nontrivial.
See Cowlishaw paper: "4.1.1. Commercial rounding. The extra rounding mode is called round-half-up, which is a requirement for many financial calculations (especially for tax purposes and in Europe). In this mode, if the digits discarded during rounding represent greater than or equal to half (0.5) of the value of a one in the next left position then the re- sult should be rounded up. Otherwise the discarded dig- its are ignored. This is in contrast to round-half-even, the default IEEE 854 rounding mode, where if the dis- carded digits are exactly half of the next digit then the least significant digit of the result will be even. It is also recommended that implementations offer two further rounding modes: round-half-down (where a 0.5 case is rounded down) and round-up (round away from zero). "
All 5 rounding modes are already supported: https://cppalliance.org/decimal/decimal.html#cfenv. The trunc_to function was a specific addition to what is already specified in <cmath>. We have nearly all of <cmath> implemented minus some of the C++17 special math functions.
"4.2.6. ... An important operator, rescale, sets the exponent of a number and adjusts its coefficient (with rounding, if necessary) to maintain its value. For example, rescaling the number {0, 1234567, −4} so its exponent is −2 gives {0, 12346, −2}. This example is the familiar, and very heavily used, ‘round to cents’ operation, although rescale has many other uses (round-to-integer is a special case of rescale, for example)."
The point he makes in 4.2.5 should also be taken into account somehow.
So the trunc_to function is basically the rescale operator. I don't remember seeing that in any of the specifications (odd since Cowlishaw is the IEEE 754-2019 editor). I'll deprecate the former and change the name for consistency. Thanks for bringing it to my attention. Matt