Computing: Free Pascal Programming

Working with complex numbers in Free Pascal.

The core of the Free Pascal programming language does not include complex numbers, however, FPC's default runtime library includes the unit uComplex, that defines the type Complex, operator overloading for this type, and lots of complex number functions. The "u" in uComplex stands for the Greek letter μ, meaning "micro", as the implementation is kept as simple as possible.

The type Complex is defined as a record of two real numbers, the first one being the real part, the second one being the imaginary part of the complex number.
    type
    Complex = record
      re: Real;
      im: Real;
    end;
    PComplex = ^Complex;

The unit also defines two constants, one for the complex number i (0 + 1i), the other for the complex number 0 (0 + 0i):
    const
        i:    Complex = (re: 0.0; im: 1.0);
        _0: Complex = (re: 0.0; im: 0.0);

To assign a value to a variable of type Complex, you can assign its real and imaginary parts to the record items. Another way is to use the function CInit:
    function CInit(Zre, Zim: Real): Complex;

Arithmetic operators, as well as the equality comparison operator (=) are overloaded for usage with complex numbers; a mixture of complex and real numbers is also possible. Some examples:
    Z := Z1 + Z2;
    Z := Z3 * (Z1 - Z2);
    Z := Z1 ** R;
    Z := Z1 ** Z2;
    if Z1 = Z2 then
        ...

With the constant i being defined, operator overloading allows the direct assignment of a value to a complex variable, the value being given as an arithmetic expression of the form Zre ± Zim*i. Examples:
    Z := -i;
    Z := 2-3*i;

The uComplex unit doesn't include any procedures for complex number input/output. There is, however, a function to convert a complex number into a string, that may be used in a Write or Writeln statement to output the complex number.
    function CStr(Z: Complex): string;
    function CStr(Z: Complex; Len: Integer): string;
    function CStr(Z: Complex; Len, Dec: Integer): string;

The following program sample shows some arithmetic operations and the usage of the CStr function.

    program cplx1;
    {$mode objfpc}{$H+}
    uses
        UComplex;
    var
        R: Real;
        Z1, Z2, Z3, Z4: Complex;
    begin
        R := -1 / 5;
        Z1 := i; Z2 := -i;
        Z3 := 1 + i; Z4 := 1 - i;
        Writeln('(1+i) + (1-i) = ', CStr(Z3 + Z4));
        Writeln('(1+i) + (1-i) = ', CStr(Z3 + Z4, 0, 0));
        Writeln('(1+i) - (1-i) = ', CStr(Z3 - Z4, 0, 0));
        Writeln('-5 * [-(i-1)] = ', CStr(R * -Z4, 0, 2));
        Writeln('i^2 = ', CStr(Z1 ** 2, 0, 0));
        Writeln('(-i)^2 = ', CStr(Z2 ** 2, 0, 0));
        Writeln;
        Write('Hit ENTER to terminate '); Readln;
    end.

Here is the program output:

Complex numbers in Free Pascal: Sample program showing the usage of the function CStr to output a complex number

As you can see on the screenshot, the implementation of CStr is rudimentary. If the complex actually is a real number (if the imaginary part is zero), the number is sometimes printed as such, but sometimes is printed with ending +0i, or even -0i. Similarly, numbers that have a real part of zero are printed with leading 0+ or 0-. Even tough the programmer has well the possibility to take control over the number of decimal digits, the insignificant zeros are not dropped (but this isn't the case for the function Str either).

I just don't like such "ugly looking output". That's the reason why I have written the function ComplexToStr, that properly transforms a complex number into a string. Here is the code:

    function ComplexToStr(CplxNumber: Complex): string;
    // As a difference with "CStr" of the UComplex unit, this function returns a properly formatted string representation of a complex number
    // Important: Real/imaginary values with an absolute value < 1E-7 are considered to be 0!
    var
        L: Integer;
        SComplex, SReal, SImag: string;
    begin
        // Complex z = 0: return '0'
        if (Abs(CplxNumber.Re) < 1E-7) and (Abs(CplxNumber.Im) < 1E-7) then
            SComplex := '0'
        // Complex z <> 0: return formatted string
        else begin
            // Round real and decimal part to 7 digits and remove all non-significant zeros
            Str(CplxNumber.Re:0:7, SReal); Str(Abs(CplxNumber.Im):0:7, SImag);
            L := Length(SReal);
            while SReal[L] = '0' do
                Dec(L);                                           // non-significant zeros
            if SReal[L] = '.' then
                Dec(L);                                           // decimal separator (without fractional digits)
            SReal := LeftStr(SReal, L);
            L := Length(SImag);
            while SImag[L] = '0' do
                Dec(L);
            if SImag[L] = '.' then
                Dec(L);
            SImag := LeftStr(SImag, L);
            SComplex := '';
            // Keep real part only if it is <> 0
            if Abs(CplxNumber.Re) >= 1E-7
                SComplex := SReal;
            // Keep imaginary part only if <> 0
            if Abs(CplxNumber.Im) >= 1E-7 then begin
                // Complex with real and imaginary part <> 0
                if Abs(CplxNumber.Re) >= 1E-7 then begin
                    if CplxNumber.Im < 0 then
                        SComplex += '-'
                    else
                        SComplex += '+';
                end
                // Complex with imaginary part only <> 0
                else begin
                    if CplxNumber.Im < 0 then
                        SComplex += '-'                      // minus sign has to be displayed (plus sign has not)
                end;
                if Abs(CplxNumber.Im) <> 1 then    // use "i" instead of "1i"
                    SComplex += SImag;
                SComplex += 'i';
            end;
        end;
        Result := SComplex;
    end;

Important: As comparing the content of a real variable to some value rarely yields an equality, all comparisons of "real/imaginary value = 0" are implemented as "absolute value of real/imaginary value ≥ 1e-7". This results in proper display of complex numbers with only a real, or only an imaginary part. On the other hand, a real/imaginary value that is less than 1e-7 will be treated as 0! Thus, if your program uses such small values, you'll have to change the code of the function...

The same program sample as before, but using the function ComplexToStr to format the complex numbers display gives the following output:

Complex numbers in Free Pascal: Sample program showing the usage of the custom function ComplexToStr to output a complex number

The uComplex unit doesn't include any function to convert a string into a complex number. I have written the function StrToComplex for this purpose. The function supposes that the string is a correctly formatted complex number string, where "correctly formatted" means with a format as the return value of the ComplexToStr function (in particular, no spaces are permitted as separators of the operator between the real and the imaginary part of the complex number). Here is the code:

    function StrToComplex(SNumber: string): Complex;
    // The string is supposed to be properly formatted (as the one returned by the ComplexToStr function)
    var
        Sign, P: Integer;
        NumberRe, NumberIm: Real;
    begin
        if SNumber = 'i' then
            SNumber := '1i'
        else if SNumber = '-i' then
            SNumber := '-1i';
        // Complex number contains an imaginary part
        if RightStr(SNumber, 1) = 'i' then begin
            SNumber := LeftStr(SNumber, Length(SNumber) - 1);
            Sign := 1;
            // This "-" is the sign of the real part (if this one <> 0) or the sign of the imaginary part (if there is no real part)
            if LeftStr(SNumber, 1) = '-' then begin
                SNumber := RightStr(SNumber, Length(SNumber) - 1);
                Sign := -1;
            end;
            // This "+" resp. "-" sign starts the imaginary part; if both are absent, the real part = 0 (cf. ComplexToStr function)
            P := Pos('+', SNumber);
            if P = 0 then
                P := Pos('-', SNumber);
            if P = 0 then begin
                NumberRe := 0; Val(SNumber, NumberIm); NumberIm *= Sign;
            end
            else begin
                Val(LeftStr(SNumber, P - 1), NumberRe); NumberRe *= Sign;
                Val(RightStr(SNumber, Length(SNumber) - P + 1), NumberIm);
            end;
        end
        // Complex number contains no imaginary part
        else begin
            Val(SNumber, NumberRe); NumberIm := 0;
        end;
        Result := CInit(NumberRe, NumberIm);
    end;

The following program sample asks the user for two complex numbers and calculates their product. User input, supposed to be a correctly formatted complex number string is converted into complex numbers using StrToComplex. The product of the two numbers is displayed using ComplexToStr.

    program cplx3;
    {$mode objfpc}{$H+}
    uses
        SysUtils, Crt, UComplex;
    var
        S: string;
        Key: Char;
        Z1, Z2: Complex;
    { Convert string to complex number }
    function StrToComplex(SNumber: string): Complex;
        ...
    { Convert complex number to string }
    function ComplexToStr(CplxNumber: Complex): string;
        ...
    begin
        repeat
            Writeln;
            Write('Enter complex number z1? '); Readln(S);
            Z1 := StrToComplex(S);
            Write('Enter complex number z2? '); Readln(S);
            Z2 := StrToComplex(S);
            Writeln('z1 * z2 = ', ComplexToStr(Z1 * Z2));
            Write('ESC to terminate, any other key to continue...');
            Key := ReadKey;
            if Key = #0 then
                Key := ReadKey;
        until Key = #27;
    end.

Here is an example of the program output:

Complex numbers in Free Pascal: Sample program showing the usage of the custom functions StrToComplex and ComplexToStr to input/output a complex number

A complex number's conjugate, modulus (absolute value), reciprocal (inverse) and argument ("phase" φ) are returned by the following functions:
    function Cong(Z: Complex): Complex;
    function CMod(Z: Complex): Real;
    function CInv(Z: Complex): Complex;
    function CArg(Z: Complex): Real;

For a definition and the formulas to calculate these values, please, have a look at the Complex number article in Wikipedia.

The following are the complex equivalents of the standard Free Pascal real functions:
    function CSqr(Z: Complex): Complex;
    function CSqrt(Z: Complex): Complex;
    function CExp(Z: Complex): Complex;
    function CLn(Z: Complex): Complex;

The following complex trigonometric functions and inverse complex trigonometric functions are declared in uComplex:
    function CCos(Z: Complex): Complex;
    function CSin(Z: Complex): Complex;
    function CTg (Z: Complex): Complex;
    function CArc_cos(Z: Complex): Complex;
    function CArc_sin(Z: Complex): Complex;
    function CArc_tg(Z: Complex): Complex;
Note that CTg returns the complex tangent (not, as it may perhaps seem, the cotangent)!

And here are the declared complex hyperbolic functions and their inverse:
    function CCh(Z: Complex): Complex;
    function CSh(Z: Complex): Complex;
    function CTh(Z: Complex): Complex;
    function CArg_ch(Z: Complex): Complex;
    function CArg_sh(Z: Complex): Complex;
    function CArg_th(Z: Complex): Complex;

Programs on my site that deal with complex numbers.

The command line programs eququad and equcub calculate the roots of a quadratic (2nd degree) resp. cubic (3rd degree) equation with real coefficients (the roots of such equations may be complex numbers). Whereas equcub uses uComplex, eququad uses a custom record type to describe complex numbers. Click the following link to visit the Quadratic equations in one variable documentation page, and the following one to view the Cubic equations in one variable documentation.

The command line programs equcplx and equcplx2 calculate the roots of a linear (1st degree) resp. quadratic (2nd degree) equation with complex coefficients. The programs use uComplex, as well as my custom functions StrToComplex and ComplexToStr. Click the following link to visit the First degree complex equations in 1 variable documentation page, and the following one to view the Second degree complex equations in 1 variable documentation.

The command line program cplxroots calculates the nth roots of a complex number. The program doesn't use uComplex, but declares a custom record type TComplex to describe complex numbers. The input is done by entering the real and imaginary part separately. The display form of the roots may be chose by the user: standard (Cartesian) form: z=a+bi, polar form: z=r[cos(φ)+sin(φ)], or exponential form: z=reφi. Click the following link to visit the Roots of a complex number documentation page.

The GUI application Arithmetic6 is a math trainer (exercise generator) concerning the basic operations with complex numbers. The application uses uComplex, as well as my custom functions StrToComplex and ComplexToStr. Click the following link to visit the Mathematics trainer: Basic complex numbers arithmetic documentation page.

The GUI application SimpleCplxCalculator is a simple calculator application for complex numbers. Besides the 4 basic operations (+, -, x, :), it includes buttons to calculate the square, the cube, the inverse, and the modulus of a complex number. The application uses uComplex, as well as my custom functions StrToComplex and ComplexToStr. Click the following link to visit the Simple complex numbers calculator documentation page.


If you find this text helpful, please, support me and this website by signing my guestbook.