Hi Damian --

As a blanket disclaimer on this response (and part of the reason I didn't chime in on your last thread): I'm not at all a floating point expert and rely upon learning from those who are moreso (like you) to help guide Chapel's design in sensible and attractive ways.


Currently there is

        param INFINITY : real(64)
and
        proc NAN : real(64)

I'm not seeing that INFINITY is a param. It appears to me that both symbols are proc's:

http://chapel.cray.com/docs/latest/modules/standard/Math.html?highlight=nan#Math.NAN
http://chapel.cray.com/docs/latest/modules/standard/Math.html?highlight=infinity#Math.INFINITY

I'm guessing this means you've found some other documentation that needs updating. If so, can you tell me where you got your definitions?


i note that there are no 32 bit equivalents

I think this would be a great feature request (if not code contribution) -- would you be willing to open a GitHub issue requesting it, and ideally proposing symbol names / interfaces for accessing these values?

A related question in my mind is whether there should be imag(*) equivalents of these constants, or whether the programmer should be required to cast between real and imaginary in such cases?


Why is it not a 'proc param'?

The current implementations rely on evaluating the C definitions at execution time, so aren't available at compile-time (a requirement to be a param). I'm not enough of a floating point expert to be 100% confident, but would imagine that these values are sufficiently well-defined that they could be represented/computed in the Chapel source (e.g., via a hex floating point literal?), in which case they could be written as 'proc param's or simply 'param's.

[All that said, Chapel does not currently do much compile-time optimization of floating point 'param' values, so making them 'param' would likely not have a big impact at present (unless it helped the back-end compiler with optimizations). This of course may improve in the future...].

[Aside: I found myself curious why they are 'proc's rather than simply 'const's, and with a quick check, believe that the answer relates to the supporting them in the LLVM back-end.]


To write truly templated code, something the C standard did not have to consider, do we need something like

        proc fpINFINITY(fudge : real(64)) param real(64) ......
        proc fpINFINITY(fudge : real(32)) param real(32) ......
        proc fpNAN(fudge : real(64)) param real(64) ......
        proc fpNAN(fudge : real(32)) param real(32) ......

Rather than using 'fudge', if I were pursuing a procedure-based approach like this, I'd simply make them functions that took a type argument:

        proc fpINFINITY(type t): real(64) where t == real(64) ...
        proc fpINFINITY(type t): real(32) where t == real(32) ...

in which case you could call:

        fpINFINITY(real(32))
        fpINFINITY(real(64))
        fpINFINITY(real)


or are such constants an attribute of a real, e.g.

        var x : real(64)

        assert(isinf(x.INFINITY()) == true)
or
        assert(isnan(x.NAN()) == true)

They're definitely standalone constants at present, though we could make them into methods on a real value -- or better, the real type -- if that was considered attractive. For example, the following declaration:

        proc type real.INFINITY return INFINITY;

says to define a method named 'INFINITY' on the (64-bit) real type, and supports calls like:

        writeln(real.INFINITY);
        writeln(real(64).INFINITY);

I believe we _ought_ to also be able to create overloads on 32- vs. 64-bit real types like so:

        proc type (real(32)).INFINITY return INFINITY;
        proc type (real(64)).INFINITY return INFINITY;

but I'm having trouble getting them to compile today. I suspect this is due to a bug in the compiler related to 'real's being treated as somewhat more of a special type than typical generics...

If the 'type' keyword were dropped on the declarations above, they'd apply to values of those types rather than the types themselves.



What about when Chapel rules the HPC/GPU space and Chapel has to support the IEEE types

        real(128)
or
        real(16)

I certainly think we'd want to support such types and their related constants as well.


Also how viable/smart is my use of 'fudge' because it is just a dummy variable except for its number of bits?

See above for some counterproposals that avoid 'fudge'.


Assume that if I want a set of templated functions to return say the limits of the exponents of a given IEEE754 floating point number

        proc fpEmax(x : real(32)) : param return 127:int(32);

        proc fpEmax(x : real(64)) : param return 1023:int(64);

        proc fpEmin(x : real(32)) : param return -126:int(32);

        proc fpEmin(x : real(64)) : param return -1022:int(64);

Is there a better way to guarantee the correct templated instantiation?

Here also, I'd make the arguments 'type's rather than values, but other than that, I think you're on the right track.

Thanks for your continued thoughts and feedback in this,
-Brad

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers

Reply via email to