aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/ieee/math_complex-body.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ieee/math_complex-body.vhdl')
-rw-r--r--libraries/ieee/math_complex-body.vhdl394
1 files changed, 394 insertions, 0 deletions
diff --git a/libraries/ieee/math_complex-body.vhdl b/libraries/ieee/math_complex-body.vhdl
new file mode 100644
index 000000000..9b8b75ad4
--- /dev/null
+++ b/libraries/ieee/math_complex-body.vhdl
@@ -0,0 +1,394 @@
+---------------------------------------------------------------
+--
+-- This source file may be used and distributed without restriction.
+-- No declarations or definitions shall be included in this package.
+-- This package cannot be sold or distributed for profit.
+--
+-- ****************************************************************
+-- * *
+-- * W A R N I N G *
+-- * *
+-- * This DRAFT version IS NOT endorsed or approved by IEEE *
+-- * *
+-- ****************************************************************
+--
+-- Title: PACKAGE BODY MATH_COMPLEX
+--
+-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX
+-- which contains common complex constants and basic complex
+-- functions and operations.
+--
+-- Author: IEEE VHDL Math Package Study Group
+--
+-- Notes:
+-- The package body uses package IEEE.MATH_REAL
+--
+-- The package body shall be considered the formal definition of
+-- the semantics of this package. Tool developers may choose to implement
+-- the package body in the most efficient manner available to them.
+--
+-- Source code for this package body comes from the following
+-- following sources:
+-- IEEE VHDL Math Package Study Group participants,
+-- U. of Mississippi, Mentor Graphics, Synopsys,
+-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol
+-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable
+-- Random Number Generators, Handbook of Mathematical Functions
+-- by Milton Abramowitz and Irene A. Stegun (Dover).
+--
+-- History:
+-- Version 0.1 Jose A. Torres 4/23/93 First draft
+-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code
+--
+-------------------------------------------------------------
+Library IEEE;
+
+Use IEEE.MATH_REAL.all; -- real trascendental operations
+
+Package body MATH_COMPLEX is
+
+ function CABS(Z: in complex ) return real is
+ -- returns absolute value (magnitude) of Z
+ variable ztemp : complex_polar;
+ begin
+ ztemp := COMPLEX_TO_POLAR(Z);
+ return ztemp.mag;
+ end CABS;
+
+ function CARG(Z: in complex ) return real is
+ -- returns argument (angle) in radians of a complex number
+ variable ztemp : complex_polar;
+ begin
+ ztemp := COMPLEX_TO_POLAR(Z);
+ return ztemp.arg;
+ end CARG;
+
+ function CMPLX(X: in real; Y: in real := 0.0 ) return complex is
+ -- returns complex number X + iY
+ begin
+ return COMPLEX'(X, Y);
+ end CMPLX;
+
+ function "-" (Z: in complex ) return complex is
+ -- unary minus; returns -x -jy for z= x + jy
+ begin
+ return COMPLEX'(-z.Re, -z.Im);
+ end "-";
+
+ function "-" (Z: in complex_polar ) return complex_polar is
+ -- unary minus; returns (z.mag, z.arg + MATH_PI)
+ begin
+ return COMPLEX_POLAR'(z.mag, z.arg + MATH_PI);
+ end "-";
+
+ function CONJ (Z: in complex) return complex is
+ -- returns complex conjugate (x-jy for z = x+ jy)
+ begin
+ return COMPLEX'(z.Re, -z.Im);
+ end CONJ;
+
+ function CONJ (Z: in complex_polar) return complex_polar is
+ -- returns complex conjugate (z.mag, -z.arg)
+ begin
+ return COMPLEX_POLAR'(z.mag, -z.arg);
+ end CONJ;
+
+ function CSQRT(Z: in complex ) return complex_vector is
+ -- returns square root of Z; 2 values
+ variable ztemp : complex_polar;
+ variable zout : complex_vector (0 to 1);
+ variable temp : real;
+ begin
+ ztemp := COMPLEX_TO_POLAR(Z);
+ temp := SQRT(ztemp.mag);
+ zout(0).re := temp*COS(ztemp.arg/2.0);
+ zout(0).im := temp*SIN(ztemp.arg/2.0);
+
+ zout(1).re := temp*COS(ztemp.arg/2.0 + MATH_PI);
+ zout(1).im := temp*SIN(ztemp.arg/2.0 + MATH_PI);
+
+ return zout;
+ end CSQRT;
+
+ function CEXP(Z: in complex ) return complex is
+ -- returns e**Z
+ begin
+ return COMPLEX'(EXP(Z.re)*COS(Z.im), EXP(Z.re)*SIN(Z.im));
+ end CEXP;
+
+ function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar is
+ -- converts complex to complex_polar
+ begin
+ return COMPLEX_POLAR'(sqrt(z.re**2 + z.im**2),atan2(z.re,z.im));
+ end COMPLEX_TO_POLAR;
+
+ function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex is
+ -- converts complex_polar to complex
+ begin
+ return COMPLEX'( z.mag*cos(z.arg), z.mag*sin(z.arg) );
+ end POLAR_TO_COMPLEX;
+
+
+ --
+ -- arithmetic operators
+ --
+
+ function "+" ( L: in complex; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L.Re + R.Re, L.Im + R.Im);
+ end "+";
+
+ function "+" (L: in complex_polar; R: in complex_polar) return complex is
+ variable zL, zR : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(zL.Re + zR.Re, zL.Im + zR.Im);
+ end "+";
+
+ function "+" ( L: in complex_polar; R: in complex ) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re + R.Re, zL.Im + R.Im);
+ end "+";
+
+ function "+" ( L: in complex; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L.Re + zR.Re, L.Im + zR.Im);
+ end "+";
+
+ function "+" ( L: in real; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L + R.Re, R.Im);
+ end "+";
+
+ function "+" ( L: in complex; R: in real ) return complex is
+ begin
+ return COMPLEX'(L.Re + R, L.Im);
+ end "+";
+
+ function "+" ( L: in real; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L + zR.Re, zR.Im);
+ end "+";
+
+ function "+" ( L: in complex_polar; R: in real) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re + R, zL.Im);
+ end "+";
+
+ function "-" ( L: in complex; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L.Re - R.Re, L.Im - R.Im);
+ end "-";
+
+ function "-" ( L: in complex_polar; R: in complex_polar) return complex is
+ variable zL, zR : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(zL.Re - zR.Re, zL.Im - zR.Im);
+ end "-";
+
+ function "-" ( L: in complex_polar; R: in complex ) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re - R.Re, zL.Im - R.Im);
+ end "-";
+
+ function "-" ( L: in complex; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L.Re - zR.Re, L.Im - zR.Im);
+ end "-";
+
+ function "-" ( L: in real; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L - R.Re, -1.0 * R.Im);
+ end "-";
+
+ function "-" ( L: in complex; R: in real ) return complex is
+ begin
+ return COMPLEX'(L.Re - R, L.Im);
+ end "-";
+
+ function "-" ( L: in real; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L - zR.Re, -1.0*zR.Im);
+ end "-";
+
+ function "-" ( L: in complex_polar; R: in real) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re - R, zL.Im);
+ end "-";
+
+ function "*" ( L: in complex; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L.Re * R.Re - L.Im * R.Im, L.Re * R.Im + L.Im * R.Re);
+ end "*";
+
+ function "*" ( L: in complex_polar; R: in complex_polar) return complex is
+ variable zout : complex_polar;
+ begin
+ zout.mag := L.mag * R.mag;
+ zout.arg := L.arg + R.arg;
+ return POLAR_TO_COMPLEX(zout);
+ end "*";
+
+ function "*" ( L: in complex_polar; R: in complex ) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re*R.Re - zL.Im * R.Im, zL.Re * R.Im + zL.Im*R.Re);
+ end "*";
+
+ function "*" ( L: in complex; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L.Re*zR.Re - L.Im * zR.Im, L.Re * zR.Im + L.Im*zR.Re);
+ end "*";
+
+ function "*" ( L: in real; R: in complex ) return complex is
+ begin
+ return COMPLEX'(L * R.Re, L * R.Im);
+ end "*";
+
+ function "*" ( L: in complex; R: in real ) return complex is
+ begin
+ return COMPLEX'(L.Re * R, L.Im * R);
+ end "*";
+
+ function "*" ( L: in real; R: in complex_polar) return complex is
+ variable zR : complex;
+ begin
+ zR := POLAR_TO_COMPLEX( R );
+ return COMPLEX'(L * zR.Re, L * zR.Im);
+ end "*";
+
+ function "*" ( L: in complex_polar; R: in real) return complex is
+ variable zL : complex;
+ begin
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'(zL.Re * R, zL.Im * R);
+ end "*";
+
+ function "/" ( L: in complex; R: in complex ) return complex is
+ variable magrsq : REAL := R.Re ** 2 + R.Im ** 2;
+ begin
+ if (magrsq = 0.0) then
+ assert FALSE report "Attempt to divide by (0,0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ return COMPLEX'( (L.Re * R.Re + L.Im * R.Im) / magrsq,
+ (L.Im * R.Re - L.Re * R.Im) / magrsq);
+ end if;
+ end "/";
+
+ function "/" ( L: in complex_polar; R: in complex_polar) return complex is
+ variable zout : complex_polar;
+ begin
+ if (R.mag = 0.0) then
+ assert FALSE report "Attempt to divide by (0,0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ zout.mag := L.mag/R.mag;
+ zout.arg := L.arg - R.arg;
+ return POLAR_TO_COMPLEX(zout);
+ end if;
+ end "/";
+
+ function "/" ( L: in complex_polar; R: in complex ) return complex is
+ variable zL : complex;
+ variable temp : REAL := R.Re ** 2 + R.Im ** 2;
+ begin
+ if (temp = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ zL := POLAR_TO_COMPLEX( L );
+ return COMPLEX'( (zL.Re * R.Re + zL.Im * R.Im) / temp,
+ (zL.Im * R.Re - zL.Re * R.Im) / temp);
+ end if;
+ end "/";
+
+ function "/" ( L: in complex; R: in complex_polar) return complex is
+ variable zR : complex := POLAR_TO_COMPLEX( R );
+ variable temp : REAL := zR.Re ** 2 + zR.Im ** 2;
+ begin
+ if (R.mag = 0.0) or (temp = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ return COMPLEX'( (L.Re * zR.Re + L.Im * zR.Im) / temp,
+ (L.Im * zR.Re - L.Re * zR.Im) / temp);
+ end if;
+ end "/";
+
+ function "/" ( L: in real; R: in complex ) return complex is
+ variable temp : REAL := R.Re ** 2 + R.Im ** 2;
+ begin
+ if (temp = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ temp := L / temp;
+ return COMPLEX'( temp * R.Re, -temp * R.Im );
+ end if;
+ end "/";
+
+ function "/" ( L: in complex; R: in real ) return complex is
+ begin
+ if (R = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ return COMPLEX'(L.Re / R, L.Im / R);
+ end if;
+ end "/";
+
+ function "/" ( L: in real; R: in complex_polar) return complex is
+ variable zR : complex := POLAR_TO_COMPLEX( R );
+ variable temp : REAL := zR.Re ** 2 + zR.Im ** 2;
+ begin
+ if (R.mag = 0.0) or (temp = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ temp := L / temp;
+ return COMPLEX'( temp * zR.Re, -temp * zR.Im );
+ end if;
+ end "/";
+
+ function "/" ( L: in complex_polar; R: in real) return complex is
+ variable zL : complex := POLAR_TO_COMPLEX( L );
+ begin
+ if (R = 0.0) then
+ assert FALSE report "Attempt to divide by (0.0,0.0)"
+ severity ERROR;
+ return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
+ else
+ return COMPLEX'(zL.Re / R, zL.Im / R);
+ end if;
+ end "/";
+end MATH_COMPLEX;