Announcement

Collapse
No announcement yet.

Double --> Extended

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Double --> Extended

    I’ve converted a FORTRAN program to PBCC5, a numerical analysis sort of program, that works when the floating point variables are declared Double.

    The program doesn’t work (not always in the same cases as before) when the variables are declared Extended. You would think, anyway I would, that if it worked with Double it would work even better, if slower, with Extended.

    Any ideas in general? If you want to see the code in particular see this webpage. You can change the type in the line
    Macro Precision = Double 'Single, Double, Extended
    to change the type of all the floating point variables at once.



    Politically incorrect signatures about immigration patriots are forbidden. Googling “immigration patriots” is forbidden. Thinking about Googling ... well, don’t even think about it.

  • #2
    Which one doesn't work?

    Comment


    • #3
      if slower, with Extended.
      The speed penalty is only noticeable if you have lots of EXTENDED variables. With just a handful, the speed difference is insignificant.

      It is possible to tell the FPU to limit precision of calculations when the full 80 bit precision isn't needed and that can speed up some calculations, but PB doesn't do that.

      PowerBASIC doesn't switch the FPU precision at all. It's set as EXTENDED for all calculations, so if you load a DOUBLE or a SINGLE, the FPU loads the number and converts it internally to EXTENDED, does all the calculations as EXTENDED, then converts the number back to the required precision when the result is stored in memory.


      The only significant time penalty you'll get is that smaller data types take less memory so less memory needs to be moved to do calculations on them.

      If you had an array of 1 million SINGLES then you needs to shift 4MB of data.
      If you used DOUBLES, that becomes 8MB of data.
      If you use EXTENDED you're hit with 2 speed penalties. Each EXTENDED variable take 10 bytes to store so you need to shift 10MB of data.
      Aditionally, SINGLES and DOUBLES are nicely aligned in memory, being 4 and 8 bytes, they fit evenly into 16 or 32 byte cache lines in the CPU.
      EXTENDED variables don't fit in neatly and every other EXTENDED variable you load is misaligned in memory and often needs 2 cache lines to be fetched instead of 1.

      It's quicker on some systems to store EXTENDED numbers padded out with 6 unused bytes so each takes 16 bytes with the unused 6 bytes being wasted. This allows all EXTENDED numbers to be aligned in memory and only 1 cache line is needed for each as they will never straddle 2 lines.

      Comment


      • #4
        I tried it with PBCC4 and PBCC6 and it works the same with both.

        The answer given is 1.64515079839734 for both DOUBLE and EXTENDED using both compilers.


        When set to use SINGLEs your code crashes because the limit on the error you have in FUNCTION eExp() is too small and is beyond the range of a SINGLE so the loop never ends.
        Last edited by Paul Dixon; 28 May 2018, 11:28 AM. Reason: Deleted an incorrect assumption.

        Comment


        • #5
          Deleted. never mind, I was having a brain f*rt.


          Comment


          • #6
            Hmmm.
            It might just be coincidence that e0.5 is almost the same as e0.5 but not quite!

            Comment


            • #7
              With both PBCC 5.04 and 6.04 and Precision set to DOUBLE, I get 1.64515079839734 in about one second.

              However, with Precision set to EXTENDED both 5.04 and 6.04 the program goes into an infinite loop that needs killing with Task Manager. Considering 1 Sec for DOUBLE, 10 minute wait for EXTENDED should have been enough.

              This just a report. No comment ATT. My OS is Windows Vista on this PC.

              Later (maybe ),


              Dale

              Comment


              • #8
                Is this the software equivalent of the Yanny/Laurel sound clip?
                The outcome depends on who runs the code.

                It works here with EXTENDED in all versions of the compiler that I've tried.

                Since I can't replicate the problem it's going to be difficult to track down.

                Comment


                • #9
                  It works here with EXTENDED in all versions of the compiler that I've tried.
                  Yeah, I saw that in post 4. That is why I made sure to say "... just a report"

                  Did I follow your comment about function eExp() right? Because -
                  .0000001 = 1.0*10^-7 is greater than 8.43*10^-37, and so is in range of a single. Thanx.
                  Dale

                  Comment


                  • #10
                    It's not that the resulting value can't be held in a SINGLE, it's that the 2 numbers being compared can't be calculated sufficiently accurately with SINGLEs to allow the loop to end.

                    The loop continues until LOOP UNTIL ABS(x - xlast) < .0000001

                    x and xlast are converging and have values in the region of 2.23
                    (x-xlast) is subtracting 2 ever closer values such as 2.2301 and 2.2302
                    As they converge, this gets close to 2.2300001 and 2.2300002 (the numbers are made up just to explain it more clearly but the magintudes are of the right order).

                    If you subtract those 2 numbers, the difference is less than 1 LSB in a SINGLE containing the number 2.23.
                    To do the subtraction properly you need at least 8 digits but a SINGLE only calculates to about 6 digits.

                    Comment


                    • #11
                      Given all the micro kernel patches for various OS and various CPUs surrounding the Spectre CPU exploits family, I am inclined to think this might be an unintended consequence of it. So naming OS and CPU along with the reports might help (in case my speculation is correct). DxDiag is a handy tool or that.

                      Windows 7, 64 bit Prof., Intel(R) Core(TM) i7-2640M CPU

                      - Double: result in an blink of an eye: 1.64515079839734
                      - Extended: same result as Dale, endless loop (hint: the compiler directive #Break On at least let's you close the running app with CTRL+BREAK)

                      Mark Hunter : you may want to use PB's TRACE and/or CALLSTK$ to determine where the endless loop happens.

                      Comment


                      • #12
                        Okay, I didn't follow.

                        After asking the question I tried SINGLE in PBCC 5 and 6.This also caused infinite loop. Took closer look a code.

                        In function function ExpReal() the DO/LOOP near the end has -

                        LOOP UNTIL z = 0

                        Never, ever, count on a floating point being equal to anything exactly.

                        Fixing that instance with -
                        Code:
                        do
                          ...
                            if z < .00001 or z > -.00001 then
                              exit do
                            end if
                        loop
                        ...
                        did not fix the problem. Not sure I'm interested enough to continue looking.

                        Mark, a suggestion.- replace other places where IF float = and UNTIL float equals.

                        Have fun guys,

                        Dale

                        Comment


                        • #13
                          Thank you all for looking into this.

                          My system is Windows 7, 32 bit. That corresponds to the row of results below.
                          Code:
                          CC4 & Double      CC4 & Extended     CC5 & Double     CC5 & Extended
                          -------------     ---------------    ------------     --------------
                          wrong answers     hangs              works fine       hangs
                          Paul,

                          e sub s really differs from e^s. If we replace the one line in PBMain with
                          Code:
                           Local s, e As Precision
                           e = Exp(1)              '2.71828...
                           Print s,"e sub s","e^s"
                           Print "-------------------------------"
                           For s = 0 To 2.75 Step .25
                            Print Format$(s,"0.00"), Format$(ExpReal(s, 1),"0.00000"), Format$(e^s,"0.00000")
                           Next
                          the result is
                          Code:
                          s        e sub s    e^s
                          ---------------------------
                          0.00     1.00000    1.00000
                          0.25     1.29320    1.28403
                          0.50     1.64515    1.64872
                          0.75     2.09688    2.11700
                          1.00     2.71828    2,71828
                          1.25     3.64443    3.49034
                          1.50     5.18179    4.48169
                          1.75     8.14071    5.75460
                          2.00    15.15426    7.38906
                          2.25    38.26080    9.48774
                          2.50   178.00137   12.18249
                          2.75  3431.35786   15.64263
                          I stopped it at 2.75 because at 3.00 it overflows in intermediate calculations – with Double precision anyway. Since 3 is a whole number we can compute it normally: e sub 3 = Exp(Exp(Exp(1))) = 3814279.10476.

                          Paul, Dale,

                          In general one should check for equality of two real numbers (floating point numbers) x and y as you say, Abs(x – y) < tolerance. But in this case the variable is set to exactly zero (by default of exiting a function without assigning a value) in the case I wanted to check for.
                          Politically incorrect signatures about immigration patriots are forbidden. Googling “immigration patriots” is forbidden. Thinking about Googling ... well, don’t even think about it.

                          Comment


                          • #14
                            might just be coincidence that e0.5 is almost the same as e0.5 but not quite!
                            More like SQR(e) , I would think.

                            Comment


                            • #15
                              Michael,

                              A number raised to 1/2 equals the square root of the number.
                              Code:
                              e^.5  *  e^.5  =  e^(.5+.5)  =  e^1  =  e
                              And Sqr(e) doesn't equal e^e^e^...e 1/2 times, as the program calculation shows.
                              Politically incorrect signatures about immigration patriots are forbidden. Googling “immigration patriots” is forbidden. Thinking about Googling ... well, don’t even think about it.

                              Comment


                              • #16
                                It looks like the program has an error in it.
                                It's the same line that caused the problem with SINGLEs
                                LOOP UNTIL ABS(x - xlast) < .0000001


                                For the enormous numbers being generated by the program (in the order of 1E77) the .0000001 is way smaller than the LSB of an EXTENDED precision number.
                                A rounding error of 1 LSB is 1E60 bigger.
                                It just happens that using DOUBLEs the result is exactly zero but using EXTENDEDs the result is 1 LSB away from zero so the test always fails and the loop never ends.

                                You should probably scale the value so it has some relation to the size of x and xlast.
                                Maybe this is better:
                                LOOP UNTIL ABS(x - xlast) < (x * .0000001)

                                Comment


                                • #17
                                  Paul,

                                  Thanks for looking into it. If the tolerance is .01 it still fails. I think the problem is using Newton’s method. The lack of absolute exactness in the slope of eLog – which is DeLog – may be the problem. If we change from Newton’s method to the bifurcation method:
                                  Code:
                                   Local x, x1, x2 As Precision
                                   x1 = 0             'bracket solution
                                   x2 = 10^20
                                   Do
                                    x = (x1 + x2) / 2
                                    If eLog(x) = y Or Abs(x1 - x2) < .0000001 Then Exit Do      
                                    If Sgn(eLog(x) - y) = Sgn(eLog(x2) - y) Then
                                     x2 = x
                                    Else
                                     x1 = x
                                    End If
                                   Loop               '28 loops vs 4 with Newton
                                   Function = x
                                  then it works with Precision = Extended. Of course it’s much slower (when Newton’s Method works). (About the equality check, it seems to work OK, using Abs etc. makes no difference. One or the other is necessary though, the second check by itself isn't sufficient, don't know why.)
                                  Last edited by Mark Hunter; 29 May 2018, 09:00 PM.
                                  Politically incorrect signatures about immigration patriots are forbidden. Googling “immigration patriots” is forbidden. Thinking about Googling ... well, don’t even think about it.

                                  Comment

                                  Working...
                                  X