⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmath.pas

📁 Delphi 的数学控件
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{ **********************************************************************
  *                            Unit FMATH.PAS                          *
  *                             Version 3.0d                           *
  *                      (c) J. Debord, August 2003                    *
  **********************************************************************
    This unit implements some mathematical functions in Delphi Pascal
  **********************************************************************
  Notes:

  1) The default real type is DOUBLE (8-byte real).
     Other types may be selected by defining the symbols:

       SINGLEREAL   (Single precision, 4 bytes)
       EXTENDEDREAL (Extended precision, 10 bytes)

  2) Error handling: The global variable MathError returns the error code
     from the last function evaluation. It must be checked immediately
     after a function call:

       Y := f(X);        (* f is one of the functions of the library *)
       if MathError = FN_OK then ...

     The possible error codes are:

     ---------------------------------------------
     Error code   Value  Significance
     ---------------------------------------------
     FN_OK          0    No error
     FN_DOMAIN     -1    Argument domain error
     FN_SING       -2    Positive singularity
     FN_OVERFLOW   -3    Overflow range error
     FN_UNDERFLOW  -4    Underflow range error
     FN_TLOSS      -5    Total loss of precision
     FN_PLOSS      -6    Partial loss of precision
     ---------------------------------------------

     When an error occurs, a default value is attributed to the function.

     The standard functions Exp and Ln have been redefined according to
     the above conventions as Expo and Log.

  **********************************************************************
  References:

  Complex functions: modified Pascal code from E. F. Glynn
                     (http://www.efg2.com/Lab/)

  Lambert's function: translated Fortran code from D. A. Barry et al.
                      (http://www.netlib.org/toms/743)

  Thanks to Volker Walter <vw@metrohm.ch>
  for improving the Power functions.
  ********************************************************************** }

unit fmath;

interface

{ ----------------------------------------------------------------------
  Floating point type (Default = Double)
  ---------------------------------------------------------------------- }

{$IFDEF SINGLEREAL}
  type Float = Single;
{$ELSE}
{$IFDEF EXTENDEDREAL}
  type Float = Extended;
{$ELSE}
  {$DEFINE DOUBLEREAL}
  type Float = Double;
{$ENDIF}
{$ENDIF}

{ ----------------------------------------------------------------------
  Mathematical constants
  ---------------------------------------------------------------------- }

const
  PI         = 3.14159265358979323846;  { Pi }
  LN2        = 0.69314718055994530942;  { Ln(2) }
  LN10       = 2.30258509299404568402;  { Ln(10) }
  LNPI       = 1.14472988584940017414;  { Ln(Pi) }
  INVLN2     = 1.44269504088896340736;  { 1/Ln(2) }
  INVLN10    = 0.43429448190325182765;  { 1/Ln(10) }
  TWOPI      = 6.28318530717958647693;  { 2*Pi }
  PIDIV2     = 1.57079632679489661923;  { Pi/2 }
  SQRTPI     = 1.77245385090551602730;  { Sqrt(Pi) }
  SQRT2PI    = 2.50662827463100050242;  { Sqrt(2*Pi) }
  INVSQRT2PI = 0.39894228040143267794;  { 1/Sqrt(2*Pi) }
  LNSQRT2PI  = 0.91893853320467274178;  { Ln(Sqrt(2*Pi)) }
  LN2PIDIV2  = 0.91893853320467274178;  { Ln(2*Pi)/2 }
  SQRT2      = 1.41421356237309504880;  { Sqrt(2) }
  SQRT2DIV2  = 0.70710678118654752440;  { Sqrt(2)/2 }
  GOLD       = 1.61803398874989484821;  { Golden Mean = (1 + Sqrt(5))/2 }
  CGOLD      = 0.38196601125010515179;  { 2 - GOLD }

{ ----------------------------------------------------------------------
  Machine-dependent constants
  ---------------------------------------------------------------------- }

{$IFDEF SINGLEREAL}
const
  MACHEP = 1.192093E-7;               { Floating point precision: 2^(-23) }
  MAXNUM = 3.402823E+38;              { Max. floating point number: 2^128 }
  MINNUM = 1.175495E-38;              { Min. floating point number: 2^(-126) }
  MAXLOG = 88.72283;                  { Max. argument for Exp = Ln(MAXNUM) }
  MINLOG = -87.33655;                 { Min. argument for Exp = Ln(MINNUM) }
  MAXFAC = 33;                        { Max. argument for Factorial }
  MAXGAM = 34.648;                    { Max. argument for Gamma }
  MAXLGM = 1.0383E+36;                { Max. argument for LnGamma }
{$ELSE}
{$IFDEF DOUBLEREAL}
const
  MACHEP = 2.220446049250313E-16;     { 2^(-52) }
  MAXNUM = 1.797693134862315E+308;    { 2^1024 }
  MINNUM = 2.225073858507202E-308;    { 2^(-1022) }
  MAXLOG = 709.7827128933840;
  MINLOG = -708.3964185322641;
  MAXFAC = 170;
  MAXGAM = 171.624376956302;
  MAXLGM = 2.556348E+305;
{$ELSE}
{$IFDEF EXTENDEDREAL}
const
  MACHEP = 1.08420217248550444E-19;   { 2^(-63) }
  MAXNUM = 1.18973149535723103E+4932; { 2^16384 }
  MINNUM = 3.36210314311209558E-4932; { 2^(-16382) }
  MAXLOG = 11356.5234062941439;
  MINLOG = - 11355.137111933024;
  MAXFAC = 1754;
  MAXGAM = 1755.455;
  MAXLGM = 1.04848146839019521E+4928;
{$ENDIF}
{$ENDIF}
{$ENDIF}

{ ----------------------------------------------------------------------
  Error codes for mathematical functions
  ---------------------------------------------------------------------- }

const
  FN_OK        =   0;  { No error }
  FN_DOMAIN    = - 1;  { Argument domain error }
  FN_SING      = - 2;  { Singularity }
  FN_OVERFLOW  = - 3;  { Overflow range error }
  FN_UNDERFLOW = - 4;  { Underflow range error }
  FN_TLOSS     = - 5;  { Total loss of precision }
  FN_PLOSS     = - 6;  { Partial loss of precision }

{ ----------------------------------------------------------------------
  Global variables
  ---------------------------------------------------------------------- }

var
  MathError    : Integer;  { Error code from the latest function evaluation }
  SgnZeroIsOne : Boolean;  { Indicates if Sgn(0) returns 1 (default) or 0 }

{ ----------------------------------------------------------------------
  Functional type
  ---------------------------------------------------------------------- }

type
  TFunc = function(X : Float) : Float;

{ ----------------------------------------------------------------------
  Complex numbers
  ---------------------------------------------------------------------- }

type
  Complex = record
    X, Y : Float;
  end;

{ ----------------------------------------------------------------------
  Complex constants
  ---------------------------------------------------------------------- }

const
  C_infinity : Complex = (X : MAXNUM; Y : 0.0);
  C_zero     : Complex = (X : 0.0;    Y : 0.0);
  C_one      : Complex = (X : 1.0;    Y : 0.0);
  C_i        : Complex = (X : 0.0;    Y : 1.0);
  C_pi       : Complex = (X : PI;     Y : 0.0);
  C_pi_div_2 : Complex = (X : PIDIV2; Y : 0.0);

{ ----------------------------------------------------------------------
  Min, max, sign and exchange
  ---------------------------------------------------------------------- }

function Min(X, Y : Integer) : Integer; overload;
function Max(X, Y : Integer) : Integer; overload;

function Min(X, Y : Float) : Float; overload;
function Max(X, Y : Float) : Float; overload;

function Sgn(X : Float)     : Integer; overload;  { Sign }
function Sgn(Z : Complex)   : Integer; overload;  { Complex sign }
function DSgn(A, B : Float) : Float;              { Sgn(B) * |A| }

procedure Swap(var X, Y : Float);   overload;   { Exchange 2 reals }
procedure Swap(var X, Y : Integer); overload;   { Exchange 2 integers }
procedure Swap(var W, Z : Complex); overload;   { Exchange 2 complexes }

{ ----------------------------------------------------------------------
  Complex numbers
  ---------------------------------------------------------------------- }

function Cmplx(X, Y : Float)     : Complex;  { X + i.Y }
function Polar(R, Theta : Float) : Complex;  { R.exp(i.Theta) }

function CAbs(Z : Complex) : Float;          { |Z| }
function CArg(Z : Complex) : Float;          { Arg(Z) }

function CNeg(A : Complex)     : Complex;    { -A }
function CConj(A : Complex)    : Complex;    { A* }
function CAdd(A, B : Complex)  : Complex;    { A + B }
function CSub(A, B : Complex)  : Complex;    { A - B }
function CMult(A, B : Complex) : Complex;    { A * B }
function CDiv(A, B : Complex)  : Complex;    { A / B }

function CSqrt(Z : Complex)                 : Complex;  { Sqrt(Z) }
function CRoot(Z : Complex; K, N : Integer) : Complex;  { Z^(1/N), K=0..N-1 }

function CSin(Z : Complex)    : Complex;     { Sin(Z) }
function CCos(Z : Complex)    : Complex;     { Cos(Z) }
function CArcTan(Z : Complex) : Complex;     { ArcTan(Z) }

{ ----------------------------------------------------------------------
  Logarithms, exponentials, and powers (real or complex argument)
  ---------------------------------------------------------------------- }

function Expo(X : Float)   : Float;   overload;  { Exponential }
function Expo(Z : Complex) : Complex; overload;

function Log(X : Float)   : Float;   overload;   { Natural log }
function Log(Z : Complex) : Complex; overload;

function Power(X : Float; N : Integer)   : Float;   overload; { X^N }
function Power(X, Y : Float)             : Float;   overload; { X^Y, X >= 0 }
function Power(Z : Complex; N : Integer) : Complex; overload; { Z^N }
function Power(Z : Complex; X : Float)   : Complex; overload; { Z^X }
function Power(A, B : Complex)           : Complex; overload; { A^B }

{ ----------------------------------------------------------------------
  Other logarithms and exponentials (real argument only)
  ---------------------------------------------------------------------- }

function Exp2(X : Float)    : Float;  { 2^X }
function Exp10(X : Float)   : Float;  { 10^X }
function Log2(X : Float)    : Float;  { Log, base 2 }
function Log10(X : Float)   : Float;  { Decimal log }
function LogA(X, A : Float) : Float;  { Log, base A }

{ ----------------------------------------------------------------------
  Lambert's function
  ---------------------------------------------------------------------- }
function LambertW(X : Float; UBranch, Offset : Boolean) : Float;
{ ----------------------------------------------------------------------
  Lambert's W function: Y = W(X) ==> X = Y * Exp(Y)    X >= -1/e
  ----------------------------------------------------------------------
  X       = Argument
  UBranch = TRUE  for computing the upper branch (X >= -1/e, W(X) >= -1)
            FALSE for computing the lower branch (-1/e <= X < 0, W(X) <= -1)
  Offset  = TRUE  for computing W(X - 1/e), X >= 0
            FALSE for computing W(X)
  ---------------------------------------------------------------------- }

{ ----------------------------------------------------------------------
  Trigonometric functions (real or complex argument)
  ---------------------------------------------------------------------- }

function Tan(X : Float)   : Float;   overload;     { Tangent }
function Tan(Z : Complex) : Complex; overload;

function ArcSin(X : Float)   : Float;   overload;  { Arc sinus }
function ArcSin(Z : Complex) : Complex; overload;

function ArcCos(X : Float)   : Float;   overload;  { Arc cosinus }
function ArcCos(Z : Complex) : Complex; overload;

{ ----------------------------------------------------------------------
  Other trigonometric functions (real argument only)
  ---------------------------------------------------------------------- }

function Pythag(X, Y : Float)    : Float;  { Sqrt(X^2 + Y^2) }
function ArcTan2(Y, X : Float)   : Float;  { Angle (Ox, OM) with M(X,Y) }
function FixAngle(Theta : Float) : Float;  { Set Theta in -Pi..Pi }

{ ----------------------------------------------------------------------
  Hyperbolic functions (real or complex argument)
  ---------------------------------------------------------------------- }

function Sinh(X : Float)   : Float;   overload;     { Hyperbolic sine }
function Sinh(Z : Complex) : Complex; overload;

function Cosh(X : Float)   : Float;   overload;     { Hyperbolic cosine }
function Cosh(Z : Complex) : Complex; overload;

function Tanh(X : Float)   : Float;   overload;     { Hyperbolic tangent }
function Tanh(Z : Complex) : Complex; overload;

function ArcSinh(X : Float)   : Float;   overload;  { Inverse hyperbolic sine }
function ArcSinh(Z : Complex) : Complex; overload;

function ArcCosh(X : Float)   : Float;   overload;  { Inverse hyperbolic cosine }
function ArcCosh(Z : Complex) : Complex; overload;

function ArcTanh(X : Float)   : Float;   overload;  { Inverse hyperbolic tangent }
function ArcTanh(Z : Complex) : Complex; overload;

{ ----------------------------------------------------------------------
  Other hyperbolic function (real argument only)
  ---------------------------------------------------------------------- }

procedure SinhCosh(X : Float; var SinhX, CoshX : Float);  { Sinh & Cosh }

{ ********************************************************************** }

implementation

{ ----------------------------------------------------------------------
  Error handling function
  ---------------------------------------------------------------------- }

  function DefaultVal(ErrCode : Integer; Default : Float) : Float;
  { Sets the global variable MathError and returns
    the default value according to the error code }
  begin
    MathError := ErrCode;
    DefaultVal := Default;
  end;

{ ----------------------------------------------------------------------
  Min, max, sign and exchange
  ---------------------------------------------------------------------- }

  function Min(X, Y : Integer) : Integer; overload;
  begin
    if X < Y then Min := X else Min := Y;
  end;

  function Max(X, Y : Integer) : Integer; overload;
  begin
    if X > Y then Max := X else Max := Y;
  end;

  function Min(X, Y : Float) : Float; overload;
    begin
    if X < Y then Min := X else Min := Y;
  end;

  function Max(X, Y : Float) : Float; overload;
  begin
    if X > Y then Max := X else Max := Y;
  end;

  function Sgn0(X : Float) : Integer;
  begin
    if X > 0.0 then
      Sgn0 := 1
    else if X = 0.0 then
      Sgn0 := 0
    else
      Sgn0 := - 1;
  end;

  function Sgn(X : Float) : Integer;
  begin
    if X > 0.0 then
      Sgn := 1
    else if X < 0.0 then
      Sgn := - 1
    else
      Sgn := Ord(SgnZeroIsOne);
  end;

  function Sgn(Z : Complex) : Integer; overload;
  begin
    if Z.X > 0.0 then
      Sgn := 1
    else if Z.X < 0.0 then
      Sgn := - 1
    else if Z.Y > 0.0 then
      Sgn := 1
    else if Z.Y < 0.0 then
      Sgn := - 1
    else
      Sgn := Ord(SgnZeroIsOne);
  end;

  function DSgn(A, B : Float) : Float;
  begin
    if B < 0.0 then DSgn := - Abs(A) else DSgn := Abs(A);
  end;

  procedure Swap(var X, Y : Integer); overload;
  var
    Temp : Integer;
  begin
    Temp := X;
    X := Y;
    Y := Temp;
  end;

  procedure Swap(var X, Y : Float); overload;
  var
    Temp : Float;
  begin
    Temp := X;
    X := Y;
    Y := Temp;
  end;

  procedure Swap(var W, Z : Complex); overload;
  var
    Temp : Complex;
  begin
    Temp := W;
    W := Z;
    Z := Temp;
  end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -