{ *********************************************************************** }
{                                                                         }
{ Delphi Visual Component Library                                         }
{                                                                         }
{ Copyright (c) 2001-2004 Borland Software Corporation                    }
{                                                                         }
{ *********************************************************************** }

unit Borland.Vcl.VarCmplx;

interface

uses
  Variants;

{ Complex variant creation utils }

function VarComplexCreate: Variant; overload;
function VarComplexCreate(const AReal: Double): Variant; overload;
function VarComplexCreate(const AReal, AImaginary: Double): Variant; overload;
function VarComplexCreate(const AText: string): Variant; overload;

function VarComplex: TVarType;
function VarIsComplex(const AValue: Variant): Boolean;
function VarAsComplex(const AValue: Variant): Variant;
function VarComplexSimplify(const AValue: Variant): Variant;

{ Complex variant support }

function VarComplexAbsSqr(const AValue: Variant): Double;
function VarComplexAbs(const AValue: Variant): Double;
function VarComplexAngle(const AValue: Variant): Double;
function VarComplexSign(const AValue: Variant): Variant;
function VarComplexConjugate(const AValue: Variant): Variant;
function VarComplexInverse(const AValue: Variant): Variant;
function VarComplexExp(const AValue: Variant): Variant;
function VarComplexLn(const AValue: Variant): Variant;
function VarComplexLog2(const AValue: Variant): Variant;
function VarComplexLog10(const AValue: Variant): Variant;
function VarComplexLogN(const AValue: Variant; const X: Double): Variant;
function VarComplexSqr(const AValue: Variant): Variant;
function VarComplexSqrt(const AValue: Variant): Variant;
function VarComplexPower(const AValue, APower: Variant): Variant;
function VarComplexTimesPosI(const AValue: Variant): Variant;
function VarComplexTimesNegI(const AValue: Variant): Variant;
function VarComplexTimesImaginary(const AValue: Variant; const AFactor: Double): Variant;
function VarComplexTimesReal(const AValue: Variant; const AFactor: Double): Variant;

{ Complex variant trig support }

function VarComplexCos(const AValue: Variant): Variant;
function VarComplexSin(const AValue: Variant): Variant;
function VarComplexTan(const AValue: Variant): Variant;
function VarComplexCot(const AValue: Variant): Variant;
function VarComplexSec(const AValue: Variant): Variant;
function VarComplexCsc(const AValue: Variant): Variant;
function VarComplexArcCos(const AValue: Variant): Variant;
function VarComplexArcSin(const AValue: Variant): Variant;
function VarComplexArcTan(const AValue: Variant): Variant;
function VarComplexArcCot(const AValue: Variant): Variant;
function VarComplexArcSec(const AValue: Variant): Variant;
function VarComplexArcCsc(const AValue: Variant): Variant;
function VarComplexCosH(const AValue: Variant): Variant;
function VarComplexSinH(const AValue: Variant): Variant;
function VarComplexTanH(const AValue: Variant): Variant;
function VarComplexCotH(const AValue: Variant): Variant;
function VarComplexSecH(const AValue: Variant): Variant;
function VarComplexCscH(const AValue: Variant): Variant;
function VarComplexArcCosH(const AValue: Variant): Variant;
function VarComplexArcSinH(const AValue: Variant): Variant;
function VarComplexArcTanH(const AValue: Variant): Variant;
function VarComplexArcCotH(const AValue: Variant): Variant;
function VarComplexArcSecH(const AValue: Variant): Variant;
function VarComplexArcCscH(const AValue: Variant): Variant;

procedure VarComplexToPolar(const AValue: Variant; var ARadius, ATheta: Double;
  AFixTheta: Boolean = True);
function VarComplexFromPolar(const ARadius, ATheta: Double): Variant;

/// These used to be unit variables, now they just expose the properties in b.d.complex
function ComplexNumberSymbol: string; deprecated;
function ComplexNumberSymbolBeforeImaginary: Boolean; deprecated;
function ComplexNumberDefuzzAtZero: Boolean; deprecated;

implementation

uses
  Math, Complex;

{ Complex variant creation utils }

function VarComplexCreate: Variant;
begin
  Result := Variant(TComplex.From(0));
end;

function VarComplexCreate(const AReal: Double): Variant;
begin
  Result := Variant(TComplex.From(AReal));
end;

function VarComplexCreate(const AReal, AImaginary: Double): Variant;
begin
  Result := Variant(TComplex.From(AReal, AImaginary));
end;

function VarComplexCreate(const AText: string): Variant;
begin
  Result := Variant(TComplex.Parse(AText));
end;

var
  FVarType: TVarType;

function VarComplex: TVarType;
begin
  Result := FVarType;
end;

function VarIsComplex(const AValue: Variant): Boolean;
begin
  Result := TObject(AValue) is TComplex;
end;

function VarToComplex(const AValue: Variant): TComplex;
begin
  if VarIsComplex(AValue) then
    Result := TComplex(TObject(AValue))
  else if VarIsNumeric(AValue) then
    Result := TComplex.From(AValue)
  else
    Result := TComplex.Parse(AValue);
end;

function VarAsComplex(const AValue: Variant): Variant;
begin
  Result := Variant(VarToComplex(AValue));
end;

function VarComplexSimplify(const AValue: Variant): Variant;
begin
  if VarIsComplex(AValue) and IsZero(TComplex(AValue).Imaginary) then
    Result := TComplex(AValue).Real
  else
    Result := AValue;
end;


{ Complex variant support }

function VarComplexAbsSqr(const AValue: Variant): Double;
begin
  Result := AbsSqr(VarToComplex(AValue));
end;

function VarComplexAbs(const AValue: Variant): Double;
begin
  Result := Abs(VarToComplex(AValue));
end;

function VarComplexAngle(const AValue: Variant): Double;
begin
  Result := Angle(VarToComplex(AValue));
end;

function VarComplexSign(const AValue: Variant): Variant;
begin
  Result := Variant(Sign(VarToComplex(AValue)));
end;

function VarComplexConjugate(const AValue: Variant): Variant;
begin
  Result := Variant(TComplex.Conjugate(VarToComplex(AValue)));
end;

function VarComplexInverse(const AValue: Variant): Variant;
begin
  Result := Variant(TComplex.Inverse(VarToComplex(AValue)));
end;

function VarComplexExp(const AValue: Variant): Variant;
begin
  Result := Variant(Exp(VarToComplex(AValue)));
end;

function VarComplexLn(const AValue: Variant): Variant;
begin
  Result := Variant(Ln(VarToComplex(AValue)));
end;

function VarComplexLog2(const AValue: Variant): Variant;
begin
  Result := Variant(Log2(VarToComplex(AValue)));
end;

function VarComplexLog10(const AValue: Variant): Variant;
begin
  Result := Variant(Log10(VarToComplex(AValue)));
end;

function VarComplexLogN(const AValue: Variant; const X: Double): Variant;
begin
  Result := Variant(LogN(VarToComplex(AValue), X));
end;

function VarComplexSqr(const AValue: Variant): Variant;
begin
  Result := Variant(Sqr(VarToComplex(AValue)));
end;

function VarComplexSqrt(const AValue: Variant): Variant;
begin
  Result := Variant(Sqrt(VarToComplex(AValue)));
end;

function VarComplexPower(const AValue, APower: Variant): Variant;
begin
  Result := Variant(Power(VarToComplex(AValue), VarToComplex(APower)));
end;

function VarComplexTimesPosI(const AValue: Variant): Variant;
begin
  Result := Variant(VarToComplex(AValue) * TComplex.OneI);
end;

function VarComplexTimesNegI(const AValue: Variant): Variant;
begin
  Result := Variant(VarToComplex(AValue) * TComplex.NegI);
end;

function VarComplexTimesImaginary(const AValue: Variant; const AFactor: Double): Variant;
begin
  Result := Variant(VarToComplex(AValue) * TComplex.From(0, AFactor));
end;

function VarComplexTimesReal(const AValue: Variant; const AFactor: Double): Variant;
begin
  Result := Variant(VarToComplex(AValue) * TComplex.From(AFactor));
end;


{ Complex variant trig support }

function VarComplexCos(const AValue: Variant): Variant;
begin
  Result := Variant(Cos(VarToComplex(AValue)));
end;

function VarComplexSin(const AValue: Variant): Variant;
begin
  Result := Variant(Sin(VarToComplex(AValue)));
end;

function VarComplexTan(const AValue: Variant): Variant;
begin
  Result := Variant(Tan(VarToComplex(AValue)));
end;

function VarComplexCot(const AValue: Variant): Variant;
begin
  Result := Variant(Cot(VarToComplex(AValue)));
end;

function VarComplexSec(const AValue: Variant): Variant;
begin
  Result := Variant(Sec(VarToComplex(AValue)));
end;

function VarComplexCsc(const AValue: Variant): Variant;
begin
  Result := Variant(Csc(VarToComplex(AValue)));
end;

function VarComplexArcCos(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCos(VarToComplex(AValue)));
end;

function VarComplexArcSin(const AValue: Variant): Variant;
begin
  Result := Variant(ArcSin(VarToComplex(AValue)));
end;

function VarComplexArcTan(const AValue: Variant): Variant;
begin
  Result := Variant(ArcTan(VarToComplex(AValue)));
end;

function VarComplexArcCot(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCot(VarToComplex(AValue)));
end;

function VarComplexArcSec(const AValue: Variant): Variant;
begin
  Result := Variant(ArcSec(VarToComplex(AValue)));
end;

function VarComplexArcCsc(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCsc(VarToComplex(AValue)));
end;

function VarComplexCosH(const AValue: Variant): Variant;
begin
  Result := Variant(CosH(VarToComplex(AValue)));
end;

function VarComplexSinH(const AValue: Variant): Variant;
begin
  Result := Variant(SinH(VarToComplex(AValue)));
end;

function VarComplexTanH(const AValue: Variant): Variant;
begin
  Result := Variant(TanH(VarToComplex(AValue)));
end;

function VarComplexCotH(const AValue: Variant): Variant;
begin
  Result := Variant(CotH(VarToComplex(AValue)));
end;

function VarComplexSecH(const AValue: Variant): Variant;
begin
  Result := Variant(SecH(VarToComplex(AValue)));
end;

function VarComplexCscH(const AValue: Variant): Variant;
begin
  Result := Variant(CscH(VarToComplex(AValue)));
end;

function VarComplexArcCosH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCosH(VarToComplex(AValue)));
end;

function VarComplexArcSinH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcSinH(VarToComplex(AValue)));
end;

function VarComplexArcTanH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcTanH(VarToComplex(AValue)));
end;

function VarComplexArcCotH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCotH(VarToComplex(AValue)));
end;

function VarComplexArcSecH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcSecH(VarToComplex(AValue)));
end;

function VarComplexArcCscH(const AValue: Variant): Variant;
begin
  Result := Variant(ArcCscH(VarToComplex(AValue)));
end;


procedure VarComplexToPolar(const AValue: Variant; var ARadius, ATheta: Double; AFixTheta: Boolean = True);
var
  LValue: TComplex;
begin
  LValue := VarToComplex(AValue);
  ARadius := LValue.Modulus;
  ATheta := LValue.Phase;
  if AFixTheta then
  begin
    while ATheta > Pi do
      ATheta := ATheta - 2.0 * Pi;
    while ATheta <= -Pi do
      ATheta := ATheta + 2.0 * Pi;
  end;
end;

function VarComplexFromPolar(const ARadius, ATheta: Double): Variant;
begin
  Result := Variant(TComplex.From(ARadius, ATheta));
end;

/// These used to be unit variables, now they just expose the properties in b.d.complex
function ComplexNumberSymbol: string;
begin
  Result := TComplex.Symbol;
end;

function ComplexNumberSymbolBeforeImaginary: Boolean;
begin
  Result := TComplex.SymbolBeforeImaginary;
end;

function ComplexNumberDefuzzAtZero: Boolean;
begin
  Result := TComplex.DefuzzAtZero;
end;

initialization
  FVarType := RegisterCustomVariantType(TypeOf(TComplex));
end.
