Open lydia-duncan opened 2 years ago
They are not C rounding modes, they are the rounding modes supported by the IEEE 754 standard.
I did not know that #11970 was considering dropping rounding modes and I was part of the conversation. What did I miss and when?
As far as I knew, it was only that there was the possibility that, for now, it is problematic to change rounding modes but that is a compiler problem which needs fixing. Firstly and finally, that problem needs to be addressed longer term. But even without being able to change those modes, these functions are extremely useful in their own right. Specifically, because the default rounding mode is rounding-to-nearest-with-ties-to-even, rint()
is the only way to achieve such rounding of a real(w) datum. But that routine may affect the IEEE 754 Exception state. And if you want that functionality but do not want to mess with the Exception state, you still need nearbyint()
functionality. So ditching these functions is totally out of the question.
But yes, the name sucks. It is a version of rint()
that never affects the INEXACT floating point exception state. When actually, what happens is we capture the state, call rint()
, and then if the INEXACT floating point exception was affected, we save it back to what it was before. Both the latest ARM and IBM's System Z support this in hardware. For anything else, see below.
Using a lot of imagination, this routine can be thought of as
proc rintWithoutException(x : ?R) : R
{
const e = ieee754.testException(ieee754.inexact);
const t = rint(x);
if (e != ieee754.inexactException)
{
ieee754.voidException(ieee754.inexact);
}
return t;
}
The name has not been around long enough for me to object to a change of name over existing practice.
I have used a method on a real(w) called rintNo754X()
but that name might be too spartan for some.
I did not know that #11970 was considering dropping rounding modes and I was part of the conversation. What did I miss and when?
As far as I knew, it was only that there was the possibility that, for now, it is problematic to change rounding modes but that is a compiler problem which needs fixing.
I wouldn't characterize it as dropping them, since we don't really support them much to begin with. It's not just problematic to change rounding modes (though that's definitely a problem) - it's also that we don't even support querying them in code today. You mention:
the default rounding mode is rounding-to-nearest-with-ties-to-even
But that's just something you personally know, and you don't have a way to check if someone else has happened to change it for a particular piece of code you're running - C does provide functions for that, but we don't wrap them today. That's what I mean when I say that nearbyint
and rint
aren't useful in Chapel code today - there isn't a good way to predict what they're going to do without relying on meta knowledge or implementing your own calls out to C. That's not great for functions we're blessing as part of our standard library.
Now, that's not to say that we couldn't still provide them in the interim. We could choose to mark them as unstable for Chapel 2.0 - they'd still be available to programs, but we wouldn't make any assurances about whether we'd break them in the future. But saying that we might break them in the future isn't great either. So it sounds like you'd push for nailing down rounding support for 2.0, is that fair?
The name has not been around long enough for me to object to a change of name over existing practice.
I have used a method on a real(w) called rintNo754X() but that name might be too spartan for some.
What about something like roundSpecified
? roundCurrent
? controlledRound
? Those all seem a bit long to me, but maybe they'll inspire a better name.
We could even merge rint
and nearbyint
into a single function that takes a boolean on whether to use the exception version or not, if we were feeling particularly creative.
With regard to rint
and nearbyint
, it was mentioned
we don't really support them much to begin with
If Chapel is going to be IEEE 754 compliant, then this needs to be fixed rather than dropping rint
. Unless you are going for backwards compatability, IEEE754-2019 says you can ditch 'nearbyintbut need to implement an exceptionless
Rounding-To-Nearest-Ties-To-Even` routine.
Note that any Chapel program must start life with its rounding mode as rounding-to-nearest-ties-to-even
. It is not just something I personally know, it is mandated. If I cannot change it, the default will hold. And if I call routines written others which mess with the rounding mode, I assume they are polite enough to restore it to what it was before they did their messing.
If Chapel is going to say it is not IEEE 754 compliant, then that is a whole new ball game.
The best way to attack this problem is to
remembering that a lot of people adopting Chapel might want to use familiar names, that programs need to read well as a description of the mathematics, and be readable by people who want them as an ultimate reference for the algorithm.
I like the fact that you have choices in names but new names are premature at this stage. Also, the fact that there is a routine called round
which implements only a single rounding mode, and not the default one at that, makes life hard to start with.
Like roundCurrent, roundSpecified (definitely too long), controlledRound (no thanks), but rint is pervasive. Users love it, people remember it, it rolls off the tongue easily, it reads clearly, and now that nobody needs to remember its mate nearbyint
, you would get flak cutting it. My 2c.
A lot of these modes on be implemented in a single machine instruction so merged routines might not cut it, although optimization might prove me wrong. I think ARM has individual instructions for each of the five modes. Intel does not but goes down the backward compatability route. Not sure about RISC-V and others.
Later....
The rounding of 'x' is a mapping of x to either a) itself if its fractional part is zero b) one its two non-fractional neighbours
For case (b), the choice of neighbour is driven by the rounding mode, one of:
1) Directed Rounding { Towards Positive | Away from Negative | Above | Up } 2) Directed Rounding { Towards Negative | Away from Positive | Below | Down } 3) Directed Rounding { Towards Zero | Away from Infinity } 4) Rounding To Nearest returning in the event of a tie the ... non-fractional neighbour of x with the larger magnitude (away from zero) 5) Rounding To Nearest returning in the event of a tie the ... non-fractional neighbour of x which is an even integer
There is the concept of the current rounding mode which is one of (1)..(5), which defaults to (5). When that rounding mode is requested at run-time, the CPU chooses the appropriate one. This is called
6) The Current Rounding Mode.
The C/C++ current practice names are:
- ceil
- floor
- trunc
- round
- roundeven
- rint
Chapel supports all except roundeven. All except roundeven are historic names with long provenance. The name 'trunc' goes back to the early 1970s and Pascal.
Unfortunately, with 20/20 hindsight, 'round' was a poor choice because it is only one of the five IEEE types of rounding, and one of two types of round-to-nearest, i.e. where ties are forced away from zero. If its was chosen with the same thought pattern as 'roundeven', it may be called:
roundaway
or roundlarger.
That particular background, and some from Fortran, means some people use other names.
Calling it Enhanced Current Practice A, these would be:
- ceiling - breaking changes(taken from Fortran)
- floor
- trunc
- roundaway - breaking change (but reflects a commonality with 'roundeven')
- roundeven
- rint
That said, 'even', 'away' and 'larger' all have nothing to do with the actual rounding but everything about what happens with a tie, or when the fractional part of the number to be rounded is 0.5. So those names could be a lot more descriptive and be
roundTiesToEven
and roundTiesToAway (or roundTiesToLarger).
The names in Enhanced Current Practice A are a bit messy. A mix of nouns, abbreviations and phrases.
Limiting oneselves to verb[+qualification], we might get a new nomenclature mix.
This results in Enhanced Current Practice II - all breaking but all adjectival (some qualified)
- roundedabove - a.k.a. ceiling
- roundedbelow - a.k.a. floor
- truncated
- roundedTiesToAway or roundedTiesToLarger
- roundedTiesToEven
- rounded - a.k.a. rint
The last name could be
roundedcurrent
but it is long, like so many of the above. Long names look awful in formulae.
Alternatively you can run with nouns[+qualifications] for a different mix:
- ceiling
- floor
- truncated
- nearestTiesToLarger (or nearestTiesToAway)
- nearestTiesToEven
- rounded
Except for the first two, there is not a lot of sound mathematical basis for the names.
And the historical names of the last four are too long, are all less than optimal, and above all breaking unless the old names are retained as aliases for a while before being deprecated.
Maybe you can drop the 'To' in those long names.
As extra background, ....
floor'ed rounding, truncated rounding, and nearestTiesToEven rounding are the basis behind respectively.
remaindering as implemented by Chapel's 'mod' routine
remaindering as implemented by Chapel's '%' operator
remaindering as mandated by the IEE754's 'rem' functionality
Ada & Lisp agree with Chapel and call remaindering by flooring 'mod'.
Fortran & C both call remaindering by truncation 'mod' - Ada calls it 'rem'.
All food for thought.
Another simpler approach is a mix of provenance and mechanical name derivation.
Let's grab the names of rounding operations mandated by the IEEE 754 standard:
* Round To Integral Towards Positive
* Round To Integral Towards Negative
* Round To Integral Towards Zero
* Round To Integral Ties To Away
* Round To Integral Ties To Even
* Round To Integral Exact
These are verbatim and are precisely (and clearly) described. Spaces have been inserted into the names to make them more readable to a human.
For the first 3, use the mathematically accepted verb for that operation, i.e.
ceil as in, ... to ceil the interior of the roof with plaster or panelling
floor as in, ... to floor the accelerator
truncate
We cannot use truncate because of a name clash with a file operation so let's revert to the abbreviation Wirth used in Pascal 50 years ago, i.e.
trunc
At least I am in good company if that is a bad choice! Feed free to disagree!
Not unsurprisingly, these match what Chapel (and C/C++) already does, i.e.
ceil
floor
trunc
So no breaking changes so far.
There are no accepted mathematical names for the last 3 operations and using names out of air like tom, dick and harry is not really an option.
Let's take a mechanical approach to this. Looking at the words within the IEEE 754 operation, drop every word except the first and last of that same operation. This is the approach the CFP interest group took when creating a name for the second last case in C23. So we are in good company!!
So dropping all but the first & last words of the operation, we have:
roundaway
roundeven
roundexact
The first is new, the second agrees with C23, the last is arguably better than rint
even though that name is well known and easy to remember. Feel free to disagree!!
The name round
will be kept as an alias for roundaway
in Chapel for the foreseeable future but marked for deprecation at some point. Probably should do the same for rint
.
So again, we are not making any breaking changes with these last 3 names.
In summary, the rounding operations then become
ceil
floor
trunc
roundaway
roundeven
roundexact
Not perfect, but this is more functionally complete that what we have and the nomenclature is no worse.
These are unstable for 2.0, we intend to design more thorough rounding support after that. Removing the 2.0 tag
If in #11970 we decide to not support the C rounding modes, these functions are not really useful. If we do decide to support that particular style of rounding mode, we should camelCase
nearbyint
tonearbyInt