On Sun, Aug 11, 2013 at 6:15 PM, Cedric Blancher
<cedric.blanc...@gmail.com> wrote:
> On 11 August 2013 10:43, Tina Harriott <tina.harriott.m...@gmail.com> wrote:
>> On Wed, Jul 24, 2013 at 7:28 PM, Glenn Fowler <g...@research.att.com> wrote:
>>>
>>> On Wed, 24 Jul 2013 19:02:39 +0200 Tina Harriott wrote:
>>>> Here's one of my little tough problems which I am unable to solve
>>>> myself, even after looking at the source code of ast-ksh. The problem
>>>> below requires a good understanding how floating point numbers are
>>>> implemented in computers.
>>>
>>>> I'm trying to prototype code and like to iterate over a small, linear
>>>> area by using the C library function nextafter() to step forward the
>>>> smallest possible distance between each step, and print the number of
>>>> iterations needed to cover the distance between 4 and 4.000000000001:
>>>> ksh -c 'float v ; integer iter ; for ((iter=0,v=4 ; v < 4.000000000001
>>>> && iter < 10000000; v=nextafter(v,4.000000000001))) ; do
>>>> ((iter++));done;print $iter '
>>>> 2305843
>>>
>>>> The result 2305843 is correct.
>>>
>>>> However, if I use typeset -E (or just typeset) to declare the variable
>>>> v the loop runs forever, or in this case until it hits iter < 10000000
>>>> which I added as safeguard later:
>>>> ksh -c 'typeset -E v ; integer iter ; for ((iter=0,v=4 ; v <
>>>> 4.000000000001 && iter < 10000000; v=nextafter(v,4.000000000001))) ;
>>>> do ((iter++));done;print $iter '
>>>> 10000000
>>>
>>>> Can anyone explain this?
>>>
>>> float is an alias
>>> this shows the alias definition
>>>         type float
>>> which is
>>>         typeset -lE
>>> this documents -l
>>>         typeset --?l
>>>
>>> so for your example
>>>         typeset -E
>>> gave you a double v and
>>>         typeset -lE
>>> would give you a "long double" v
>>
>> 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 ?

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.ma...@nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)
_______________________________________________
ast-users mailing list
ast-users@lists.research.att.com
http://lists.research.att.com/mailman/listinfo/ast-users

Reply via email to