Re: New proposal for math.e

new topic     » goto parent     » topic index » view thread      » older message » newer message

Juergen Luethje wrote:
> 
> Me wrote:
> 
> <snip>
> 
> > Using the code:
> > }}}
<eucode>
> > function log2 (atom x)
> >    return log(x)/log(2)
> > end function
> >  
> > for i = 0 to 32 do
> >    printf(1, "%d: %0.16g\n", i & log2( power( 2, i ) ))
> > end for
> > </eucode>
{{{

> > with the EXW.EXE interpreter 3.0.2, I can't manage to get imprecise results
> > anymore, neither on my old system nor on my new system.  *LOL*
> 
> <snip>
> 
> I think know I've found the explanation.
> Matt, when I had tested my log2() function, I probably had used a different
> way than you to look for imprecise results. Please test this:

<snip>

> These are the two cases that I treated specially in my proposal for
> "math.e".
> 
> So it seems that for i = 29 and for i = 31, the results of log2() are
> not equal according to the != operator, but they are (or only look)
> equal according to printf() ...

OK, I see the difference now.  Using the straight log/log method, there
is still a difference for 29 and 31.

OTOH, using the constant, the difference for 29 and 31 was in the next to 
least significant bit, making the differences twice as big.  And there 
were many more differences.  Definitely looks like rounding errors.

And by looking at what I got by parsing the constant, I can see that 
by letting the interpreter parse your constant, it loses accuracy.
Below, I've shown the bits of the double gotten in these different
ways:

1: log(2)
2: 0.6931471805599453
3: 0.6931471805599453e0 (using my parser)

1: 1111011110011100010111110111111101000010011101000110 01111111110 0 (-1)
2: 0111011110011100010111110111111101000010011101000110 01111111110 0 (-1)
3: 1111011110011100010111110111111101000010011101000110 01111111110 0 (-1)

This certainly calls into question the other constants, since they might
also be one bit off (probably ok for most applications, but still...)
For log(2), we could just do the calculation on assignment, but that 
doesn't help with the others.  The easiest solution is to use the
float64s, and call machine_func(46,...) on them (to avoid including
machine.e) and putting the human readable value in a comment:
LN2        = machine_func(47, {239,57,250,254,66,46,230,63}),   --
    0.6931471805599453e0
LN10       = machine_func(47, {21,85,181,187,177,107,2,64}),    --
    2.3025850929940456e0
E          = machine_func(47, {105,87,20,139,10,191,5,64}),     --
    2.7182818284590452e0
SQRT2      = machine_func(47, {204,59,127,102,158,160,246,63}), --
    1.4142135623730950e0
HALF_SQRT2 = machine_func(47, {204,59,127,102,158,160,230,63}), --
    0.7071067811865475e0
PI         = machine_func(47, {24,45,68,84,251,33,9,64}),       --
    3.1415926535897932e0
HALF_PI    = machine_func(47, {24,45,68,84,251,33,249,63}),     --
    1.5707963267948966e0
QUARTER_PI = machine_func(47, {24,45,68,84,251,33,233,63}),     --
    0.7853981633974483e0
TWO_PI     = machine_func(47, {24,45,68,84,251,33,25,64})       --
    6.2831853071795864e0


Using the constant for LN2 (as long as it's the *right* one) is probably
faster (I think that's a reasonable assumption), we should probably go
with your original function, but without the special cases.

For a new proposal, I know that we've covered the most common cases, but
how about a logn (or logx?) function for the general case:
global function logn( object x, atom base )


Matt

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu