Roland Mainz
2013-08-11 20:57:40 UTC
On Sun, Aug 11, 2013 at 6:15 PM, Cedric Blancher
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
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
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
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 aliasmyself, 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
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
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?
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
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.
|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.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)