github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/Math.pas (about)

     1  namespace go.math;
     2  
     3  uses
     4    go.builtin;
     5  
     6  type
     7    {$IF ECHOES}PlatformMath = System.Math;{$ENDIF}
     8    {$IF ISLAND}PlatformMath = RemObjects.Elements.System.Math;{$ENDIF}
     9  
    10  
    11  
    12  
    13  const
    14    MaxInt8   = 1 shl 7 - 1; public;
    15    MinInt8   = -1  shl  7; public;
    16    MaxInt16  = 1 shl 15 - 1; public;
    17    MinInt16  = -1  shl  15; public;
    18    //MaxInt32  = 1 shl 31 - 1; public;
    19    MaxInt32 = 2147483647; public;
    20    MinInt32  = -1  shl  31; public;
    21    MaxInt64  = 1 shl 63 - 1; public;
    22    MinInt64  = -1  shl  63; public;
    23    MaxUint8  = 1 shl 8 - 1; public;
    24    MaxUint16 = 1 shl 16 - 1; public;
    25    MaxUint32 = 1 shl  32 - 1; public;
    26    MaxUint64 = 1 shl 64 - 1; public;
    27  
    28  
    29  method Trunc(x: Double): Double; public;
    30  begin
    31    {$IFDEF ECHOES}
    32    exit System.Math.Truncate(x);
    33    {$ELSE}
    34    exit RemObjects.Elements.System.Math.Truncate(x);
    35    {$ENDIF}
    36  end;
    37  
    38  method NaN(): Double; public;
    39  begin
    40    exit Double.NaN;
    41  end;
    42  
    43  method IsInf(v: Double; sign: Integer): Boolean; public;
    44  begin
    45    if sign < 0 then
    46      exit Double.IsNegativeInfinity(v);
    47    if sign > 0 then
    48      exit Double.IsPositiveInfinity(v);
    49    exit Double.IsInfinity(v);
    50  end;
    51  
    52  method IsNaN(v: Double): Boolean; public;
    53  begin
    54    exit Double.IsNaN(v);
    55  end;
    56  
    57  method Abs(v: Double): Double; public;
    58  begin
    59    exit PlatformMath.Abs(v);
    60  end;
    61  
    62  method Sqrt(v: Double): Double; public; inline;
    63  begin
    64    exit PlatformMath.Sqrt(v);
    65  end;
    66  
    67  
    68  method Inf(sign: Integer): Double; public;unsafe;
    69  begin
    70    if sign < 0 then
    71      exit Double.NegativeInfinity;
    72    exit Double.PositiveInfinity
    73  end;
    74  
    75  method Float32bits(f: Single): uint32; public;unsafe;
    76  begin
    77    ^Single(@result)^ := f;
    78  end;
    79  
    80  method Float32frombits(b: uint32): Single; public; unsafe;
    81  begin
    82    ^uint32(@Result)^ := b;
    83  end;
    84  
    85  method Float64bits(f: Double): uint64; public;unsafe;
    86  begin
    87    ^Double(@result)^ := f;
    88  end;
    89  
    90  method Float64frombits(b: uint64): Double; public; unsafe;
    91  begin
    92    ^uint64(@Result)^ := b;
    93  end;
    94  
    95  method Log(x: Double): Double; public;
    96  begin
    97    exit PlatformMath.Log(x);
    98  end;
    99  
   100  method Exp(x: Double): Double; public;
   101  begin
   102    exit PlatformMath.Exp(x);
   103  end;
   104  
   105  method Floor(x: Double): Double; public;
   106  begin
   107    exit PlatformMath.Floor(x);
   108  end;
   109  
   110  method Ceil(x: Double): Double; public;
   111  begin
   112    exit PlatformMath.Ceiling(x);
   113  end;
   114  
   115  method Ldexp(frac: Double; aexp: Integer): Double; public;
   116  begin
   117    exit PlatformMath.Pow(2, aexp) * frac;
   118  end;
   119  
   120  method Frexp(value: Double): tuple of (Double, Integer); public;
   121  begin
   122    {$IF ISLAND}
   123    var bits: int64 := Convert.ToInt64(value);
   124    {$ELSEIF ECHOES}
   125    var bits: int64 := BitConverter.DoubleToInt64Bits(value);
   126    {$ENDIF}
   127    var realMant: Double := 1.0;
   128    var exponent: Integer;
   129    var resmmantissa: Double;
   130  
   131    if Double.IsNaN(value) or
   132    (value + value = value) or
   133    Double.IsInfinity(value) then begin
   134      exponent := 0;
   135      resmmantissa := value;
   136    end   else begin
   137      var neg := bits < 0;
   138      exponent := ((bits shr 52) and $7ff);
   139      var mantissa := bits and $fffffffffffff;
   140  
   141      if(exponent = 0) then begin
   142        inc(exponent);
   143      end
   144      else begin
   145        mantissa := mantissa or (int64(1) shl 52);
   146      end;
   147  
   148        // bias the exponent - actually biased by 1023.
   149        // we are treating the mantissa as m.0 instead of 0.m
   150        //  so subtract another 52.
   151      exponent := exponent - 1075;
   152      realMant := mantissa;
   153  
   154        // normalize
   155      while(realMant > 1.0)  do begin
   156        mantissa := mantissa shr 11;
   157        realMant := realMant / 2.0;
   158        inc(exponent);
   159      end;
   160  
   161      if(neg) then begin
   162        realMant := realMant * -1;
   163      end;
   164  
   165      resmmantissa := realMant;
   166    end;
   167    exit (resmmantissa, exponent);
   168  end;
   169  
   170  method Log2(d: Double): Double;
   171  begin
   172    {$IF ISLAND}
   173    exit PlatformMath.Log2(d);
   174    {$ELSEIF ECHOES}
   175    exit PlatformMath.Log(d, 2);
   176    {$ENDIF}
   177  end;
   178  
   179  method Signbit(d: Double): Boolean;
   180  begin
   181    exit d < 0;
   182  end;
   183  
   184  //
   185  //
   186  //
   187  
   188  method Asin(x: float64): float64; public; inline;
   189  begin
   190    result := PlatformMath.Asin(x);
   191  end;
   192  
   193  method Asinh(x: float64): float64; public; inline;
   194  begin
   195    result := PlatformMath.Log(x + PlatformMath.Sqrt(x * x + 1)) // via https://stackoverflow.com/questions/2840798/c-sharp-math-class-question/2840824
   196  end;
   197  
   198  method Atan(x: float64): float64; public; inline;
   199  begin
   200    result := PlatformMath.Atan(x);
   201  end;
   202  
   203  method Atan2(y, x: float64): float64; public; // via https://en.wikipedia.org/wiki/Atan2
   204  begin
   205    if (x > 0) or (y ≠ 0) then begin
   206      result := 2 * Atan( y / (Sqrt(x*x + y*y) + x));
   207    end
   208    else if (x < 0) and (y = 0) then begin
   209      result := PlatformMath.PI;
   210    end
   211    else begin
   212      result := Double.NaN;
   213    end;
   214  end;
   215  
   216  method Copysign(x, y: float64): float64; public;
   217  begin
   218    result := if y > 0 then PlatformMath.Abs(x) else -PlatformMath.Abs(x);
   219  end;
   220  
   221  method Cos(x: float64): float64; public; inline;
   222  begin
   223    result := PlatformMath.Cos(x);
   224  end;
   225  
   226  method Cosh(x: float64): float64; public; inline;
   227  begin
   228    result := PlatformMath.Cosh(x);
   229  end;
   230  
   231  method Hypot(p, q: float64): float64; public; inline;
   232  begin
   233    result := PlatformMath.Sqrt(p * p + q * q);
   234  end;
   235  
   236  method Pow(x, y: float64): float64; public; inline;
   237  begin
   238    result := x ** y;
   239  end;
   240  
   241  method Pow10(n: int): float64; public; inline;
   242  begin
   243    result := 10 ** n;
   244  end;
   245  
   246  method Sin(x: float64): float64; public; inline;
   247  begin
   248    result := PlatformMath.Sin(x);
   249  end;
   250  
   251  method Sincos(x: float64): tuple of (sin: float64, cos: float64); public; inline;
   252  begin
   253    result := (Sin(x), Cos(x));
   254  end;
   255  
   256  method Sinh(x: float64): float64; public; inline;
   257  begin
   258    result := PlatformMath.Sinh(x);
   259  end;
   260  
   261  end.