For rounding modes, I have been thinking that if we do support them, we would do it in some way
of decorating a block or function to indicate the desired rounding mode, so that this detail would be
known at compile time vs. run time. In IEEE 754 terminology, I am saying that I think that ideally,
should support associating a constant rounding direction attribute with a block, but that Chapel never
needs to support a dynamic-mode rounding attribute.
Constant rounding is no benefit, well to me and a few others at least. I have never seen a need.
What is needed is the ability to run a block of code, or more likely, a whole program, at a given rounding mode. That might take a day (say) to run. Then you run it the next day with a different rounding mode. And the day after you compare the results. Hopefully, the two are much the same. If not, you have to dig deeper and that means dynamically isolating various chunks so you need flexibility.
And with the new RISC-V specification now supporting round-to-away giving users two round-to-nearest modes that can be used to test algorithm robustness, I expect that a need to change rounding modes will grow.
Re-running code to do physical simulations with different rounding modes can also help isolate bifurcation points or places where closely spaced eigenvalues do naughty things.
And no, people cannot easily recompile a whole program because they may not have access to the source code.
In the IEEE 754 spec is 7.1 it talks about default exception handling which seems to be about having a
reasonable result and setting some status flags. I am OK with having some facility to query these status
flags. I don't like the way that setting and querying the status flags in C is not tied to particular
blocks/computations (as far as I know).
How would you tie it to blocks? Sounds interesting. And a decorator (or pragma) is not allowed, although a new language feature is.
Many people might use it while testing algorithm performance like:
flags = _754exceptions.archive(_754exceptions.All)
const flags = _754exceptions.test(_754exceptions.All);
process results and look at, or report on, the local copy of 'flags'
That looks pretty closely tied to the block to me.
Is that what you mean when you talk about:
I think the we would meet IEEE 754 7.1's requirements if we had a way to write a block where you can
check for particular situations that result from instructions in that block (say, floating point underflow).
That said, you also need a way to say
// assume that the underflow and inexact flags have already been cleared
x = algorithm1(a, b, c)
if _754exceptions.test(_754exceptions.Underflow | _754exceptions.InExact) then
x = algorithm2(a, b, c)
This can be rewritten in the earlier style, albeit in a more long winded fashion.
Note that I prefer to write a more robust algorithm in the first place, even it it takes longer to run. But a lot of people prefer the above method, i.e. run the quickest algorithm first and then go to a fallback if need be.
The exceptions for which you have to test may not even be param so even though the above has lots of things known at compile time, other scenarios may need to use run-time choices.
The _754exception module is only drafted. But I have rewritten a whole C fenv interface so that it is vastly more generic and is devoid of logic in assembler. This is for another project. Only a few lines of inline assembler to get at those system registers. Once I did the exception stuff, the rounding stuff was trivial. Porting the C code to Chapel I expect will not be too hard but I want to finish the C project first.
This _754exception module does assume that if I ask for a statement to be done in one place, I expect the compiler to honour my request which as you mention, might be an issue with LLVM.