(************************************************************************* AP library Copyright (c) 2003-2009 Sergey Bochkanov (ALGLIB project). >>> LICENSE >>> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (www.fsf.org); either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GNU General Public License is available at http://www.fsf.org/licensing/licenses >>> END OF LICENSE >>> *************************************************************************) unit u_Ap; interface uses Math, Sysutils; ///////////////////////////////////////////////////////////////////////// // constants ///////////////////////////////////////////////////////////////////////// const MachineEpsilon = 5E-16; MaxRealNumber = 1E300; MinRealNumber = 1E-300; ///////////////////////////////////////////////////////////////////////// // arrays ///////////////////////////////////////////////////////////////////////// type PDouble = ^Double; Complex = record X, Y: Double; end; TInteger1DArray = array of LongInt; TReal1DArray = array of Double; TComplex1DArray = array of Complex; TBoolean1DArray = array of Boolean; TInteger2DArray = array of array of LongInt; TReal2DArray = array of array of Double; TComplex2DArray = array of array of Complex; TBoolean2DArray = array of array of Boolean; RCommState = record Stage: LongInt; IA: TInteger1DArray; BA: TBoolean1DArray; RA: TReal1DArray; CA: TComplex1DArray; end; ///////////////////////////////////////////////////////////////////////// // Functions/procedures ///////////////////////////////////////////////////////////////////////// function AbsReal(X : Double):Double; function AbsInt (I : Integer):Integer; function RandomReal():Double; function RandomInteger(I : Integer):Integer; function Sign(X:Double):Integer; function AP_Sqr(X:Double):Double; function DynamicArrayCopy(const A: TInteger1DArray):TInteger1DArray;overload; function DynamicArrayCopy(const A: TReal1DArray):TReal1DArray;overload; function DynamicArrayCopy(const A: TComplex1DArray):TComplex1DArray;overload; function DynamicArrayCopy(const A: TBoolean1DArray):TBoolean1DArray;overload; function DynamicArrayCopy(const A: TInteger2DArray):TInteger2DArray;overload; function DynamicArrayCopy(const A: TReal2DArray):TReal2DArray;overload; function DynamicArrayCopy(const A: TComplex2DArray):TComplex2DArray;overload; function DynamicArrayCopy(const A: TBoolean2DArray):TBoolean2DArray;overload; function AbsComplex(const Z : Complex):Double; function Conj(const Z : Complex):Complex; function CSqr(const Z : Complex):Complex; function C_Complex(const X : Double):Complex; function C_Opposite(const Z : Complex):Complex; function C_Add(const Z1 : Complex; const Z2 : Complex):Complex; function C_Mul(const Z1 : Complex; const Z2 : Complex):Complex; function C_AddR(const Z1 : Complex; const R : Double):Complex; function C_MulR(const Z1 : Complex; const R : Double):Complex; function C_Sub(const Z1 : Complex; const Z2 : Complex):Complex; function C_SubR(const Z1 : Complex; const R : Double):Complex; function C_RSub(const R : Double; const Z1 : Complex):Complex; function C_Div(const Z1 : Complex; const Z2 : Complex):Complex; function C_DivR(const Z1 : Complex; const R : Double):Complex; function C_RDiv(const R : Double; const Z2 : Complex):Complex; function C_Equal(const Z1 : Complex; const Z2 : Complex):Boolean; function C_NotEqual(const Z1 : Complex; const Z2 : Complex):Boolean; function C_EqualR(const Z1 : Complex; const R : Double):Boolean; function C_NotEqualR(const Z1 : Complex; const R : Double):Boolean; ///////////////////////////////////////////////////////////////////////// // AP BLAS generic interface ///////////////////////////////////////////////////////////////////////// //procedure UseAPBLAS(Flag: Boolean); function APVDotProduct( V1: PDouble; I11, I12: Integer; V2: PDouble; I21, I22: Integer):Double; procedure APVMove( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; procedure APVMove( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Double);overload; procedure APVMoveNeg( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer); procedure APVAdd( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; procedure APVAdd( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Real);overload; procedure APVSub( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; procedure APVSub( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Real);overload; procedure APVMul( VOp: PDouble; I1, I2: Integer; S: Real); ///////////////////////////////////////////////////////////////////////// // IEEE-compliant functions, placed at the end, under 'non-optimization' // compiler switch ///////////////////////////////////////////////////////////////////////// function AP_Double(X:Double):Double; function AP_FP_Eq(X:Double; Y:Double):Boolean; function AP_FP_NEq(X:Double; Y:Double):Boolean; function AP_FP_Less(X:Double; Y:Double):Boolean; function AP_FP_Less_Eq(X:Double; Y:Double):Boolean; function AP_FP_Greater(X:Double; Y:Double):Boolean; function AP_FP_Greater_Eq(X:Double; Y:Double):Boolean; {var // pointers to AP BLAS functions ASMDotProduct1: function(V1: PDouble; V2: PDouble; N: Integer):Double;cdecl; ASMMove1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMMoveS1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer; S: Double);cdecl; ASMMoveNeg1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMAdd1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMAddS1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer; S: Double);cdecl; ASMSub1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; } implementation {var // use ablas.dll (ALGLIB BLAS) if found UseAPBLASFlag: Boolean = True; } // pointers to AP BLAS functions {$IFNDEF NOABLAS} { ASMDotProduct1: function(V1: PDouble; V2: PDouble; N: Integer):Double;cdecl; ASMMove1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMMoveS1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer; S: Double);cdecl; ASMMoveNeg1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMAdd1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl; ASMAddS1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer; S: Double);cdecl; ASMSub1: procedure(VDst: PDouble; VSrc: PDouble; N: Integer);cdecl;} {$ENDIF} ///////////////////////////////////////////////////////////////////////// // Functions/procedures ///////////////////////////////////////////////////////////////////////// function AbsReal(X : Double):Double; begin //Result := Abs(X); if X>=0 then Result:=X else Result:=-X; end; function AbsInt (I : Integer):Integer; begin //Result := Abs(I); if I>=0 then Result:=I else Result:=-I; end; function RandomReal():Double; begin Result := Random; end; function RandomInteger(I : Integer):Integer; begin Result := Random(I); end; function Sign(X:Double):Integer; begin if X>0 then Result := 1 else if X<0 then Result := -1 else Result := 0; end; function AP_Sqr(X:Double):Double; begin Result := X*X; end; ///////////////////////////////////////////////////////////////////////// // dynamical arrays copying ///////////////////////////////////////////////////////////////////////// function DynamicArrayCopy(const A: TInteger1DArray):TInteger1DArray;overload; var I: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do Result[I]:=A[I]; end; function DynamicArrayCopy(const A: TReal1DArray):TReal1DArray;overload; var I: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do Result[I]:=A[I]; end; function DynamicArrayCopy(const A: TComplex1DArray):TComplex1DArray;overload; var I: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do Result[I]:=A[I]; end; function DynamicArrayCopy(const A: TBoolean1DArray):TBoolean1DArray;overload; var I: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do Result[I]:=A[I]; end; function DynamicArrayCopy(const A: TInteger2DArray):TInteger2DArray;overload; var I,J: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do begin SetLength(Result[I], High(A[I])+1); for J:=Low(A[I]) to High(A[I]) do Result[I,J]:=A[I,J]; end; end; function DynamicArrayCopy(const A: TReal2DArray):TReal2DArray;overload; var I,J: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do begin SetLength(Result[I], High(A[I])+1); for J:=Low(A[I]) to High(A[I]) do Result[I,J]:=A[I,J]; end; end; function DynamicArrayCopy(const A: TComplex2DArray):TComplex2DArray;overload; var I,J: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do begin SetLength(Result[I], High(A[I])+1); for J:=Low(A[I]) to High(A[I]) do Result[I,J]:=A[I,J]; end; end; function DynamicArrayCopy(const A: TBoolean2DArray):TBoolean2DArray;overload; var I,J: Integer; begin SetLength(Result, High(A)+1); for I:=Low(A) to High(A) do begin SetLength(Result[I], High(A[I])+1); for J:=Low(A[I]) to High(A[I]) do Result[I,J]:=A[I,J]; end; end; ///////////////////////////////////////////////////////////////////////// // complex numbers ///////////////////////////////////////////////////////////////////////// function AbsComplex(const Z : Complex):Double; var W : Double; XABS : Double; YABS : Double; V : Double; begin XABS := AbsReal(Z.X); YABS := AbsReal(Z.Y); W := Max(XABS, YABS); V := Min(XABS, YABS); if V=0 then begin Result := W; end else begin Result := W*SQRT(1+Sqr(V/W)); end; end; function Conj(const Z : Complex):Complex; begin Result.X := Z.X; Result.Y := -Z.Y; end; function CSqr(const Z : Complex):Complex; begin Result.X := Sqr(Z.X)-Sqr(Z.Y); Result.Y := 2*Z.X*Z.Y; end; function C_Complex(const X : Double):Complex; begin Result.X := X; Result.Y := 0; end; function C_Opposite(const Z : Complex):Complex; begin Result.X := -Z.X; Result.Y := -Z.Y; end; function C_Add(const Z1 : Complex; const Z2 : Complex):Complex; begin Result.X := Z1.X+Z2.X; Result.Y := Z1.Y+Z2.Y; end; function C_Mul(const Z1 : Complex; const Z2 : Complex):Complex; begin Result.X := Z1.X*Z2.X-Z1.Y*Z2.Y; Result.Y := Z1.X*Z2.Y+Z1.Y*Z2.X; end; function C_AddR(const Z1 : Complex; const R : Double):Complex; begin Result.X := Z1.X+R; Result.Y := Z1.Y; end; function C_MulR(const Z1 : Complex; const R : Double):Complex; begin Result.X := Z1.X*R; Result.Y := Z1.Y*R; end; function C_Sub(const Z1 : Complex; const Z2 : Complex):Complex; begin Result.X := Z1.X-Z2.X; Result.Y := Z1.Y-Z2.Y; end; function C_SubR(const Z1 : Complex; const R : Double):Complex; begin Result.X := Z1.X-R; Result.Y := Z1.Y; end; function C_RSub(const R : Double; const Z1 : Complex):Complex; begin Result.X := R-Z1.X; Result.Y := -Z1.Y; end; function C_Div(const Z1 : Complex; const Z2 : Complex):Complex; var A : Double; B : Double; C : Double; D : Double; E : Double; F : Double; begin A := Z1.X; B := Z1.Y; C := Z2.X; D := Z2.Y; if AbsReal(D)Z2.X) or (Z1.Y<>Z2.Y); end; function C_EqualR(const Z1 : Complex; const R : Double):Boolean; begin Result := (Z1.X=R) and (Z1.Y=0); end; function C_NotEqualR(const Z1 : Complex; const R : Double):Boolean; begin Result := (Z1.X<>R) or (Z1.Y<>0); end; ///////////////////////////////////////////////////////////////////////// // AP BLAS generic interface ///////////////////////////////////////////////////////////////////////// {procedure UseAPBLAS(Flag: Boolean); begin UseAPBLASFlag:=Flag; end;} function APVDotProduct( V1: PDouble; I11, I12: Integer; V2: PDouble; I21, I22: Integer):Double; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVDotProduct: arrays of different size!'); Inc(V1, I11); Inc(V2, I21); // // Generic pascal code // C:=I12-I11; Result:=0; for I:=0 to C do begin Result:=Result+V1^*V2^; Inc(V1); Inc(V2); end; end; procedure APVMove( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVMove: arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVMove( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Double);overload; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVMove: arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=S*VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVMoveNeg( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer); var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVMoveNeg: arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=-VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVAdd( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVAdd: arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=VDst^+VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVAdd( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Real);overload; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVAdd: arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=VDst^+S*VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVSub( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer);overload; var I, C: LongInt; begin Assert(I12-I11=I22-I21, 'APVSub arrays of different size!'); Inc(VDst, I11); Inc(VSrc, I21); // // Generic pascal code // C:=I12-I11; for I:=0 to C do begin VDst^:=VDst^-VSrc^; Inc(VDst); Inc(VSrc); end; end; procedure APVSub( VDst: PDouble; I11, I12: Integer; VSrc: PDouble; I21, I22: Integer; S: Real);overload; begin Assert(I12-I11=I22-I21, 'APVSub: arrays of different size!'); APVAdd(VDst, I11, I12, VSrc, I21, I22, -S); end; procedure APVMul( VOp: PDouble; I1, I2: Integer; S: Real); var I, C: LongInt; begin Inc(VOp, I1); C:=I2-I1; for I:=0 to C do begin VOp^:=S*VOp^; Inc(VOp); end; end; ///////////////////////////////////////////////////////////////////////// // IEEE-compliant functions ///////////////////////////////////////////////////////////////////////// {$OPTIMIZATION OFF} function AP_Double(X:Double):Double; begin Result:=X; end; function AP_FP_Eq(X:Double; Y:Double):Boolean; begin Result:=X=Y; end; function AP_FP_NEq(X:Double; Y:Double):Boolean; begin Result:=X<>Y; end; function AP_FP_Less(X:Double; Y:Double):Boolean; begin Result:=XY; end; function AP_FP_Greater_Eq(X:Double; Y:Double):Boolean; begin Result:=X>=Y; end; end.