{CMPXLIB: Complex math library for Pascal; by Ficomp, Inc., Fairfax, Va. This library uses pointer variables so that functions rather than procedures can be used. Reference: "Information Hiding in Pascal", Michael B. Feldman, BYTE, November 1981, pp. 493-498. As pointed out in the reference, the problem with pointer variables is that a new record is created every time a complex function is called. Temporary record space is not reused unless it is specifically released with the built-in function DISPOSE( ). These library functions create temporary records that will automatically be erased when used in a subsequent complex operation. The CPERM( ) procedure will mark a complex number so that it will not be erased until DISPOSE( ) is used. The program segment below illustrates the use of the functions: 1 T1:=CMPLX(SQR(COS(RPSI)),0.0); 2 T1:=CSQRT(CMPXO(N2,'-',T1)); 3 CPERM(T1); 4 T2:=CMPLX(SIN(RPSI),0.0); 5 IF POL = 'V' THEN 6 T2:=CMPXO(T2,'*',N2); 7 CPERM(T2); 8 GAMA:=POLAR(CMPXO(CMPXO(T2,'-',T1),'/',CMPXO(T2,'+',T1))); 9 DISPOSE(T1); 10 DISPOSE(T2); 11 LAG:=-ANG(GAMA); 12 IF LAG < 0 THEN 13 LAG:=LAG+PI_2; 14 WRITELN(MAG(GAMA),LAG); 15 DISPOSE(GAMA); In line 1, complex variable T1 is created. In line 2 T1 is replaced by a new T1. The old T1 was erased by CMPXO function call. That intermediate variable was also erased by the CSQRT function. In line 3, T1 is made permanent because it will be used twice in line number 8. T2 is treated in the same manner in lines 4 to 7. Lines 9 and 10 erase T1 & T2 since they are no longer needed. All of the intermediate complex numbers created in line 8 are automatically erased as they are used. In line 15, GAMA is specifically erased, since it is no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} MODULE CMPXLIB; {$M CMPLX} {$M RE} {$M IM} {$M PHASOR} {$M MAG} {$M ANG} {$M CMPXO} {$M POLAR} {$M CART} {$M CSQR} {$M CSQRT} {$M CRECP} {$M CONJG} {$M CABS} {$M CPERM} {$M *} TYPE CMPXNUM = RECORD RE_PART,IM_PART: REAL TEMPSTO: BOOLEAN END; COMPLEX = ^CMPXNUM; VAR P:COMPLEX; NR,NI,NRE,NIM,T:REAL; EXTERNAL PROCEDURE @ERR(AN_ERROR:BOOLEAN;ERRNUM:INTEGER); EXTERNAL FUNCTION ATAN2(X,Y:REAL): REAL; FUNCTION CMPLX(R,I:REAL): COMPLEX; {to create complex number with cartesian coordinates} BEGIN NEW(P); P^.RE_PART := R; P^.IM_PART := I; P^.TEMPSTO := TRUE; CMPLX := P END; FUNCTION RE(N:COMPLEX): REAL; {returns real part of complex number} BEGIN RE := N^.RE_PART END; FUNCTION IM(N:COMPLEX): REAL; {returns imaginary part of complex number} BEGIN IM := N^.IM_PART END; FUNCTION PHASOR(M,A:REAL): COMPLEX; {to create phasor from magnitude and angle} BEGIN NEW(P); P^.RE_PART := M; P^.IM_PART := A; P^.TEMPSTO := TRUE; PHASOR := P END; FUNCTION MAG(N:COMPLEX): REAL; {returns magnitude part of phasor} BEGIN MAG := N^.RE_PART END; FUNCTION ANG(N:COMPLEX): REAL; {returns angle part of phasor} BEGIN ANG := N^.IM_PART END; FUNCTION CMPXO(N1:COMPLEX;OP:CHAR;N2:COMPLEX): COMPLEX; {to add, subtract, miltiply, or divide complex numbers} BEGIN NR := RE(N1); NI := IM(N1); NRE := RE(N2); NIM := IM(N2); CASE OP OF '+': {complex sum of 2 complex numbers, N1+N2} CMPXO := CMPLX(NR+NRE,NI+NIM); '-': {complex difference of 2 complex numbers, N1-N2} CMPXO := CMPLX(NR-NRE,NI-NIM); '*': {complex product of 2 complex numbers, N1*N2} CMPXO := CMPLX(NR*NRE-NI*NIM,NR*NIM+NI*NRE); '/': {complex quotient of 2 complex numbers, N1/N2} BEGIN T := SQR(NRE)+SQR(NIM); CMPXO := CMPLX((NR*NRE+NI*NIM)/T,(NRE*NI-NR*NIM)/T) END; ELSE BEGIN @ERR(TRUE,4); WRITELN(OP,' is an illegal complex operator'); CMPXO := CMPLX(0.0,0.0) END; END; CERASE(N1); CERASE(N2) END; FUNCTION POLAR(N:COMPLEX): COMPLEX; {to convert complex number from cartesian to polar coordinates} BEGIN NR := RE(N); NI := IM(N); POLAR := PHASOR(SQRT(SQR(NR)+SQR(NI)),ATAN2(NR,NI)); CERASE(N) END; FUNCTION CART(N:COMPLEX): COMPLEX; {to convert complex number from polar to cartesian coordinates} BEGIN NR := MAG(N); NI := ANG(N); CART := CMPLX(NR*COS(NI),NR*SIN(NI)); CERASE(N) END; FUNCTION CSQR(N:COMPLEX): COMPLEX; {square of complex number, SQR(N)} BEGIN NR := RE(N); NI := IM(N); CSQR := CMPLX(SQR(NR)-SQR(NI),2*NR*NI); CERASE(N) END; FUNCTION CSQRT(N:COMPLEX): COMPLEX; {square root of complex number, SQRT(N)} BEGIN NR := RE(N); NI := IM(N); T := SQRT((NR+SQRT(SQR(NR)+SQR(NI)))/2); CSQRT := CMPLX(T,NI/(2*T)); CERASE(N) END; FUNCTION CRECP(N:COMPLEX): COMPLEX; {recripical of complex number, 1/N} BEGIN NR := RE(N); NI := IM(N); T := SQR(NR)+SQR(NI); CRECP := CMPLX(NR/T,-NI/T); CERASE(N) END; FUNCTION CONJG(N:COMPLEX): COMPLEX; {conjugate of a complex number} BEGIN CONJG := CMPLX(RE(N),-IM(N)); CERASE(N) END; FUNCTION CABS(N:COMPLEX): REAL; {absolute value of complex number, ABS(N)} BEGIN CABS := SQRT(SQR(RE(N))+SQR(IM(N))); CERASE(N) END; PROCEDURE CPERM(N:COMPLEX); {to make complex number permanent} BEGIN N^.TEMPSTO := FALSE END; PROCEDURE CERASE(N:COMPLEX); {to release temporary complex variables} BEGIN IF N^.TEMPSTO THEN DISPOSE(N) END; MODEND.