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...

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) [email protected]
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)
diff -r -u original/src/cmd/ksh93/sh/arith.c 
build_i386_64bit_debug/src/cmd/ksh93/sh/arith.c
--- src/cmd/ksh93/sh/arith.c    2013-06-04 22:14:14.000000000 +0200
+++ src/cmd/ksh93/sh/arith.c    2013-08-11 23:49:21.027203489 +0200
@@ -502,8 +502,12 @@
                r = nv_getnum(np);
                if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
                        lvalue->isfloat= (r!=(Sflong_t)r);
+               else 
if(nv_isattr(np,(NV_DOUBLE|NV_SHORT))==(NV_DOUBLE|NV_SHORT))
+                       lvalue->isfloat=2;
+               else if(nv_isattr(np,(NV_DOUBLE|NV_LONG))==(NV_DOUBLE|NV_LONG))
+                       lvalue->isfloat=3;
                else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
-                       lvalue->isfloat=1;
+                       lvalue->isfloat=4;
                if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
                        lvalue->nosub = nv_aindex(np)+1;
                return(r);
diff -r -u original/src/cmd/ksh93/sh/streval.c 
build_i386_64bit_debug/src/cmd/ksh93/sh/streval.c
--- src/cmd/ksh93/sh/streval.c  2013-07-23 20:48:04.000000000 +0200
+++ src/cmd/ksh93/sh/streval.c  2013-08-12 00:01:19.333351488 +0200
@@ -492,7 +492,28 @@
                        if(c&T_NOFLOAT)
                                num = (*((Math_2f_i)fun))(sp[1],(int)num);
                        else
-                               num = (*((Math_2f_f)fun))(sp[1],num);
+                       {
+                               if (((void*)fun) == ((void*)nextafterl))
+                               {
+                                       switch(node.isfloat)
+                                       {
+                                               case 2:
+                                                       num = 
(nextafterf)((float)sp[1],(float)num);
+                                                       break;
+                                               case 3:
+                                                       num = 
(nextafterl)((long double)sp[1],(long double)num);
+                                                       break;
+                                               default:
+                                               case 4:
+                                                       num = 
(nextafter)((double)sp[1],(double)num);
+                                                       break;
+                                       }
+                               }
+                               else
+                               {
+                                       num = (*((Math_2f_f)fun))(sp[1],num);
+                               }
+                       }
                        break;
                    case A_CALL2I:
                        sp-=2,tp-=2;
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers

Reply via email to