David send Roland a comment that nextafter(x+1.1,5) does not figure the data type of x+1.1 correctly and always uses the data type of the right value.
IMO the rules of ISO C (C1X) should apply. The difficult part is that I do not know how to do that with the arithmetic engine in ksh, some how the value of node.isfloat (which is now a kind of enum describing which kind of floating point data type is used - float, double, long double) must be recalculated based on the left hand lhand_node.isfloat and right hand rhand_node.isfloat value of such operations. Olga On Mon, Aug 12, 2013 at 6:36 PM, Glenn Fowler <g...@research.att.com> wrote: > > On Sun, 11 Aug 2013 22:57:40 +0200 Roland Mainz wrote: >> 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. > > this looks like the problem > >> 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 ? > > I'll meet with dgk shortly > > _______________________________________________ > ast-users mailing list > ast-users@lists.research.att.com > http://lists.research.att.com/mailman/listinfo/ast-users -- , _ _ , { \/`o;====- Olga Kryzhanovska -====;o`\/ } .----'-/`-/ olga.kryzhanov...@gmail.com \-`\-'----. `'-..-| / http://twitter.com/fleyta \ |-..-'` /\/\ Solaris/BSD//C/C++ programmer /\/\ `--` `--` _______________________________________________ ast-users mailing list ast-users@lists.research.att.com http://lists.research.att.com/mailman/listinfo/ast-users