GithubHelp home page GithubHelp logo

neslib / neslib.multiprecision Goto Github PK

View Code? Open in Web Editor NEW
33.0 7.0 6.0 1.93 MB

High-Precision Floating-Point Types for Delphi

License: Other

Batchfile 0.62% Shell 0.35% C++ 35.10% C 9.87% Makefile 0.09% Pascal 53.97%
qd-library multiprecision neslib delphi math high-precision

neslib.multiprecision's Introduction

Neslib - Base library used by other Neslib projects

Neslib is a (still small) library of Delphi utilities that is shared across some other Neslib projects.

License

Neslib is licensed under the Simplified BSD License.

See License.txt for details.

neslib.multiprecision's People

Contributors

erikvanbilsen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

neslib.multiprecision's Issues

Incorrect conversion from strings with 'E0' suffix

As reported by @Andreas113:

Erik,
I just noticed something that may help you find the error:
It concerns both Delphi 10.3. and Delphi 10.3. XE5.

When assigning the values:

X_Dd:= '1E0';
X_Qd:= '1E0';
Y_Dd:= '3.5E0';
Y_Qd:= '3.5E0';

the program will crash. It is therefore probably due to your parser routine within Init.
Andreas

Incorrect conversion from strings with 'E+1' suffix

Hi Erik,
I'm sorry to tell you, but there are still errors in the parser routine:

Function: Division
Example:

Y/X:
----
X            = -3.5
Y            = -5.08888E+1
MPA_Float    = 14.53965714285714285714285714285714285714285714285714285714285714285714 --> Correct
QuadDouble   = 1.45396571428571428571428571428571428571428571428571428571428571 --> WRONG! 
DoubleDouble = 1.453965714285714 --> WRONG!

The Exponent E+1 is not parsed correctly.

Andreas

Handling of integers

Great library, thanks for making it available for Delphi!

I was wondering how integers are handled. Extended/float80 can represent 64 bit integers without rounding, which makes it and ideal type to hold floats as well as integers.

Can DoubleDouble do this as well? Are integers guaranteed to be preserved if the operations don't involve fractions?
Is there a possibility to do precise division by an integer and truncating the fractional part?

Incorrect string parsing of QuadDouble

Hi Erik,
have just discovered a small malfunction in the parser routine of QuadDouble.

Here is an example:

Procedure Print(Name: String; Value: QuadDouble);
VAR
  S: String;
Begin
   S:= QuadDouble.ToString(Value, TMPFloatFormat.Fixed);
   WriteLn(Name + ' = ', S);
   WriteLn;
End;{Print}
{---------}

VAR
  ZQd: QuadDouble;
  St : String;
. . . 
St:= '12345.678901234567890123456789012345678901234567890123456789012345678901';
ZQd:= St;
Print('ZQd: Only the first 33 figures are correct: ', ZQd);

// ---> Result:
ZQd: Only the first 33 figures are correct:  = 12345.67890123456789012345678901235113471715242452040893925930542385

--> 12345.67890123456789012345678901235113471715242452040893925930542385

Could you please have a look at it if you have time?
Thank you!

Regards,
Andreas

QuadDouble not working with Delphi XE5

As reported by @Andreas113:

I have used Delphi XE5 for the tests because I have not yet got my tested MPA float library working with Delphi 10.3 and there is no way to control the results. However, I have a simplified version of the tests without this MPA float library with Delphi 10.3.

Also, how are you able to use the code with XE5?

I call this routine at the beginning of the program to get the correct settings:

Procedure ConfiguraRegiaoBR;
// DecimalSeparator in SysUtils and System.SysUtils - Stack Overflow
// By Rodrigo Garcia
Var
  WFormatoBR: TFormatSettings;

Begin
  WFormatoBR:= TFormatSettings.Create;
   
  WFormatoBR.DecimalSeparator := '.';  // ',';
  WFormatoBR.ThousandSeparator:= ',';  // '.';
  WFormatoBR.CurrencyDecimals := 2;
  WFormatoBR.DateSeparator    := '/';
  WFormatoBR.ShortDateFormat  := 'dd/mm/yyyy';
  WFormatoBR.LongDateFormat   := 'dd/mm/yyyy';
  WFormatoBR.TimeSeparator    := ':';
  WFormatoBR.TimeAMString     := 'AM';
  WFormatoBR.TimePMString     := 'PM';
  WFormatoBR.ShortTimeFormat  := 'hh:nn';
  WFormatoBR.LongTimeFormat   := 'hh:nn:ss';
  WFormatoBR.CurrencyString   := 'R$';

  System.SysUtils.FormatSettings:= WFormatoBR;
End;{Procedure ConfiguraRegiaoBR}

The DoubleDouble routines, so far I have tested, work with Delphi XE5, but not the QuadDouble's. I was able to locate the position in the debugger where the malfunction occurs.
The difference is here:

procedure QuadDouble.Init(const S: String; const FormatSettings: TFormatSettings);
. . .
    if (C >= '0') and (C <= '9') then
    begin
      D := Ord(C) - Ord('0'); 
      R := (R * 10) + D;       // Line number: ca. 4017
      Inc(ND);
    end
    else
    begin
. . .

In the multiplication routine _qd_mul_qd_d(..) is the divergence:

D := Ord(C) - Ord('0'); 
// for example: If X_Qd:= '0.4'; --> S = '0.4';
// D = 0
// R = (0,0,0,0)

R := (R * 10) + D;

10.3: --> R = (0,0,0,0)
XE5: --> R = (-NAN, -NAN, -NAN, -NAN)
The error was caused in line: ca. 4195:

class operator QuadDouble.Multiply(const A: QuadDouble; const B: Double): QuadDouble;
begin
  _qd_mul_qd_d(A, @B, Result); // Line: ca. 4195
end;

"Guilty" is therefore _qd_mul_qd_d(A, @b, Result);

The values of parameters A and B are identical with both Delphi versions.
Can it be that a

QuadDouble.X: array [0..3] of Double;

is aligned differently in memory with Delphi XE5 than with Delphi 10.3?

Would any compiler switches possibly be needed for both versions to get the same behaviour?
Unfortunately, I don't have any C knowledge and can't debug the C-source code.

I'm afraid Iโ€™m quite helpless.

Thanks,
Andreas

Support of Type Extended for Win32

Hi Erik,
if you are going to make changes to the code anyway, I have one more request for you.

For the Windows 32 target platform, it is relatively easy to include the use of the Extended type. I have already tried this and tested it several times: It works very well. This would make your library more compatible with the 10-byte "Extended world" instead of the less accurate 8-byte "Double world" of Windows.

For this you would only have to add the following additions to your library:

1):
function MultiPrecisionInit: UInt32;

Instead of:
. . .
SetPrecisionMode(pmDouble); // Original

New:

{IF Defined(WIN32)}
  SetPrecisionMode(pmExtended);
{$ELSE}
  SetPrecisionMode(pmDouble);
{$EndIF}

This would be necessary anyway, because with SetPrecisionMode(pmExtended); in Win32 e.g. the routine FloatToStrF(..) no longer works correctly and cuts off trailing decimal places.

2): In Interface:

Type
  DoubleDouble = record
  public
. . .
New:

class operator Implicit(const Value: Extended): DoubleDouble; inline; static;
class operator Implicit(const Value: DoubleDouble): Extended; inline; static;

3): In Implementation:

New:

class operator DoubleDouble.Implicit(const Value: Extended): DoubleDouble;
VAR
  a, b: Double;

begin
  // QuickTwoSum algorithm:
  a:= Value;
  b:= Value - a;

  Result.X[0]:= a + b;
  Result.X[1]:= b - (Result.X[0] - a);
end;

class operator DoubleDouble.Implicit(const Value: DoubleDouble): Extended;
Begin
  Result:= Value.X[1] + Value.X[0];
End;

Thank you in advance!

Regards,
Andreas

Problems with numerical overflows/underflows in some functions

Hi Erik,
I have run numerous numerical tests over the past few days. I did not encounter any new parsing errors but I observed some incorrect results with overflow and underflow of input values in some mathematical functions like follows:

Function: hyperbolic cosine Cosh(..)
Example:

Cosh(Y*X):
----------
X            = -4987654.6211234567891011
Y            = -0.100000000000000009999995

MPA_Float    = 6.122507439387169799822007412143668689493139250589157593313679373744026E+216610 --> Exact!
QuadDouble   = NAN  --> WRONG! --> Correct for DoubleDouble range: +Inf
DoubleDouble = NAN  --> WRONG! --> Correct for QuadDouble   range: +Inf

Function: hyperbolic sine Sinh(..)
Example:

Sinh(Y*X):
----------
X            = -4987654.6211234567891011
Y            = -0.100000000000000009999995

MPA_Float    = 6.122507439387169799822007412143668689493139250589157593313679373744026E+216610 --> Exact!
QuadDouble   = NAN  --> WRONG! --> Correct for DoubleDouble range: +Inf
DoubleDouble = NAN  --> WRONG! --> Correct for QuadDouble   range: +Inf

Sinh(Y*X):
----------
X            = -4987654.6211234567891011
Y            = +0.100000000000000009999995

MPA_Float    = -6.122507439387169799822007412143668689493139250589157593313679373744026E+216610
QuadDouble   = NAN  --> WRONG! --> Correct for DoubleDouble range: -Inf
DoubleDouble = NAN  --> WRONG! --> Correct for QuadDouble   range: -Inf

I cannot judge which result the original C functions return: It would therefore be possible that there is an error there in the C-code, but also in the implementation of the +/- infinity values in Delphi is possible.

I will be testing further and reporting to you.

Kind regards,
Andreas

Tanh produces incorrect results

As reported by @Andreas113

Hi Erik,
In the meantime, I made several more numerical tests of the mathematical routines and I came across the following error:

Function: Hyperbolic tangent: Tanh(..)

Numerical Example:

Tanh(Y/X):

X = 3.42897556698888888812345
Y = +1.63128799224455996622337700123
MPA_Float = 0.442822429892976193018935445355621315339799605925608439366306296677512: Exact!
DoubleDouble = 0.4428224298929761930189354453556
QuadDouble = 0.44282242989297619301893544535562131533979960592560843936630630

Conclusion:
DobleDouble: -----> OK!
QuadDouble : -----> OK!

Tanh(Y/X):

X = -3.5
Y = 1.0E-1
MPA_Float = -0.028563656570828037865016530810004960582783350513412052472238074033367: Exact!
DoubleDouble = -0.2781854903257024404718000872415 -----> WRONG!
QuadDouble = -0.27818549032570244047180008724146610677969449455154405945034634 -----> WRONG!

Conclusion:
DobleDouble: -----> WRONG!
QuadDouble : -----> WRONG!
On Delphi XE5 still only DoubleDouble runs, on Delphi 10.3 DobleDouble and QuadDouble.
The wrong result comes out - with this number combination - with both Delphi versions!
Even my old calculator (HP 41 CX) can calculate this value to 10 digits correctly...
So, there seems to be something wrong with the C routine. Or is it possibly due to the data transfer from Delphi to C?

Iโ€™ will be keeping testing!

Regards,
Andreas

Let's keep improving the parser...

Hi Erik,
Sorry to pester and harass you again, but I suffer from the nasty disease called perfectionism. My motto and guiding principle in programming is as follows: Make the software intelligent, because the user is stupid anyway.
So: let's keep improving the parser, if you like...

Function: Division
Example:

Y/X:
----
X            =   1
Y            = - 0
MPA_Float    = 0 ---> Correct
QuadDouble   = NAN
DoubleDouble = NAN

Y/X:
----
X            =   1
Y            = -2
MPA_Float    = -2 ---> Correct
QuadDouble   = NAN
DoubleDouble = NAN

Y/X:
----
X            = + 1
Y            = -2
MPA_Float    = -2 ---> Correct
QuadDouble   = NAN
DoubleDouble = NAN

Y/X:
----
X            =   1
Y            = - 2
MPA_Float    = -2 ---> Correct
QuadDouble   = NAN
DoubleDouble = NAN

Y/X:
----
X            =   1
Y            = - 2
MPA_Float    = -2 ---> Correct
QuadDouble   = NAN
DoubleDouble = NAN

The input strings are not parsed correctly. But the above cases can be solved very easily by trimming the inputs.
A bit more complex, but solvable is the following case:


Y/X:
----
X            = 1E - 1
Y            = - 2
MPA_Float    = -20 ---> Correct
QuadDouble   = -2.00000000000000000000000000000000000000000000000000000000000000
DoubleDouble = -2.0000000000000000000000000000000

Thanks
Andreas

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.