Page 1 of 3

maths functions

Posted: Wed Sep 17, 2008 3:45 pm
by sospel
Hello !

Looking for a BASIC language for personal use, I downloaded several software (ex: PureBasic-Demo some days ago) and I make small programs-tests in touch with my needs.
To test their "answer" to the mathematical functions, I execute the 3 loops below, by adapting them to the specificities of every language (declarations of variables - value.d - , printings of the results StrD(...), etc...) :

value = 1.0
FOR i=1 TO 10
FOR j=1 TO 1000
FOR k=1 TO 1000
value = Tan(ATan(Pow(10.00,Log10(Sqr(value*value))))) + 1.0
NEXT k
NEXT j
NEXT i

( take in an old "Sky & Telescope" review)

Calculations in all langages are made in "DOUBLE".
I deliver you the main results :

1/in FORTRAN 95 : value = 10000001.000593 , error in % = 0.000010005 [Reference calculation]
2/in GFA-Basic (WinXP) : value = 10000001.001222 , error in % = 0.000010001 [remarkable for a "BASIC"!!]
3/in Visual-Basic6 : value = 9999818.448501 , error in % = 0.001815515 [acceptable]
4/in Emergence BASIC : value = 9999818.448501 , error in % = 0.001815515 [NB: idem than VB6].
5/in XBLite : value = 9999818.448501 , error in % = 0.001815515 [NB: idem than VB6].

To my great surprise, the calculation in PureBasic is FALSE :( :

a/ with "value.f" : value = 4095.73364
b/ with "value.d" : value = 1708221.50000

Is one of you can say myself if I made an error of programming or if it is an "intrinsic" fault in the functions of PureBASIC ?
Thank you in advance for any remark !
Cordially
SosPel

Posted: Wed Sep 17, 2008 4:01 pm
by Froggerprogger
All the math-functions (as Tan, ATan, Pow, Log10, Sqr) in PB do only work with single precision. There is atm no implementation for doubles.
[edit]According to the help which says e.g. Result.f = Tan(Angle.f) [/edit]

Posted: Wed Sep 17, 2008 8:10 pm
by Trond
Froggerprogger wrote:All the math-functions (as Tan, ATan, Pow, Log10, Sqr) in PB do only work with single precision. There is atm no implementation for doubles.
That is not true.

Code: Select all

; value.d = Tan(ATan(Pow(10.00,Log10(Sqr(value*value))))) + 1.0
Here:
Sqr() works with extended precision (full fpu usage, no extra truncation at all)
Log10() and Pow() works with single precision().
ATan() works with double precision.
Tan() works with extended precision.

Posted: Wed Sep 17, 2008 8:56 pm
by Helle
With Doubles:

Code: Select all

value.d = 1.0 
For i=1 To 10 
  For j=1 To 1000 
    For k=1 To 1000 
      T1.d=Log10(Sqr(value*value))
      T2.d=Pow(10.00, T1)
      value = Tan(ATan(T2)) + 1.0
    Next k 
  Next j 
Next i 

Debug value   ;10000001.001298055
;--------------------------------------
value.d = 1.0 
For i=1 To 10 
  For j=1 To 1000 
    For k=1 To 1000 
      T1.d=Log10(Sqr(value*value))
      T2.d=Pow(10.00, T1)
      T3.d=ATan(T2)
      value = Tan(T3) + 1.0
    Next k 
  Next j 
Next i 

Debug value   ;9999818.4040938206
Hmmm.... :o

Gruss
Helle

Posted: Wed Sep 17, 2008 9:25 pm
by blueznl
I think it's a bug, caused by wrong type conversion / enforcement.

Here's the culprit:

Code: Select all

value.d = 1.0
For i.l=1 To 10
  For j.l=1 To 1000
    For k.l=1 To 1000
      ;
      ; value = Tan(ATan(Pow(10.00,Log10(Sqr(value*value))))) + 1.0
      ;
      t5.d = value*value
      t4.d = Sqr(t5.d)
      
      ; t3.d = Log10(t4.d)
      ; t2.d = Pow(10.00,t3)
      
      t2.d = Pow(10.00,Log10(t4.d))
      
      t1.d = ATan(t2)
      t0.d = Tan(t1)
      value.d = t0 + 1.0
    Next k
  Next j
Next i
Debug value

Posted: Wed Sep 17, 2008 9:55 pm
by blueznl
And I've boiled it down to this:

Code: Select all

t3.d = Log10(2.00)
t2.d = Pow(10.00,t3)
x1.d = t2
Debug x1

t2.d = Pow(10.00,Log10(2.00))
x2.d = t2
Debug x2
It looks like Pow(...) is forcing Log10(...) to a lower precision. Which is, according to Fred's own rules ;-) not correct, type conversions were only allowed upwards, not downwards...

Who wants to have the honour to post this as a bug? :-)

Posted: Wed Sep 17, 2008 10:22 pm
by Psychophanta
Yes, look like a bug.
blueznl wrote:Who wants to have the honour to post this as a bug? :-)
You have been the first one to discover it, which means you should have such a honour. 8)

Posted: Wed Sep 17, 2008 10:48 pm
by blueznl
Well, actually Sospel should, but okay, in Sospel's name then :-)

Report is here:

http://www.purebasic.fr/english/viewtop ... 621#259621

Posted: Thu Sep 18, 2008 7:37 am
by Helle
Sospel´s Code tested with V4.30B1:
- 32-Bit: 1708221.5000000533
- 64-Bit: 9999818.1154463831 :D

Gruss
Helle

Posted: Thu Sep 18, 2008 10:09 am
by sospel
Hello !

Thank you for answers, which are enlighten a little my problem:

1/ FROGGERPROGGER is right: the PB manual indeed says " Result.f = Tan ( Angle.f) " and not Tan ( Angle.d) .

2/ HELLE shows that by making calculation piece by piece, we arrive at the good result: 10000001.001298055!
But this is not satisfactory, because he shows that the result depends on the "division" of the instruction.

3 / BLUEZNL:
" I think of it has bug ": I agree!
" Well, actually Sospel should, drank okay, in Sospel name then "
-> seen well : my name = "S.O.S for Programs Et (and) Languages"

My opinion on this problem : the necessity of cutting the calculations according to "risky" manipulations is very bad, and unworthy of a language as PureBasic. In my tries, it is the only language which has this abnormality. Furthermore, there is no function "EXP", opposite of LOG. It is indeed about a bug :( .

The only solution is that the designer of the language replaces these functions by " generic " functions for variables in INT, FLOAT or DOUBLE. As comparison, the other languages –VB6, XBLITE, EMERGENGE - have no these problems, and they are free. Nevertheless, they must also be doubtless written too with C++...

Cordially :D
SosPel

Posted: Thu Sep 18, 2008 10:28 am
by Psychophanta
This is very important, no doubt.
I agree with sospel in the part that PB should be at least as GFA-BASIC (win32) for accuracy for calculations with floats, doubles, or any.
Imho, this issue is enough important to move this forum thread to "General discussion" section, and to suggest to the developpers to not pass over this necessary matter.

Posted: Thu Sep 18, 2008 10:29 am
by blueznl
> the necessity of cutting the calculations according to "risky"
> manipulations is very bad

You never tried Forth :-)

Honestly, I don't think it's that bad. Splitting it to pieces is bad indeed, but there is a very clear logic behind the processing. Types are only converted upward when necessary. I had to wrap my mind around it a few times as well (and it is now so stretched you can poke holes through it :-)) but it makes sense from a speed perspective: no unnecessary up-conversions means MORE speed, and in the real world the limitations are limited. Simplest fix to turn everything to highest accuracy would be typecasting, which turns out to be very easy in PureBasic:

Code: Select all

float.d = 0
;
z.d = float + 1/3 + 1/3
Or (untested though :-))

Code: Select all

Procedure.d Float(float.d)
  ProcedureReturn float.d
EndProcedure
;
a.d = Float( 1/3 + 1/3 )


.

Unfortunately, the Pow( Log10( ) ) seems to be a bug. Eveything else can be put on the same line without any problems.

Posted: Thu Sep 18, 2008 5:34 pm
by Trond
sospel wrote:Hello !

Thank you for answers, which are enlighten a little my problem:

1/ FROGGERPROGGER is right: the PB manual indeed says " Result.f = Tan ( Angle.f) " and not Tan ( Angle.d) .
I simply looked at the asm output from PB 4.30b1, so what I wrote is how it was done in that code (of course it should not be this way, everything should be with double or extended precision).

Posted: Thu Sep 18, 2008 7:06 pm
by Road Runner
PowerBASIC answer = 10000001.0010595

Why use 3 nested loops when a single loop counting from 1 to 10,000,000 would do the same thing?

Your calculation of the % error is wrong.
The exact answer is 10000001
So the % error will be (value-10000001)/10000001 * 100
In your first case value = 10000001.0010595 so
% error = (10000001.0010595 - 10000001)/10000001 * 100 = 0.000000010595 % and not 0.000010005 %

Posted: Thu Sep 18, 2008 9:31 pm
by Psychophanta
Road Runner wrote: % error = (10000001.0010595 - 10000001)/10000001 * 100 = 0.000000010595 % and not 0.000010005 %
That is also wrong, coz the correct calculation should be:
(10000001.0010595-10000001.0)/10000000.0*100
because the number of iterations is 10000000 and not 10000001

BTW, anyone tested it with blitz?