eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'LargeFloat':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: LargeFloat


Inheritance:

   Object
   |
   +--Magnitude
      |
      +--ArithmeticValue
         |
         +--Number
            |
            +--LimitedPrecisionReal
               |
               +--LargeFloat

Package:
stx:libbasic2
Category:
Magnitude-Numbers
Version:
rev: 1.55 date: 2023/12/04 15:29:03
user: cg
file: LargeFloat.st directory: libbasic2
module: stx stc-classLibrary: libbasic2

Description:


Attention:
    Experimental & Unfinished Code.
    The implementation is neither complete nor tuned for performance - still being developed.

This class provides arbitrary precision floats.

I store floating point numbers in base 2 with some arbitrary precision (arbitrary number of bits).
I do inexact arithmetic like Float.
But I am very slow due to emulated (Large) Integer arithmetic... (compared to IEEE 754 hardwired)

Unlike Float, mantissa is not normalized to the form 1.mmmmmm
It is just stored as an integer.
The sign is stored in the mantissa.
biasedExponent is the power of two that multiplies the mantissa to form the number.
There is no limitation of exponent (overflow or underflow),
unless you succeed in exhausting the VM memory...

Like Float, my arithmetic operations are inexact.
They will round to nearest precision LargeFloat.

If two different precisions are used in arithmetic,
the result is expressed in the higher precision.
If the number is exact (i.e. was constructed from an integer),
I store 0 as precision.

Default operating mode is rounding, but might be one of the other possibility
(truncate floor ceiling).

Notice: the internals are completely non-IEEE;
although, I simulate an IEEE float when asked for exponent, mantissa, ebias, etc.
so some common bit-shuffling agorithms should work with me as well.

Instance Variables:
        mantissa        <Integer>       the bits of mantissa including sign
        exponent        <Integer>       the times two power to multiply the mantissa (floating binary scale)
        precision       <Magnitude>     number of bits to be stored in mantissa when I am normalized

copyright

COPYRIGHT (c) 2003 by eXept Software AG All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

class initialization
o  initialize
LargeFloat initialize

coercing & converting
o  coerce: aNumber
convert the argument aNumber into an instance of the receiver (class) and return it.

o  generality
return the generality value - see ArithmeticValue>>retry:coercing:

constants
o  NaN
LargeFloat NaN
(0.0 uncheckedDivide:0.0)

o  e
return the constant e as LargeFloat with at least 130 decimal digits precision

Usage example(s):

E := nil
     LargeFloat e

o  halfPi
return the constant pi/2 as quad precision double.
(returns approx. 200 bits of precision)

Usage example(s):

     QuadFloat halfPi printfPrintString:'%.60f'
        '1.570796326794896619231321691639751442098584699687552910487472'
     LargeFloat halfPi printfPrintString:'%.60f'
        '1.570796326794896619231321691639751442098584699687552910487472'
     Wolfram says:
        '1.5707963267948966192313216916397514420985846996875529104874722961539082031431044993140174126710585339910740432566411533235469223047752911158626797040642405587251420513509692605527798223114744774651909822144054878329667230642378241168933915826356009545728243'

     (QDouble readFrom:'1.5707963267948966192313216916397514420985846996875529104874722961539082031431044993140174126710585339910740432566411533235469223047752911158626797040642405587251420513509692605527798223114744774651909822144054878329667230642378241168933915826356009545728243')
        printfPrintString:'%.60f'

o  infinity
LargeFloat infinity
(1.0 uncheckedDivide:0.0)

o  ln10
return the ln(10) as largeFloat with at least 130 decimal digits precision

Usage example(s):

Ln10 := nil
     LargeFloat ln10

o  ln2
return the ln(2) as largeFloat with at least 130 decimal digits precision

Usage example(s):

Ln2 := nil
     LargeFloat ln2

o  negativeInfinity
LargeFloat negativeInfinity
(-1.0 uncheckedDivide:0.0)

o  one
return a one with the default precision

Usage example(s):

     LargeFloat one

o  phi
return the constant phi as LargeFloat with at least 130 decimal digits precision

Usage example(s):

Phi := nil
     LargeFloat phi

o  pi
return the constant pi as LargeFloat with at least 130 decimal digits precision

Usage example(s):

     LargeFloat pi
     (1 asLargeFloatPrecision:500) exp

o  sqrt2
return the sqrt(2) as largeFloat with at least 130 decimal digits precision

Usage example(s):

Sqrt2 := nil
     LargeFloat sqrt2

o  sqrt3
return the sqrt(3) as largeFloat with at least 130 decimal digits precision

Usage example(s):

     LargeFloat sqrt3

o  unity
return the neutral element for multiplication (1) as LargeFloat

Usage example(s):

     LargeFloat unity

o  zero
LargeFloat zero

instance creation
o  fromFraction: aFraction precision: n
return a largeFloat with value taken from aFraction

Usage example(s):

     (1/2) asLargeFloat                             -> 0.500000000000
     (1/3) asLargeFloat                             -> 0.333333333333
     (1/3333) asLargeFloat                          -> 0.000300030003
     (1/3333) asLargeFloat * 3333                   -> 1.000000000000
     LargeFloat fromFraction:(1/3) precision:100    -> 0.333333333333

     (LargeFloat fromFraction:(1/3) precision:100)
     + (LargeFloat fromFraction:(1/3) precision:100) -> 0.666666666667

     (LargeFloat fromFraction:(1/3) precision:500)
     + (LargeFloat fromFraction:(1/3) precision:500) -> 0.666666666667

o  fromInteger: anInteger
return a new largeFloat, given an integer value

Usage example(s):

     LargeFloat fromInteger:123456

     1 asLargeFloat
     2 asLargeFloat
     16 asLargeFloat
     1000 factorial asLargeFloat
     1000 factorial asLargeFloat asInteger = 1000 factorial

o  fromInteger: anInteger precision: n
LargeFloat fromInteger:123456 precision:6
1000 factorial asLargeFloat
1 asLargeFloat == 1 asLargeFloat
1.0 asLargeFloat == 1.0 asLargeFloat

o  fromLimitedPrecisionReal: aLimitedPrecisionReal
assumes that aLimitedPrecisionReal is a regular IEEE floating pnt number,
with a biased base2 exponent and hidden mantissa bit

Usage example(s):

     LargeFloat fromLimitedPrecisionReal:(Float fmin)                  2.2250738585072e-308       is: 2.2250738585072e-308
     LargeFloat fromLimitedPrecisionReal:(Float fminDenormalized)      4.9406564584125e-324       is: 4.94065645841247e-324
     LargeFloat fromLimitedPrecisionReal:(Float fmaxDenormalized)      2.2250738585072e-308       is: 2.2250738585072e-308

     LargeFloat fromLimitedPrecisionReal:(LongFloat fmin)              3.36210314311209351e-4932  is: 3.362103143112093506e-4932
     LargeFloat fromLimitedPrecisionReal:(LongFloat fminDenormalized)  3.95213325161012275e-4970  is: 3.645199531882474603e-4951
     LargeFloat fromLimitedPrecisionReal:(LongFloat fmaxDenormalized)  nan                        is: 3.362103143112093506e-4932

     LargeFloat fromLimitedPrecisionReal:(ShortFloat fmin)             1.1755e-38  is: 1.175494e-38
     LargeFloat fromLimitedPrecisionReal:(ShortFloat fminDenormalized) 1.4013e-45  is: 1.401298e-45
     LargeFloat fromLimitedPrecisionReal:(ShortFloat fmaxDenormalized) 1.1755e-38  is: 1.175494e-38

     1.0 asLargeFloat
     123456 asLargeFloat /7

     take a look at the precision...

     1.0 asShortFloat asLargeFloat precision
     1.0 asLongFloat asLargeFloat precision
     1.0 asQDouble asLargeFloat precision
     1 asLargeFloat
     (5/3) asLargeFloat
     (3/5) asLargeFloat
     (1/2) asLargeFloat

     2.0 asLargeFloat
     20000.0 asLargeFloat
     2e6 asLargeFloat
     1e300 asLargeFloat
     2e300 asLargeFloat

     0.5 asLargeFloat
     0.25 asLargeFloat
     (1.0/20000.0) asLargeFloat
     2e-6 asLargeFloat
     2e-300 asLargeFloat

     -1.0 asLargeFloat
     -0.5 asLargeFloat

     Float fmin asLargeFloat  
     Float fminDenormalized asLargeFloat  

     Float NaN asLargeFloat
     Float infinity asLargeFloat
     Float negativeInfinity asLargeFloat

    0.0 asLargeFloat  
    1.0 asLargeFloat   
    0.5 asLargeFloat   
    -1.0 asLargeFloat   
    1e20 asLargeFloat
    1e3 asLargeFloat
    1e-3 asLargeFloat
    -1e-3 asLargeFloat 
    Float fmin               2.2250738585072e-308 
    Float fmin asLargeFloat  2.2250738585072e-308  
    Float fminDenormalized               4.94065645841247e-324
    Float fminDenormalized asLargeFloat  4.9406564584125e-324
    LongFloat fmin                3.362103143112093506e-4932
    LongFloat fmin asLargeFloat   3.36210314311209351e-4932
    LongFloat fminDenormalized    3.645199531882474603e-4951
    LongFloat fminDenormalized asLargeFloat 3.6451995318824746e-4951 

o  integerMantissa: m unbiasedExponent: e precision: p

o  readFrom: aStringOrStream precision: precisionOrNil
if precisionOrNil is nil, the precision is computed from the number of
significant digits in the input
(adding a little bit, to ensure that we can later print it rounded to the
number of given digits; this approach is questionable,but affects only the
later printing and precision queries).
Otherwise,the given precision is assumed (give a non-nil precision, to prevent the
above)

Usage example(s):

     self readFrom:'12345' precision:50       12345.0
     self readFrom:'12345.678' precision:50   12345.678000000000
     self readFrom:'12345e3' precision:50     12345000.0
     self readFrom:'12345e1' precision:50     123450.0
     self readFrom:'12345e0' precision:50     12345.0
     self readFrom:'12345e-1' precision:50    1234.500000000000
     self readFrom:'1.234e4' precision:50     12340.0
     self phi

     self readFrom:'12345' precision:nil                    12345.0
     self readFrom:'12345678901234567890'  precision:nil    12345678901234567890.0
     self readFrom:'1234.5678901234567890' precision:nil    1234.567890123457
     self readFrom:'1234.5678901234567890' precision:200    1234.567890123457
     self readFrom:'1234.56789012345674' precision:nil      1234.567890123457
     self readFrom:'1234.56789012345674' precision:200      1234.567890123457
     self readFrom:'1234.56789012345679' precision:nil      1234.567890123457
     self readFrom:'1234.56789012345679' precision:200      1234.567890123457

queries
o  defaultPrecision
the default precision, if not specified explicitly

o  defaultPrintPrecision
the default number of digits when printing

o  defaultPrintfPrecision
the default number of digits when printing with printf's %f format.
Notice, that the C-language standard states that this should be 6;
however, we can adjust it on a per-class basis.

o  eBias
Answer the exponent's bias;
that is the offset of the zero exponent when stored

Usage example(s):

     1.0 numBitsInExponent 11
     1.0 eBias             1023
     1.0 emin              -1022
     1.0 emax              1023
     1.0 fmin              2.2250738585072E-308
     1.0 fmax              1.79769313486232E+308

     1.0 asLargeFloat numBitsInExponent - arbitrary; raises an error
     1.0 asLargeFloat eBias             - no such thing; raises an error
     1.0 asLargeFloat emin              - no such thing; raises an error
     1.0 asLargeFloat emax              - no such thing; raises an error
     1.0 asLargeFloat fmin              - no such thing; raises an error
     1.0 asLargeFloat fmax              - no such thing; raises an error

o  emax
The largest exponent value allowed by instances of this class.

o  emin
The smallest exponent value allowed by (normalized) instances of this class.
There is no minimum here

o  fmax
there is no maximum

o  fmaxDenormalized
there is no minimum

o  fmin
return the smallest normalized non-zero value that instances of me can hold.
There is no minimum here

Usage example(s):

     Float fmin      2.2250738585072e-308
     LargeFloat fmin 0.0

o  fminDenormalized
there is no minimum

o  isIEEEFormat

o  numBitsInMantissa
notice: this is an instance specific value; thus only a default value is returned here

o  numHiddenBits

o  radix
answer the radix of a LargeFloat's exponent


Instance protocol:

accessing
o  biasedExponent
anwser the biased exponent;
this is not what a standard floating point would return (adding its ebias to it),
(but I have an eBias of 0, also answer eBias with 0;
so my biasedExponent is the same as the unbiased)

o  exponent
anwser the floating point like exponent e of self,
normalized such that:
mantissa * (2 raisedTo: e)

Usage example(s):

     1.0 exponent                 1
     1.0 asLargeFloat exponent    0
     2.0 exponent
     2.0 asLargeFloat exponent
     3.0 exponent
     3.0 asLargeFloat exponent
     3.0 mantissa
     3.0 asLargeFloat mantissa
     3.0 mantissa * (2 raisedTo:3.0 exponent)
     3.0 asLargeFloat mantissa * (2 raisedTo:3.0 asLargeFloat exponent)
     4.0 exponent
     4.0 asLargeFloat exponent
     10.0 exponent
     10.0 asLargeFloat exponent
     0.5 exponent
     0.4 exponent
     0.25 exponent
     0.2 exponent
     0.00000011111 exponent
     0.0 exponent
     1e1000 exponent

     LargeFloat NaN exponent
     LargeFloat infinity exponent  

o  integerMantissa
return my internal mantissa;
that is an integer which needs to be shifted right,
precision number of bits to become a 'real' IEEE mantissa.
This returns an integer

o  mantissa
return what would be the normalized float's mantissa if I was an IEEE float.
This assumes that a float's mantissa is normalized to
0.5 .. 1.0 and the number's value is:
mantissa * 2^exp.
Returns a float of the receiver's type

o  nextToward: aNumber
answer the nearest floating point number to self with same precision than self,
toward the direction of aNumber argument.
If the nearest one falls on the other side of aNumber, than answer a Number

o  precision
answer the precision (the number of bits in the mantissa) of my elements (in bits).
If the receiver has never been given a precision, a default value (200) is returned.

o  precisionOrNil
answer the precision (the number of bits in the mantissa) of my elements (in bits).
If the receiver has not been given a precision, nil is returned

o  significand

arithmetic
o  * aNumber
return the product of the receiver and the argument.

o  + aNumber
return the sum of the receiver and the argument

Usage example(s):

     1.0 asLargeFloat + 20 asLargeFloat
     1.0 asLargeFloat + 20
     1.0 asLargeFloat + 20.0
     1.0 asLargeFloat + ( 2 / 5 )
     1.0 asLargeFloat + 0.4 asLargeFloat

     20 asLargeFloat + 1.0 asLargeFloat
     20 + 1.0 asLargeFloat
     20.0 + 1.0 asLargeFloat
     ( 2 / 5 ) + 1.0 asLargeFloat

o  - aNumber
Return the difference of the receiver and the argument.

o  / aNumber
return the quotient of the receiver and the argument, aNumber

o  // aNumber
return the integer quotient of dividing the receiver by aNumber with
truncation towards negative infinity.

Usage example(s):

     8 // 2    -> 4
     -8 // 2   -> -4
     9 // 2    -> 4
     -9 // 2   -> -5

     8 // -2   -> -4
     -8 // -2  -> 4
     9 // -2   -> -5
     -9 // -2  -> 4

     8 asFloat // 2    -> 4
     -8 asFloat // 2   -> -4
     9 asFloat // 2    -> 4
     -9 asFloat // 2   -> -5

     8 asFloat // -2   -> -4
     -8 asFloat // -2  -> 4
     9 asFloat // -2   -> -5
     -9 asFloat // -2  -> 4

     8 asLargeFloat // 2    -> 4
     -8 asLargeFloat // 2   -> -4
     9 asLargeFloat // 2    -> 4
     -9 asLargeFloat // 2   -> -5

     8 asLargeFloat // -2   -> -4
     -8 asLargeFloat // -2  -> 4
     9 asLargeFloat // -2   -> -5
     -9 asLargeFloat // -2  -> 4

o  naiveRaisedToInteger: n
Very naive algorithm: use full precision.
Use only for small n

o  negated
LargeFloat unity negated -1.0
LargeFloat zero negated 0.0
0.0 asLargeFloat negated 0.0

o  raisedToInteger: anInteger
return the receiver raised to an integer exp.
The caller must ensure that the arg is actually an integer

o  reciprocal
(comment from inherited method)
return the receiver's reciprocal

o  squared
return receiver * receiver.

o  timesTwoPower: n
Return the receiver multiplied by 2 raised to the power of the argument.
I.e. self * (2**n).

Usage example(s):

     1 timesTwoPower:10     -> 1024
     2**10                  -> 1024
     3 timesTwoPower:10     -> 3072
     3 * (2**10)            -> 3072
     1 timesTwoPower:20                     -> 1048576
     2**20                                  -> 1048576
     (1 timesTwoPower:10) timesTwoPower:10  -> 1048576
     1.0 timesTwoPower:10                   -> 1024.0
     1.0 timesTwoPower:20                   -> 1048576.0
     (1.0 asLargeFloatPrecision:100) timesTwoPower:10     -> 1024.0
     (1.0 asLargeFloatPrecision:100) timesTwoPower:20     -> 1048576.0
     LargeFloat infinity timesTwoPower:20   -> inf

coercing & converting
o  asFloat
Convert to a IEEE 754 double precision floating point.
Might return infinity if the receiver cannot be represented as a float

Usage example(s):

     100 factorial                           93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
     100 factorial asFloat                   9.33262154439442e+157
     100 factorial asLongFloat               9.332621544394415268E+157
     100 factorial asLargeFloat              93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000.0
     100 factorial asLargeFloat asFloat      9.33262154439442e+157

     200 factorial asLargeFloat asLongFloat  7.886578673647905467E+374

     1000 factorial asLargeFloat asFloat     inf
     1000 factorial asLargeFloat asLongFloat 4.023872600770937921E+2567

o  asFraction
Convert to a fraction.

o  asInteger
return an integer with same value - might truncate

Usage example(s):

     (self new exponent:0 mantissa:100) asInteger
     (self new exponent:1 mantissa:100) asInteger
     (self new exponent:-1 mantissa:100) asInteger

o  asLargeFloat
return a large float with same value - that's me

o  asLargeFloatPrecision: n
possibly change the precision

o  asLongFloat
Convert to a IEEE 754 extended precision floating point.
Might return infinity if the receiver cannot be represented as an extended float

Usage example(s):

     100 factorial asLargeFloat asShortFloat 9.33262124234219e+157
     100 factorial asLargeFloat asFloat      9.33262154439442E+157
     100 factorial asLargeFloat asLongFloat  9.332621544394415097e+157

     120 factorial asLargeFloat asShortFloat 9.33262124234219e+157
     100 factorial asLargeFloat asFloat      9.33262154439442E+157
     100 factorial asLargeFloat asLongFloat  9.332621544394415097e+157

     200 factorial asLargeFloat asShortFloat inf
     200 factorial asLargeFloat asFloat      inf
     200 factorial asLargeFloat asLongFloat  7.886578673647905467E+374
     1000 factorial asLargeFloat asLongFloat 4.023872600770937921E+2567

o  asShortFloat
Convert to a IEEE 754 single precision floating point.
Might return infinity if the receiver cannot be represented as a float32

Usage example(s):

     ShortFloat fmax                           3.402823e+38
     ShortFloat fmax asLargeFloat              340282346638528859811704183484516925440.0
     ShortFloat fmax asLargeFloat asShortFloat 3.402823e+38
     30 factorial asLargeFloat asShortFloat  2.652529e+32
     34 factorial asLargeFloat asShortFloat  2.952328e+38
     35 factorial asLargeFloat asShortFloat  inf
     50 factorial asLargeFloat asShortFloat  inf

     100 factorial asLargeFloat asShortFloat inf
     100 factorial asLargeFloat asFloat      9.33262154439442E+157
     100 factorial asLargeFloat asLongFloat  9.332621544394415097e+157

o  asTrueFraction
Answer a fraction or integer that EXACTLY represents self.

Usage example(s):

     0.3 asFloat asTrueFraction
     0.3 asShortFloat asTrueFraction
     0.3 asLongFloat asTrueFraction
     0.3 asLargeFloat asTrueFraction

     1 asLargeFloat asTrueFraction
     2 asLargeFloat asTrueFraction
     0.5 asLargeFloat asTrueFraction

     0.25 asLargeFloat asTrueFraction
     -0.25 asLargeFloat asTrueFraction
     0.125 asLargeFloat asTrueFraction
     -0.125 asLargeFloat asTrueFraction

     1.25 asLargeFloat asTrueFraction
     3e37 asLargeFloat asTrueFraction

     LargeFloat NaN asTrueFraction               -> error
     LargeFloat infinity asTrueFraction          -> error
     LargeFloat negativeInfinity asTrueFraction  -> error

o  coerce: aNumber
return the argument as a LargeFloat (with whichever precision is larger).
The larger precision is required, because we might be called to coerce a QuadFloat
with a less-precision LargeFloat (although LargeFloat generality is higher)

o  generality
return the generality value - see ArithmeticValue>>retry:coercing:

o  specialValueAs: floatClass
either zero, NaN or INF

comparing
o  < aNumber
return true, if the argument is greater

o  = aNumber
return true, if the argument is equal in value

Usage example(s):

     LargeFloat unity = LargeFloat zero
     LargeFloat unity = LargeFloat unity

     LargeFloat unity = nil
     LargeFloat unity ~= nil

o  hash
return a number for hashing; redefined, since floats compare
by numeric value (i.e. 3.0 = 3), therefore 3.0 hash must be the same
as 3 hash.

Usage example(s):

     LargeFloat unity hash
     LargeFloat zero hash

     3 hash
     3.0 hash
     3.1 hash
     3.14159 hash
     31.4159 hash
     3.141591 hash
     1.234567890123456 hash
     1.234567890123457 hash
     Set withAll:#(3 3.0 99 99.0 3.1415)

constants
o  one
return a one with my precision

o  pi
answer the value of pi rounded to my precision.
Note: use the Brent-Salamin Arithmetic Geometric Mean algorithm

Usage example(s):

    Number piDigits
    Time microsecondsToRun:[(1.0 asLargeFloatPrecision:2000) pi]
     (1.0 asLargeFloatPrecision:400) pi
        -> 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648564
     wolfram:
           3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648567

o  piDoublePrecision

o  zero
return a zero with my precision

copying-private
o  postCopy
(comment from inherited method)
this is for compatibility with ST-80 code, which uses postCopy for
cleanup after copying, while ST/X passes the original in postCopyFrom:
(see there)

double dispatching
o  differenceFromLargeFloat: aLargeFloat
INF or NaN

o  equalFromLargeFloat: aLargeFloat
assuming normalized numbers, they cannot be equal then

o  lessFromLargeFloat: aLargeFloat
return true if aLargeFloat < self

o  productFromLargeFloat: aLargeFloat
INF or NaN

o  quotientFromLargeFloat: aLargeFloat
Return the quotient of the argument, aLargeFloat and the receiver.
(i.e. divide aLargeFloat by self)
Sent when aLargeFloat does not know how to divide by the receiver.

o  sumFromLargeFloat: aLargeFloat
INF or NaN

initialization
o  setPrecisionTo: n

mathematical functions
o  agm: aNumber
return the arithmetic-geometric mean agm(a, b) of the receiver (a) and the argument, b.
See https://en.wikipedia.org/wiki/Arithmetic-geometric_mean
and http://www.wolframalpha.com/input/?i=agm(24,+6)

o  exp
Answer the exponential of the receiver.

Usage example(s):

Use following decomposition:
	    x exp = (2 ln * q + r) exp.
	    x exp = (2**q * r exp)

Usage example(s):

now compute r exp by power series expansion
    we compute (r/(2**p)) exp ** (2**p) in order to have faster convergence

o  integerLog10
1234.567 integerLog10 3
1234.567 asLargeFloat integerLog10 3

0.000001234 integerLog10 -5
0.000001234 asLargeFloat integerLog10 -5

(10.5 raisedTo:100) integerLog10 102
(10.5 asLargeFloat raisedTo:100) integerLog10 102

o  integerLog2
1234.567 integerLog2 10
1234.567 asLargeFloat integerLog2 10

0.000001234 integerLog2 -19
0.000001234 asLargeFloat integerLog2 -19

(10.5 raisedTo:100) integerLog2 339
(10.5 asLargeFloat raisedTo:100) integerLog2 339

o  ln
Answer the naperian (natural) logarithm of the receiver.

Usage example(s):

x ln = Pi  / (2 * (1 agm: 4/x) ).

Usage example(s):

If x not big enough, compute (x timesTwoPower: p) ln - (2 ln * p)

Usage example(s):

selfHighRes inPlaceReciprocal      "Use ln(1/x) => - ln(x)"

Usage example(s):

     0.00001 ln                 -11.5129254649702
     0.00001 asShortFloat ln    -11.51293
     0.00001 asLongFloat ln     -11.51292546497022834
     0.00001 asIEEEFloat ln     -11.51293
     0.00001 asLargeFloat ln    -11.512925464970

     1 ln                       0.0
     1 asLargeFloat ln          0.000000000000
     1 asLargeFloat log10       0.000000000000

o  log10
not always: we might loose precision here

Usage example(s):

     1234.567 log10                 3.09151466408626               
     1234.567 asLargeFloat log10    3.09151466408626

     (10.5 raisedTo:100) log10              102.118929906994 
     (10.5 asLargeFloat raisedTo:100) log10 102.118929906994 

o  log2
not always: we might loose precision here

Usage example(s):

     1234.567 log2                            10.2697894183844
     1234.567 asLargeFloat log2               10.2697894183844
     (LargeFloat fromString:'1234.567') log2  10.269789418384422758312631399945212567112793956158107187152

     (10.5 raisedTo:100) log2               339.231742277876
     (10.5 asLargeFloat raisedTo:100) log2  

o  sqrt
Answer the square root of the receiver.

Usage example(s):

"Initial guess for sqrt(1/n)"

Usage example(s):

"use iterations x(k+1) := x*( 1 +  (1-x*x*n)/2) to guess sqrt(1/n)"

Usage example(s):

     (144 asLargeFloatPrecision:200) sqrt
     (-144 asLargeFloatPrecision:200) sqrt

     ShortFloat decimalPrecision  7
     (2 asShortFloat) sqrt printfPrintString:'%8.7f'  
        -> 1.4142136

     Float decimalPrecision  15
     (2 asFloat) sqrt printfPrintString:'%16.15f'  
        -> 1.414213562373095

     LongFloat decimalPrecision  19
     (2 asLongFloat) sqrt printfPrintString:'%20.19Lf'  
        -> 1.4142135623730950488

     QuadFloat decimalPrecision  34
     (2 asQuadFloat) sqrt printfPrintString:'%34.33f'  
        -> 1.414213562373095048801688724209698

     QDouble decimalPrecision   61
     (2 asQDouble) sqrt printfPrintString:'%61.60f'        
        -> 1.414213562373095048801688724209698078569671875376948073176680

     OctaFloat decimalPrecision 71
     (2 asOctaFloat) sqrt printfPrintString:'%71.70f' 
        -> 1.4142135623730950488016887242096980785696718753769480731766797379907325

     (2 asLargeFloatPrecision:1000) sqrt printfPrintString:'%300.299f' 
        -> 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273501384623091229702492483605585073721264412149709993583141322266592750559275579995050115278206057147010955997160597027453459686201472851741864088919860955232923048430871432145083976260362799525140799

printing
o  absPrintExactlyOn: aStream base: base
Print my value on a stream in the given base.
Based upon the algorithm outlined in:
Robert G. Burger and R. Kent Dybvig
Printing Floating Point Numbers Quickly and Accurately
ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation
June 1996.
This version guarantees that the printed representation exactly represents my value
by using exact integer arithmetic.

o  asMinimalDecimalFraction
Answer the shortest decimal Fraction that will equal self when converted back asFloat.
A decimal Fraction has only powers of 2 and 5 as decnominator.
For example, 0.1 asLargeFloat asMinimalDecimalFraction = (1/10).

o  defaultPrintPrecision
(comment from inherited method)
the default number of digits when printing

o  printOn: aStream
a zero mantissa is impossible - except for zero and a few others

Usage example(s):

(self printfPrintString:e'%.{self defaultPrintPrecision}g') printOn:aStream.

Usage example(s):

     LargeFloat NaN printOn:Transcript

o  printOn: aStream base: base
(2 asLargeFloat raisedTo:1000) printOn:Transcript base:16
(2 asLargeFloat raisedTo:1000) printOn:Transcript base:10

o  storeOn: aStream
Modified (format): / 24-07-2019 / 09:55:11 / Claus Gittinger

private
o  cos: x
Evaluate the cosine of x by recursive cos(2x) formula and power series expansion.
Note that it is better to use this method with x <= pi/4.

o  digitCompare: b
both are positive or negative.
answer +1 if i am of greater magnitude, -1 if i am of smaller magnitude, 0 if equal magnitude

o  inPlaceAbs
destructive

o  inPlaceAdd: b
destructive

Usage example(s):

     |v|
     v := 0 asLargeFloat.
     v inPlaceAdd: 1 asLargeFloat.
     v inPlaceAdd: 1 asLargeFloat.
     v inPlaceAdd: 0.5 asLargeFloat.
     v    

Usage example(s):

     |v|
     v := 0.5 asLargeFloat.
     v inPlaceAdd: 0.4 asLargeFloat.
     v     

Usage example(s):

     |v|
     v := 0.5 asLargeFloat.
     v inPlaceAdd: 0.04 asLargeFloat.
     v     

Usage example(s):

     |v|
     v := 0.5 asLargeFloat.
     v inPlaceAdd: 0.004 asLargeFloat.
     v     

o  inPlaceAddNoRound: b
destructive

o  inPlaceCopy: b
copy another arbitrary precision float into self

o  inPlaceDivideBy: y
Reference: Accelerating Correctly Rounded Floating-Point Division when the Divisor
Is Known in Advance - Nicolas Brisebarre,
Jean-Michel Muller, Member, IEEE, and
Saurabh Kumar Raina -
http://perso.ens-lyon.fr/jean-michel.muller/DivIEEETC-aug04.pdf

o  inPlaceMultiplyBy: b
2.4 asLargeFloat inPlaceMultiplyBy:2.0 asLargeFloat
2.5 asLargeFloat inPlaceMultiplyBy:2.0 asLargeFloat

o  inPlaceMultiplyBy: b andAccumulate: c
only do rounding after the two operations.
This is the traditional muladd operation in aritmetic units

Usage example(s):

     2.4 asLargeFloat inPlaceMultiplyBy:2.0 asLargeFloat andAccumulate:10.0 asLargeFloat

o  inPlaceMultiplyNoRoundBy: b
2.4 asLargeFloat inPlaceMultiplyNoRoundBy:2.0

o  inPlaceNegated
destructive

o  inPlaceReciprocal
destructive

o  inPlaceSqrt
destructive

o  inPlaceSubtract: b
destructive

o  inPlaceSubtractNoRound: b
destructive

o  inPlaceTimesTwoPower: n
destructive

Usage example(s):

     1.0 timesTwoPower:2  -> 4.0
     1.0 timesTwoPower:3  -> 8.0
     1.0 timesTwoPower:4  -> 16.0
     1.0 asLargeFloat copy inPlaceTimesTwoPower:2    4.0
     1.0 asLargeFloat copy inPlaceTimesTwoPower:3    8.0
     1.0 asLargeFloat copy inPlaceTimesTwoPower:4   16.0
     1.0 asLargeFloat copy inPlaceTimesTwoPower:-1   0.5
     1.0 asLargeFloat copy inPlaceTimesTwoPower:-2   0.25

o  integerMantissa: mantissaArg biasedExponent: exponentArg precision: precisionArg
set instance variables.
Notice, that the float's value is
m * 2^e

As we store the mantissa as an (unnormalized) integer,
the biasedExponent will usually be negative,
and the mantissa will be a (huge) integer >= 1
(however, the above formula still holds)

o  integerMantissa: mantissaArg unbiasedExponent: exponentArg precision: precisionArg
set instance variables.
Notice, that the float's value is
m * 2^e

As we store the mantissa as an (unnormalized) integer,
the biasedExponent will usually be negative,
and the mantissa will be a (huge) integer >= 1
(however, the above formula still holds)

o  minPrecisionWith: otherPrecision

o  moduloNegPiToPi
answer a copy of the receiver modulo 2*pi, with doubled precision

Usage example(s):

     (LargeFloat pi * 2) moduloNegPiToPi
     (LargeFloat pi * 3) moduloNegPiToPi
     (LargeFloat pi * 19) moduloNegPiToPi
     (LargeFloat pi * 19.5) moduloNegPiToPi
     (LargeFloat pi * -10) moduloNegPiToPi

o  normalize
destructive

o  powerExpansionArCoshp1Precision: precBits
Evaluate arcosh(x+1)/sqrt(2*x) for the receiver x by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionArSinhPrecision: precBits
Evaluate the area hypebolic sine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionArTanhPrecision: precBits
Evaluate the area hyperbolic tangent of the receiver by power series expansion.
arTanh (x) = x (1 + x^2/3 + x^4/5 + ... ) for -1 < x < 1
The algorithm is interesting when the receiver is close to zero

o  powerExpansionArcSinPrecision: precBits
Evaluate the arc sine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionArcTanPrecision: precBits
Evaluate the arc tangent of the receiver by power series expansion.
arcTan (x) = x (1 - x^2/3 + x^4/5 - ... ) for -1 < x < 1
The algorithm is interesting when the receiver is close to zero

o  powerExpansionCosPrecision: precBits
Evaluate the cosine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

Usage example(s):

     1 cos                             0.54030230586814
     (1 asLargeFloatPrecision:300) cos 0.540302305868
     (1 asLargeFloatPrecision:300) powerExpansionCosPrecision:300 0.540302305868

o  powerExpansionCoshPrecision: precBits
Evaluate the hyperbolic cosine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

Usage example(s):

     1 cosh                            1.54308063481524
     1 asQuadFloat cosh                1.54308063 
     1 asQDouble cosh                  1.543080635 
     (1 asLargeFloatPrecision:300) cosh 1.543080634815 
     (1 asLargeFloatPrecision:300) powerExpansionCoshPrecision:300 1.543080634815 

o  powerExpansionLnPrecision: precBits
Evaluate the naperian logarithm of the receiver by power series expansion.
For quadratic convergence, use:
ln ((1+y)/(1-y)) = 2 y (1 + y^2/3 + y^4/5 + ... ) = 2 ar tanh( y )
(1+y)/(1-y) = self => y = (self-1)/(self+1)
This algorithm is interesting when the receiver is close to 1

Usage example(s):

     5 ln                                         1.6094379124341
     5 asLargeFloat powerExpansionLnPrecision:100 1.609437912434
     5 asLargeFloat powerExpansionLnPrecision:200
     5 asLargeFloat powerExpansionLnPrecision:400
     5 asLargeFloat powerExpansionLnPrecision:1000

o  powerExpansionSinCosPrecision: precBits
Evaluate the sine and cosine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionSinPrecision: precBits
Evaluate the sine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionSinhPrecision: precBits
Evaluate the hyperbolic sine of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionTanPrecision: precBits
Evaluate the tangent of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  powerExpansionTanhPrecision: precBits
Evaluate the hyperbolic tangent of the receiver by power series expansion.
The algorithm is interesting when the receiver is close to zero

o  precision: precisionArg
set instance variables.
Notice, that the float's value is m * 2^e

o  precisionInMantissa
this is equal to precision only if we are normalized.
If we are reduced (low bits being zero are removed), then it will be less.
If we haven't been rounded/truncated then it will be more

o  privateRoundToPrecision
destructive inplace round
apply algorithm round to nearest even used by IEEE arithmetic

o  privateRoundToPrecision: precision
destructive inplace round
apply algorithm round to nearest even used by IEEE arithmetic

o  privateTruncate
destructive remove trailing bits if they exceed our allocated number of bits

o  reduce
remove trailing zero bits from mantissa so that we can do arithmetic on smaller integer
(that will un-normalize self)

o  setMantissa: mantissaArg unbiasedExponent: exponentArg
set instance variables.
Notice, that the float's value is m * 2^e

o  shift: m by: d
shift mantissa m absolute value by some d bits, then restore sign

o  sin: x
Evaluate the sine of x by sin(5x) formula and power series expansion.

o  sincos: x
Evaluate the sine and cosine of x by recursive sin(2x) and cos(2x) formula and power series expansion.
Note that it is better to use this method with x <= pi/4.

queries
o  epsilon
return the maximum relative spacing of instances of mySelf
(i.e. the value-delta of the least significant bit)
according to ISO C standard;
Ada, C, C++ and Python language constants;
Mathematica, MATLAB and Octave; and various textbooks
see https://en.wikipedia.org/wiki/Machine_epsilon

Usage example(s):

^ LongFloat epsilon

o  exponentBits
simulatre an IEEE float's biased exponentbits

o  isExact
DO NOT USE; unfinished, and currenty not true
return true, if the number represented by the receiver is exact
or false, if it is an approximation.
If the receiver resulted from converting an integer, it will be exact.

Usage example(s):

     1 asLargeFloat isExact
     1.0 asLargeFloat isExact

o  mantissaBits
simulate an IEEE float's normalized mantissaBits
(my internal mantissa is not normalized, so clear the high bit
to make it look like a normalized IEEE mantissa with hidden bit)

o  nextFloat: nUlps
1 asLargeFloat nextFloat:1
(1 asLargeFloat nextFloat:1) - 1

(1 asLargeFloat nextFloat:10)
(1 asLargeFloat nextFloat:10) - 1

o  numBitsInExponent
I have as amny as needed;
but simulate having at least 20

o  numBitsInMantissa
answer the number of bits in the mantissa (the significant).
Here the number of bits in the mantissa is dynamic.

o  numHiddenBits

o  predecessor

o  successor

o  ulp
answer the distance between me and the next representable number

Usage example(s):

     (0.0 asLargeFloat nextFloat:1) - 0.0 asLargeFloat -> 1.24460305557e-60
     0.0 asLargeFloat ulp                              -> 1.24460305557e-60
     1.0 asLargeFloat ulp                              -> 2.22044604925e-16
     (1/100000) asLargeFloat ulp                       -> 2.36364252615e-130
     -1.0 asLargeFloat ulp                             -> 2.22044604925e-16
     (1.0 asLargeFloatPrecision:200) ulp               -> 1.24460305557e-60                  
     (0.0 asLargeFloatPrecision:400) ulp               -> 7.7451838297e-121
     (100000 asLargeFloatPrecision:400) ulp            -> 2.4784588255e-114

testing
o  isAnExactFloat

o  isFinite
return true, if the receiver is a finite float (not NaN and not +/-INF)

o  isInfinite
return true, if the receiver is an infinite float (+Inf or -Inf).
These are not created by ST/X float operations (they raise an exception);
however, inline C-code could produce them.

o  isNaN
return true, if the receiver is an invalid float (NaN - not a number).
These are usually not created by ST/X float operations (they raise an exception);
however, inline C-code or proceeded exceptions or reading from a stream
could produce them.

o  isZero
return true, if the receiver is zero

o  negative
return true if the receiver is negative

o  positive
return true if the receiver is greater or equal to zero (not negative).
0.0 and -0.0 are positive for now.

o  sign
return the sign of the receiver

Usage example(s):

     LargeFloat nan sign
     LargeFloat infinity sign
     LargeFloat infinity negated sign
     0 asLargeFloat sign
     1 asLargeFloat sign
     -1 asLargeFloat sign

trigonometric
o  arcCos
Evaluate the arc cosine of the receiver.

o  arcSin
Evaluate the arc sine of the receiver.

Usage example(s):

DomainError signal: 'cannot compute arcSin of a number greater than 1'

Usage example(s):

arcSin := (x = one)

Usage example(s):

self negative ifTrue: [arcSin inPlaceNegated].

Usage example(s):

^arcSin asLargeFloatPrecision: precision

o  arcTan
Evaluate the arc tangent of the receiver.

o  arcTan: denominator
Evaluate the four quadrant arc tangent of the argument denominator (x) and the receiver (y).

o  cos
Evaluate the cosine of the receiver

Usage example(s):

x := self cos: x

o  sin
Evaluate the sine of the receiver

Usage example(s):

x := self sin: x

o  sincos
Evaluate the sine and cosine of the receiver

o  tan
Evaluate the tangent of the receiver

Usage example(s):

| pi halfPi quarterPi x sincos neg tan |

Usage example(s):

tan := x powerExpansionTanPrecision: x precision

Usage example(s):

tan := sincos first

Usage example(s):

neg ifTrue: [tan inPlaceNegated].

Usage example(s):

^tan asLargeFloatPrecision: precision

trigonometric - hyperbolic
o  arCosh
Evaluate the hyperbolic area cosine of the receiver.

o  arSinh
Evaluate the hyperbolic area sine of the receiver.

o  arTanh
Evaluate the hyperbolic area tangent of the receiver.

o  cosh
return the hyperbolic cosine of the receiver (interpreted as radians)

o  sinh
@Commented by exept MBP at: 2021-10-06 09:40 Reason:

Usage example(s):

     (0 asLargeFloatPrecision:100) sinh  0.0
     (10 asLargeFloatPrecision:100) sinh 11013.232874703393377236524554848

o  tanh
(2 asLargeFloatPrecision:100) tanh 0.964027580076
(10 asLargeFloatPrecision:100) tanh 0.999999995878

truncation & rounding
o  truncated
answer the integer that is nearest to self in the interval between zero and self

Usage example(s):

     0.4 asLargeFloat truncated     => 0
     2.4 asLargeFloat truncated     => 2
     24.0 asLargeFloat truncated    => 24
     2e34 asLargeFloat truncated    => 20000000000000001217347628954550272   -- error alreay in 2e34
     (2 raisedTo:34) asLargeFloat truncated => 17179869184
     2e100 asLargeFloat truncated   => 20000000000000004203395606646656502775645430774928376064376333219774720047965581599435510382130626560
     2 * (10 asLargeFloat raisedTo:100) truncated   => inexact due to limited nr of bits (200)
     (2 * ((10 asLargeFloatPrecision:500) raisedTo:100)) truncated => 20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
     -0.4 asLargeFloat truncated   => 0
     -2.4 asLargeFloat truncated   => -2
     -24.0 asLargeFloat truncated
     -2e34 asLargeFloat truncated
     -2e100 asLargeFloat truncated


Examples:


pi should be (500 digits below):
     3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912

     '%500.498e' printf:{ (1.0 asLargeFloatPrecision:500) pi }


1000 factorial as a LargeFloat:
   (1 to:1000) inject:1 asLargeFloat into:[:p :m | p * m]

1000 factorial as an Integer:
   (1 to:1000) inject:1 into:[:p :m | p * m]

compute 20000.0 factorial:
   Time millisecondsToRun:[
      (1 to:20000) inject:1 asLargeFloat into:[:p :m | p * m]
   ] -> 210

compute 20000 factorial:
   Time millisecondsToRun:[
      (1 to:20000) inject:1 into:[:p :m | p * m]
   ] -> 160


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sun, 08 Sep 2024 02:54:51 GMT