On Mon, 12 Aug 2013 11:15:00 +0200 Tina Harriott wrote:
> On 12 August 2013 07:29, Irek Szczesniak <[email protected]> wrote:
> > On Mon, Aug 12, 2013 at 1:16 AM, Roland Mainz <[email protected]>
> > wrote:
> >> On Mon, Aug 12, 2013 at 12:28 AM, Roland Mainz <[email protected]>
> >> wrote:
> >> [Removing [email protected]]
> >>> On Mon, Aug 12, 2013 at 12:14 AM, Roland Mainz <[email protected]>
> >>> wrote:
> >>>> On Sun, Aug 11, 2013 at 10:57 PM, Roland Mainz
> >>>> <[email protected]> wrote:
> >>>>> On Sun, Aug 11, 2013 at 6:15 PM, Cedric Blancher
> >>>>> <[email protected]> wrote:
> >>>>>> On 11 August 2013 10:43, Tina Harriott <[email protected]>
> >>>>>> wrote:
> >>>>>>> On Wed, Jul 24, 2013 at 7:28 PM, Glenn Fowler <[email protected]>
> >>>>>>> wrote:
> >>>>>>>> On Wed, 24 Jul 2013 19:02:39 +0200 Tina Harriott wrote:
> >>>> [snip]
> >>>>>>> But why does nextafter() misbehave if I want to use a datatype smaller
> >>>>>>> than "long double"? Accuracy is a good thing, but in this case we
> >>>>>>> iterate too fine-grained, meaning the code should iterate over the
> >>>>>>> smallest possible steps of a double, but not over the smallest
> >>>>>>> possible steps of a long double.
> >>>>>>
> >>>>>> Does anyone have a good idea how to fix this in ksh?
> >>>>>
> >>>>> Grumpf... yes. Technically I feared that day may come when
> >>>>> |nextafter()| and |nexttoward()| were added in ksh93... ;-/
> >>>>>
> >>>>> The issue is more or less like this: Both |nextafter(f|l|)\(\)| and
> >>>>> |nexttoward(f|l|)\(\)| step over the smallest possible quantity for
> >>>>> the specific { |float|, |double|, |long double| }-datatype and
> >>>>> therefore (for example) using |nextafterl()| (intended for |long
> >>>>> double|) for a |float| doesn't work because it does so small steps
> >>>>> that they cannot be represented in a |float| ... that causes the
> >>>>> endless loop in Tina's example.
> >>>>>
> >>>>> The fix would be to "remember" the datatype (e.g. { |float|,
> >>>>> |double|, |long double| }) for a given variable and pass that down to
> >>>>> |arith_exec()| and call the specific version of |nextafter()| and
> >>>>> |nexttoward()| for that datatype, for example:
> >>>>> - variables declared via typeset -s -E/-X should use
> >>>>> |nextafterf()|/|nexttowardf()|
> >>>>> - variables declared via typeset -E/-X should use
> >>>>> |nextafter()|/|nexttoward()|
> >>>>> - variables declared via typeset -l -E/-X should use
> >>>>> |nextafterl()|/|nexttowardl()|
> >>>>> ... if the platforms libc/libm do not have a matching
> >>>>> |nextafter(f|l|)\(\)|/|nexttoward(f|l|)\(\)| variant for the input
> >>>>> datatype then the "function not found"-error should be thrown.
> >>>>>
> >>>>> Note that we do _not_ have to change the logic for all math
> >>>>> functions... AFAIK |nextafter()| and |nexttoward()| are the only
> >>>>> exceptions which require special handling...
> >>>>>
> >>>>> Glenn: What do you think ?
> >>>>
> >>>> Attached (as "astksh20130807_short_float_nextafter001.diff.txt") is a
> >>>> _prototype_ patch which shows how it would look like:
> >>>> -- snip --
> >>>> $ ksh -c 'typeset -s -E x=4 ; print $(( x=nextafter(x,5) ))'
> >>>> 4.0000004768371582
> >>>> $ ksh -c 'typeset -E x=4 ; print $(( x=nextafter(x,5) ))'
> >>>> 4.00000000000000089
> >>>> $ ksh -c 'typeset -l -E x=4 ; print $(( x=nextafter(x,5) ))'
> >>>> 4 # this is not exactly 4 but it is so a tiny step away from 4 that
> >>>> normal %f output doesn't recognise it
> >>>> -- snip --
> >>>>
> >>>> * ToDo:
> >>>> - Add |nexttoward()| support
> >>>> - Add defines for type size (|float|, |double|, |long double|)
> >>>> - Add error code in case if one of the { |float|, |double|, |long
> >>>> double| }-variants is missing
> >>>> - Somehow make the code look better
> >>>>
> >>>> Comments/rants/feedback welcome...
> >>>
> >>> Grumpf... attached (as
> >>> "astksh20130807_short_float_nextafter002.diff.txt") is a fixed
> >>> patch... the previous one used |double| in case that the datatype of
> >>> the arguments couldn't be obtained... the patch corrects this and adds
> >>> support for |nexttoward()| ...
> >>
> >> More thought about this:
> >> src/cmd/ksh93/data/math.tab could return all three variants (for {
> >> |float|, |double|, |long double| }) and |fun| in |arith_exec()| would
> >> be a pointer to an array of these three variants. That would make the
> >> support for |float| and |double| generic and remove all the
> >> |if()|/|switch()| mess from the "hot" codepath...
> >
> > That is IMO the only solution which covers *all* corner cases, i.e. if
> > an overflow/underflow or creation of subnormal numbers in a math
> > function happens. Smaller datatypes mean you'll hit the limits earlier
> > than for larger datatypes and not all float/double functions behave
> > like doing the same operation with a long double datatype and then
> > cast the result to the requested datatype.
> Irek, I looked at this. Using a wider datatype and then cast to the
> narrower datatype yields an error only in the last bit:
> #include <stdlib.h>
> #include <stdio.h>
> #include <math.h>
> int main()
> {
> long double al;
> double a;
> double al_d;
> long double r;
> a = tan(-0.001);
> al = tanl(-0.001);
> al_d = al;
> r = fabs(a-al_d);
> printf("diff=%a\n", r);
this should be
printf("diff=%La\n", r);
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers