------------------------------------------------------------------------
--
-- Copyright 1996 by IEEE. All rights reserved.
--
-- This source file is an informative part of IEEE Std 1076.2-1996, IEEE Standard 
-- VHDL Mathematical Packages. This source file may not be copied, sold, or 
-- included with software that is sold without written permission from the IEEE
-- Standards Department. This source file may be used to implement this standard 
-- and may be distributed in compiled form in any manner so long as the 
-- compiled form does not allow direct decompilation of the original source file.
-- This source file may be copied for individual use between licensed users. 
-- This source file is provided on an AS IS basis. The IEEE disclaims ANY 
-- WARRANTY EXPRESS OR IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY 
-- AND FITNESS FOR USE FOR A PARTICULAR PURPOSE. The user of the source 
-- file shall indemnify and hold IEEE harmless from any damages or liability 
-- arising out of the use thereof.
--
-- Title:       Standard VHDL Mathematical Packages (IEEE Std 1076.2-1996,
--              MATH_COMPLEX)
--
-- Library:     This package shall be compiled into a library
--              symbolically named IEEE.
--
-- Developers:  IEEE DASC VHDL Mathematical Packages Working Group
--
-- Purpose:     This package body is a nonnormative implementation of the 
--              functionality defined in the MATH_COMPLEX package declaration.
--
-- Limitation:  The values generated by the functions in this package may
--              vary from platform to platform, and the precision of results
--              is only guaranteed to be the minimum required by IEEE Std 1076
--              -1993.
--
-- Notes:
--              The "package declaration" defines the types, subtypes, and
--              declarations of MATH_COMPLEX.
--              The standard mathematical definition and conventional meaning
--              of the mathematical functions that are part of this standard
--              represent the formal semantics of the implementation of the
--              MATH_COMPLEX package declaration.  The purpose of the
--              MATH_COMPLEX package body is to clarify such semantics and
--              provide a guideline for implementations to verify their
--              implementation of MATH_COMPLEX.  Tool developers may choose to
--              implement the package body in the most efficient manner
--              available to them.
--
-- -----------------------------------------------------------------------------
-- Version    : 1.5
-- Date       : 24 July 1996
-- -----------------------------------------------------------------------------

use WORK.MATH_REAL.all;

package body MATH_COMPLEX is

    --
    -- Equality and Inequality Operators for COMPLEX_POLAR
    --
    function "=" ( L: in COMPLEX_POLAR;  R: in COMPLEX_POLAR ) return BOOLEAN
                                                                         is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns FALSE on error
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in =(L,R)"
                            severity ERROR;
                return FALSE;
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in =(L,R)"
                            severity ERROR;
                return FALSE;
        end if;

        -- Get special values
        if ( L.MAG = 0.0 and R.MAG = 0.0 ) then
                return TRUE;
        end if;

        -- Get value for general case
        if ( L.MAG = R.MAG and L.ARG = R.ARG ) then
                return TRUE;
        end if;

        return FALSE;
    end "=";


    function "/=" ( L: in COMPLEX_POLAR;  R: in COMPLEX_POLAR ) return BOOLEAN
                                                                         is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns FALSE on error
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in /=(L,R)"
                            severity ERROR;
                return FALSE;
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in /=(L,R)"
                            severity ERROR;
                return FALSE;
        end if;

        -- Get special values
        if ( L.MAG = 0.0 and R.MAG = 0.0 ) then
                return FALSE;
        end if;

        -- Get value for general case
        if ( L.MAG = R.MAG and L.ARG = R.ARG ) then
                return FALSE;
        end if;

        return TRUE;
    end "/=";

    --
    -- Other Functions Start Here
    --

    function CMPLX(X: in REAL;  Y: in REAL := 0.0 ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(X, Y);
    end CMPLX;


    function GET_PRINCIPAL_VALUE(X: in REAL ) return PRINCIPAL_VALUE is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
        variable TEMP: REAL;
    begin
        -- Check if already a principal value
        if ( X > -MATH_PI and X <= MATH_PI ) then
                return PRINCIPAL_VALUE'(X);
        end if;

        -- Get principal value
        TEMP := X;
        while ( TEMP <= -MATH_PI ) loop
                TEMP := TEMP + MATH_2_PI;
        end loop;
        while (TEMP > MATH_PI ) loop
                TEMP := TEMP - MATH_2_PI;
        end loop;

        return PRINCIPAL_VALUE'(TEMP);
    end GET_PRINCIPAL_VALUE;

    function COMPLEX_TO_POLAR(Z: in COMPLEX ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
        variable TEMP: REAL;
    begin
        -- Get value for special cases
        if ( Z.RE = 0.0 ) then
            if ( Z.IM = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
            elsif ( Z.IM > 0.0 ) then
                return COMPLEX_POLAR'(Z.IM, MATH_PI_OVER_2);
            else
                return COMPLEX_POLAR'(-Z.IM, -MATH_PI_OVER_2);
            end if;
        end if;

        if ( Z.IM = 0.0 ) then
            if ( Z.RE = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
            elsif ( Z.RE > 0.0 ) then
                return COMPLEX_POLAR'(Z.RE, 0.0);
            else
                return COMPLEX_POLAR'(-Z.RE, MATH_PI);
            end if;
        end if;

        -- Get principal value for general case
        TEMP := ARCTAN(Z.IM, Z.RE);

        return COMPLEX_POLAR'(SQRT(Z.RE*Z.RE + Z.IM*Z.IM),
                                                 GET_PRINCIPAL_VALUE(TEMP));
    end COMPLEX_TO_POLAR;

    function POLAR_TO_COMPLEX(Z: in COMPLEX_POLAR ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns MATH_CZERO on error
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                       report "Z.ARG = -MATH_PI in POLAR_TO_COMPLEX(Z)"
                       severity ERROR;
                return MATH_CZERO;
        end if;

        -- Get value for general case
        return COMPLEX'( Z.MAG*COS(Z.ARG), Z.MAG*SIN(Z.ARG) );
    end POLAR_TO_COMPLEX;


    function "ABS"(Z: in COMPLEX ) return POSITIVE_REAL is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) ABS(Z) = SQRT(Z.RE*Z.RE + Z.IM*Z.IM)

    begin
        -- Get value for general case
        return POSITIVE_REAL'(SQRT(Z.RE*Z.RE + Z.IM*Z.IM));
    end "ABS";

    function "ABS"(Z: in COMPLEX_POLAR ) return POSITIVE_REAL is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) ABS(Z) = Z.MAG
        --        b) Returns 0.0 on error

    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in ABS(Z)"
                            severity ERROR;
                  return 0.0;
        end if;

        -- Get value for general case
        return Z.MAG;
    end "ABS";


    function ARG(Z: in COMPLEX ) return PRINCIPAL_VALUE is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) ARG(Z) = ARCTAN(Z.IM, Z.RE)

        variable ZTEMP : COMPLEX_POLAR;
    begin
        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        return ZTEMP.ARG;
    end ARG;

    function ARG(Z: in COMPLEX_POLAR ) return PRINCIPAL_VALUE is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) ARG(Z) = Z.ARG
        --        b) Returns 0.0 on error

    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in ARG(Z)"
                            severity ERROR;
                  return 0.0;
        end if;

        -- Get value for general case
        return Z.ARG;
    end ARG;

    function "-" (Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns -x -jy for Z = x + jy
    begin
        -- Get value for general case
        return COMPLEX'(-Z.RE, -Z.IM);
    end "-";

    function "-" (Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns (Z.MAG, Z.ARG + MATH_PI)
        --        b) Returns Z on error
        variable TEMP: REAL;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in -(Z)"
                            severity ERROR;
                  return Z;
        end if;

        -- Get principal value for general case
        TEMP := REAL'(Z.ARG) + MATH_PI;

        return COMPLEX_POLAR'(Z.MAG, GET_PRINCIPAL_VALUE(TEMP));
    end "-";

    function CONJ (Z: in COMPLEX) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns x - jy for Z = x + jy
    begin
        -- Get value for general case
        return COMPLEX'(Z.RE, -Z.IM);
    end CONJ;

    function CONJ (Z: in COMPLEX_POLAR) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX conjugate (Z.MAG, -Z.ARG)
        --        b) Returns Z on error
        --
        variable TEMP: PRINCIPAL_VALUE;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in CONJ(Z)"
                            severity ERROR;
                  return Z;
        end if;

        -- Get principal value for general case
        if ( Z.ARG = MATH_PI or Z.ARG = 0.0 ) then
                TEMP := Z.ARG;
        else
                TEMP := -Z.ARG;
        end if;

         return COMPLEX_POLAR'(Z.MAG, TEMP);
    end CONJ;

    function SQRT(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
        variable ZTEMP : COMPLEX_POLAR;
        variable ZOUT : COMPLEX;
        variable TMAG : REAL;
        variable TARG : REAL;
    begin
        -- Get value for special cases
        if ( Z = MATH_CZERO ) then
                return MATH_CZERO;
        end if;

        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        TMAG := SQRT(ZTEMP.MAG);
        TARG := 0.5*ZTEMP.ARG;

        if ( COS(TARG) > 0.0 ) then
                ZOUT.RE := TMAG*COS(TARG);
                ZOUT.IM := TMAG*SIN(TARG);
                return ZOUT;
        end if;

        if ( COS(TARG) < 0.0 ) then
                ZOUT.RE := TMAG*COS(TARG + MATH_PI);
                ZOUT.IM := TMAG*SIN(TARG + MATH_PI);
                return ZOUT;
        end if;

        if ( SIN(TARG) > 0.0 ) then
                ZOUT.RE := 0.0;
                ZOUT.IM := TMAG*SIN(TARG);
                return ZOUT;
        end if;

        ZOUT.RE := 0.0;
        ZOUT.IM := TMAG*SIN(TARG + MATH_PI);
        return ZOUT;
    end SQRT;

    function SQRT(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns Z on error

        variable ZOUT : COMPLEX_POLAR;
        variable TMAG : REAL;
        variable TARG : REAL;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in SQRT(Z)"
                            severity ERROR;
                  return Z;
        end if;

        -- Get value for special cases
        if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then
                return Z;
        end if;

        -- Get principal value for general case
        TMAG := SQRT(Z.MAG);
        TARG := 0.5*Z.ARG;

        ZOUT.MAG := POSITIVE_REAL'(TMAG);

        if ( COS(TARG) < 0.0 ) then
                TARG := TARG + MATH_PI;
        end if;

        if ( (COS(TARG) = 0.0) and (SIN(TARG) < 0.0) ) then
                TARG := TARG + MATH_PI;
        end if;

        ZOUT.ARG := GET_PRINCIPAL_VALUE(TARG);
        return ZOUT;
    end SQRT;

    function EXP(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None

        variable TEMP: REAL;
    begin
        -- Get value for special cases
        if ( Z = MATH_CZERO ) then
                return MATH_CBASE_1;
        end if;

        if ( Z.RE = 0.0 ) then
                if ( Z.IM = MATH_PI or Z.IM = -MATH_PI ) then
                        return COMPLEX'(-1.0, 0.0);
                end if;

                if ( Z.IM = MATH_PI_OVER_2 ) then
                        return MATH_CBASE_J;
                end if;

                if ( Z.IM = -MATH_PI_OVER_2 ) then
                        return COMPLEX'(0.0, -1.0);
                end if;
        end if;

        -- Get value for general case
        TEMP := EXP(Z.RE);
        return COMPLEX'(TEMP*COS(Z.IM), TEMP*SIN(Z.IM));
    end EXP;

    function EXP(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns Z on error

        variable ZTEMP : COMPLEX;
        variable temp: REAL;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in EXP(Z)"
                            severity ERROR;
                  return Z;
        end if;

        -- Get value for special cases
        if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI and (Z.ARG = MATH_PI_OVER_2 or
                                                 Z.ARG = -MATH_PI_OVER_2 )) then
                return COMPLEX_POLAR'(1.0, MATH_PI);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 ) then
                if ( Z.ARG = MATH_PI_OVER_2 ) then
                        return COMPLEX_POLAR'(1.0, MATH_PI_OVER_2);
                end if;

                if ( Z.ARG = -MATH_PI_OVER_2 ) then
                        return COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2);
                end if;
        end if;

        -- Get principal value for general case
        ZTEMP := POLAR_TO_COMPLEX(Z);
        ZOUT.MAG := POSITIVE_REAL'(EXP(ZTEMP.RE));
        ZOUT.ARG := GET_PRINCIPAL_VALUE(ZTEMP.IM);

        return ZOUT;
    end EXP;

    function LOG(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'LOW, 0.0) on error

        variable ZTEMP : COMPLEX_POLAR;
        variable TEMP : REAL;
    begin
        -- Check validity of input arguments
        if ( Z.RE = 0.0  and Z.IM = 0.0 ) then
                assert FALSE
                        report "Z.RE = 0.0 and Z.IM = 0.0 in LOG(Z)"
                        severity ERROR;
                return COMPLEX'(REAL'LOW, 0.0);
        end if;

        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = -1.0 ) then
                        return COMPLEX'(0.0, MATH_PI);
                end if;
                if ( Z.RE = MATH_E ) then
                        return MATH_CBASE_1;
                end if;
                if ( Z.RE = 1.0 ) then
                        return MATH_CZERO;
                end if;
        end if;

        if ( Z.RE = 0.0 ) then
                if (Z.IM = 1.0) then
                        return COMPLEX'(0.0, MATH_PI_OVER_2);
                end if;
                if (Z.IM = -1.0) then
                        return COMPLEX'(0.0, -MATH_PI_OVER_2);
                end if;
        end if;

        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        TEMP := LOG(ZTEMP.MAG);
        return COMPLEX'(TEMP, ZTEMP.ARG);
    end LOG;

    function LOG2(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'LOW, 0.0) on error

        variable ZTEMP : COMPLEX_POLAR;
        variable TEMP : REAL;
    begin

        -- Check validity of input arguments
        if ( Z.RE = 0.0  and Z.IM = 0.0 ) then
                assert FALSE
                        report "Z.RE = 0.0 and Z.IM = 0.0 in LOG2(Z)"
                        severity ERROR;
                return COMPLEX'(REAL'LOW, 0.0);
        end if;

        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = 2.0 ) then
                        return MATH_CBASE_1;
                end if;
                if ( Z.RE = 1.0 ) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        TEMP := MATH_LOG2_OF_E*LOG(ZTEMP.MAG);
        return COMPLEX'(TEMP, MATH_LOG2_OF_E*ZTEMP.ARG);
    end LOG2;

    function LOG10(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'LOW, 0.0) on error

        variable ZTEMP : COMPLEX_POLAR;
        variable TEMP : REAL;
    begin
        -- Check validity of input arguments
        if ( Z.RE = 0.0  and Z.IM = 0.0 ) then
                assert FALSE
                        report "Z.RE = 0.0 and Z.IM = 0.0 in LOG10(Z)"
                        severity ERROR;
                return COMPLEX'(REAL'LOW, 0.0);
        end if;

        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = 10.0 ) then
                        return MATH_CBASE_1;
                end if;
                if ( Z.RE = 1.0 ) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        TEMP := MATH_LOG10_OF_E*LOG(ZTEMP.MAG);
        return COMPLEX'(TEMP, MATH_LOG10_OF_E*ZTEMP.ARG);
    end LOG10;


    function LOG(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error

        variable ZTEMP : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.MAG <= 0.0 ) then
                assert FALSE
                        report "Z.MAG <= 0.0 in LOG(Z)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in LOG(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        -- Compute value for special cases
        if (Z.MAG = 1.0 ) then
                if ( Z.ARG = 0.0 ) then
                        return COMPLEX_POLAR'(0.0, 0.0);
                end if;

                if ( Z.ARG = MATH_PI ) then
                        return COMPLEX_POLAR'(MATH_PI, MATH_PI_OVER_2);
                end if;

                if ( Z.ARG = MATH_PI_OVER_2 ) then
                        return COMPLEX_POLAR'(MATH_PI_OVER_2, MATH_PI_OVER_2);
                end if;

                if ( Z.ARG = -MATH_PI_OVER_2 ) then
                        return COMPLEX_POLAR'(MATH_PI_OVER_2, -MATH_PI_OVER_2);
                end if;
        end if;

        if ( Z.MAG = MATH_E and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        -- Compute value for general case
        ZTEMP.RE := LOG(Z.MAG);
        ZTEMP.IM := Z.ARG;
        ZOUT := COMPLEX_TO_POLAR(ZTEMP);
        return ZOUT;
    end LOG;



    function LOG2(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error

        variable ZTEMP : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.MAG <= 0.0 ) then
                assert FALSE
                        report "Z.MAG <= 0.0 in LOG2(Z)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                            report "Z.ARG = -MATH_PI in LOG2(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        -- Compute value for special cases
        if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = 2.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        -- Compute value for general case
        ZTEMP.RE := MATH_LOG2_OF_E*LOG(Z.MAG);
        ZTEMP.IM := MATH_LOG2_OF_E*Z.ARG;
        ZOUT := COMPLEX_TO_POLAR(ZTEMP);
        return ZOUT;
    end LOG2;

    function LOG10(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error
        variable ZTEMP : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.MAG <= 0.0 ) then
                assert FALSE
                        report "Z.MAG <= 0.0 in LOG10(Z)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;


        if ( Z.ARG = -MATH_PI ) then
                  assert FALSE
                           report "Z.ARG = -MATH_PI in LOG10(Z)"
                           severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        -- Compute value for special cases
        if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = 10.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        -- Compute value for general case
        ZTEMP.RE := MATH_LOG10_OF_E*LOG(Z.MAG);
        ZTEMP.IM := MATH_LOG10_OF_E*Z.ARG;
        ZOUT := COMPLEX_TO_POLAR(ZTEMP);
        return ZOUT;
    end LOG10;

    function LOG(Z: in COMPLEX; BASE: in REAL ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'LOW, 0.0) on error

        variable ZTEMP : COMPLEX_POLAR;
        variable TEMPRE : REAL;
        variable TEMPIM : REAL;
    begin
        -- Check validity of input arguments
        if ( Z.RE = 0.0  and Z.IM = 0.0 ) then
                assert FALSE
                        report "Z.RE = 0.0 and Z.IM = 0.0 in LOG(Z,BASE)"
                        severity ERROR;
                return COMPLEX'(REAL'LOW, 0.0);
        end if;

        if ( BASE <= 0.0 or BASE = 1.0 ) then
                assert FALSE
                        report "BASE <= 0.0 or BASE = 1.0 in LOG(Z,BASE)"
                        severity ERROR;
                return COMPLEX'(REAL'LOW, 0.0);
        end if;

        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = BASE ) then
                        return MATH_CBASE_1;
                end if;
                if ( Z.RE = 1.0 ) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        ZTEMP := COMPLEX_TO_POLAR(Z);
        TEMPRE := LOG(ZTEMP.MAG, BASE);
        TEMPIM := ZTEMP.ARG/LOG(BASE);
        return COMPLEX'(TEMPRE, TEMPIM);
    end LOG;

    function LOG(Z: in COMPLEX_POLAR; BASE: in REAL ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error

        variable ZTEMP : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.MAG <= 0.0 ) then
                assert FALSE
                        report "Z.MAG <= 0.0 in LOG(Z,BASE)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        if ( BASE <= 0.0 or BASE = 1.0 ) then
                assert FALSE
                        report "BASE <= 0.0 or BASE = 1.0 in LOG(Z,BASE)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                           report "Z.ARG = -MATH_PI in LOG(Z,BASE)"
                           severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, MATH_PI);
        end if;

        -- Compute value for special cases
        if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = BASE and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        -- Compute value for general case
        ZTEMP.RE := LOG(Z.MAG, BASE);
        ZTEMP.IM := Z.ARG/LOG(BASE);
        ZOUT := COMPLEX_TO_POLAR(ZTEMP);
        return ZOUT;
    end LOG;


    function SIN(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = 0.0 or Z.RE = MATH_PI) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        return COMPLEX'(SIN(Z.RE)*COSH(Z.IM), COS(Z.RE)*SINH(Z.IM));
    end SIN;

    function SIN(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(0.0, 0.0) on error

        variable Z1, Z2 : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                            report "Z.ARG = -MATH_PI in SIN(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for special cases
        if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for general case
        Z1 := POLAR_TO_COMPLEX(Z);
        Z2 := COMPLEX'(SIN(Z1.RE)*COSH(Z1.IM), COS(Z1.RE)*SINH(Z1.IM));
        ZOUT := COMPLEX_TO_POLAR(Z2);
        return ZOUT;
    end SIN;

    function COS(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin


        -- Get value for special cases
        if ( Z.IM = 0.0 ) then
                if ( Z.RE = MATH_PI_OVER_2 or Z.RE = -MATH_PI_OVER_2) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        return COMPLEX'(COS(Z.RE)*COSH(Z.IM), -SIN(Z.RE)*SINH(Z.IM));
    end COS;

    function COS(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(0.0, 0.0) on error

        variable Z1, Z2 : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                            report "Z.ARG = -MATH_PI in COS(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for special cases
        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for general case
        Z1 := POLAR_TO_COMPLEX(Z);
        Z2 := COMPLEX'(COS(Z1.RE)*COSH(Z1.IM), -SIN(Z1.RE)*SINH(Z1.IM));
        ZOUT := COMPLEX_TO_POLAR(Z2);
        return ZOUT;
    end COS;

    function SINH(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        -- Get value for special cases
        if ( Z.RE = 0.0 ) then
                if ( Z.IM = 0.0 or Z.IM = MATH_PI ) then
                        return MATH_CZERO;
                end if;



                if ( Z.IM = MATH_PI_OVER_2 ) then
                        return MATH_CBASE_J;
                end if;

                if ( Z.IM = -MATH_PI_OVER_2 ) then
                        return -MATH_CBASE_J;
                end if;
        end if;

        -- Get value for general case
        return COMPLEX'(SINH(Z.RE)*COS(Z.IM), COSH(Z.RE)*SIN(Z.IM));
    end SINH;

    function SINH(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(0.0, 0.0) on error

        variable Z1, Z2 : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                            report "Z.ARG = -MATH_PI in SINH(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for special cases
        if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI and Z.ARG = MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(1.0, MATH_PI_OVER_2);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2);
        end if;

        -- Compute value for general case
        Z1 := POLAR_TO_COMPLEX(Z);
        Z2 := COMPLEX'(SINH(Z1.RE)*COS(Z1.IM), COSH(Z1.RE)*SIN(Z1.IM));
        ZOUT := COMPLEX_TO_POLAR(Z2);
        return ZOUT;
    end SINH;


    function COSH(Z: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        -- Get value for special cases
        if ( Z.RE = 0.0 ) then
                if ( Z.IM = 0.0 ) then
                        return MATH_CBASE_1;
                end if;

                if ( Z.IM = MATH_PI ) then
                        return -MATH_CBASE_1;
                end if;

                if ( Z.IM = MATH_PI_OVER_2 or Z.IM = -MATH_PI_OVER_2 ) then
                        return MATH_CZERO;
                end if;
        end if;

        -- Get value for general case
        return COMPLEX'(COSH(Z.RE)*COS(Z.IM), SINH(Z.RE)*SIN(Z.IM));
    end COSH;

    function COSH(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR(0.0, 0.0) on error

        variable Z1, Z2 : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( Z.ARG = -MATH_PI ) then
                assert FALSE
                            report "Z.ARG = -MATH_PI in COSH(Z)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for special cases
        if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then
                return COMPLEX_POLAR'(1.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI and Z.ARG = MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(1.0, MATH_PI);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 ) then
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Compute value for general case
        Z1 := POLAR_TO_COMPLEX(Z);
        Z2 := COMPLEX'(COSH(Z1.RE)*COS(Z1.IM), SINH(Z1.RE)*SIN(Z1.IM));
        ZOUT := COMPLEX_TO_POLAR(Z2);
        return ZOUT;
    end COSH;


    --
    -- Arithmetic Operators
    --
    function "+" ( L: in COMPLEX;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE + R.RE, L.IM + R.IM);
    end "+";

    function "+" ( L: in REAL; R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L + R.RE, R.IM);
    end "+";

    function "+" ( L: in COMPLEX;  R: in REAL )    return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE + R, L.IM);
    end "+";

    function "+" (L: in COMPLEX_POLAR; R: in COMPLEX_POLAR)
                                                        return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZL, ZR : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in +(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;


        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in +(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZL := POLAR_TO_COMPLEX( L );
        ZR := POLAR_TO_COMPLEX( R );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE + ZR.RE, ZL.IM +ZR.IM));
        return ZOUT;
    end "+";

    function "+" ( L: in REAL;  R: in COMPLEX_POLAR) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        variable ZR : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in +(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZR := POLAR_TO_COMPLEX( R );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(L + ZR.RE, ZR.IM));
        return ZOUT;
    end "+";

    function "+" ( L: in COMPLEX_POLAR;  R: in REAL) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZL : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in +(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZL := POLAR_TO_COMPLEX( L );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE + R, ZL.IM));
        return ZOUT;
    end "+";

    function "-" ( L: in COMPLEX;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE - R.RE, L.IM - R.IM);
    end "-";

    function "-" ( L: in REAL;     R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L - R.RE, -1.0 * R.IM);
    end "-";

    function "-" ( L: in COMPLEX;  R: in REAL )    return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE - R, L.IM);
    end "-";

    function "-" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR)
                                                        return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZL, ZR : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in -(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in -(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;
        -- Get principal value
        ZL := POLAR_TO_COMPLEX( L );
        ZR := POLAR_TO_COMPLEX( R );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE - ZR.RE, ZL.IM -ZR.IM));
        return ZOUT;
    end "-";

    function "-" ( L: in REAL;  R: in COMPLEX_POLAR) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZR : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in -(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZR := POLAR_TO_COMPLEX( R );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(L - ZR.RE, -1.0*ZR.IM));
        return ZOUT;
    end "-";

    function "-" ( L: in COMPLEX_POLAR;  R: in REAL) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZL : COMPLEX;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in -(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZL := POLAR_TO_COMPLEX( L );
        ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE - R, ZL.IM));
        return ZOUT;
    end "-";


    function "*" ( L: in COMPLEX;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE * R.RE - L.IM * R.IM, L.RE * R.IM + L.IM * R.RE);
    end "*";


    function "*" ( L: in REAL;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L * R.RE, L * R.IM);
    end "*";

    function "*" ( L: in COMPLEX;  R: in REAL )    return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        None
    begin
        return COMPLEX'(L.RE * R, L.IM * R);
    end "*";

    function "*" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR)
                                                        return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in *(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in *(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZOUT.MAG := L.MAG * R.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG + R.ARG);

        return ZOUT;
    end "*";

    function "*" ( L: in REAL;  R: in COMPLEX_POLAR) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
            variable ZL : COMPLEX_POLAR;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                            report "R.ARG = -MATH_PI in *(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZL.MAG := POSITIVE_REAL'(ABS(L));
        if ( L < 0.0 ) then
                ZL.ARG := MATH_PI;
        else
                ZL.ARG := 0.0;
        end if;

        ZOUT.MAG := ZL.MAG * R.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(ZL.ARG + R.ARG);

        return ZOUT;
    end "*";

    function "*" ( L: in COMPLEX_POLAR;  R: in REAL) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(0.0, 0.0) on error
        --
        variable ZR : COMPLEX_POLAR;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                            report "L.ARG = -MATH_PI in *(L,R)"
                            severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZR.MAG := POSITIVE_REAL'(ABS(R));
        if ( R < 0.0 ) then
                ZR.ARG := MATH_PI;
        else
                ZR.ARG := 0.0;
        end if;

        ZOUT.MAG := L.MAG * ZR.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG + ZR.ARG);

        return ZOUT;
    end "*";

   function "/" ( L: in COMPLEX;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'HIGH, 0.0) on error
        --
        variable TEMP : REAL := R.RE*R.RE + R.IM*R.IM;
   begin
        -- Check validity of input arguments
        if (TEMP = 0.0) then
                 assert FALSE
                        report "Attempt to divide COMPLEX by (0.0, 0.0)"
                        severity ERROR;
                 return COMPLEX'(REAL'HIGH, 0.0);
        end if;

        -- Get value
        return COMPLEX'( (L.RE * R.RE + L.IM * R.IM) / TEMP,
                         (L.IM * R.RE - L.RE * R.IM) / TEMP);
    end "/";

   function "/" ( L: in REAL;  R: in COMPLEX ) return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'HIGH, 0.0) on error
        --
        variable TEMP : REAL := R.RE*R.RE + R.IM*R.IM;
    begin
        -- Check validity of input arguments
        if (TEMP = 0.0) then
                 assert FALSE
                        report "Attempt to divide COMPLEX by (0.0, 0.0)"
                        severity ERROR;
                 return COMPLEX'(REAL'HIGH, 0.0);
        end if;

        -- Get value
        TEMP := L / TEMP;
        return  COMPLEX'( TEMP * R.RE, -TEMP * R.IM );
    end "/";

    function "/" ( L: in COMPLEX;  R: in REAL )    return COMPLEX is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX'(REAL'HIGH, 0.0) on error
    begin
        -- Check validity of input arguments
        if (R = 0.0) then
                 assert FALSE
                        report "Attempt to divide COMPLEX by 0.0"
                        severity ERROR;
                 return COMPLEX'(REAL'HIGH, 0.0);
        end if;

        -- Get value
        return COMPLEX'(L.RE / R, L.IM / R);
    end "/";


    function "/" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR)
                                                        return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error
        --
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if (R.MAG = 0.0) then
                assert FALSE
                        report "Attempt to divide COMPLEX_POLAR by (0.0, 0.0)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, 0.0);
        end if;

        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                        report "L.ARG = -MATH_PI in /(L,R)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, 0.0);
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                        report "R.ARG = -MATH_PI in /(L,R)"
                        severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZOUT.MAG := L.MAG/R.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG - R.ARG);

        return ZOUT;
    end "/";

    function "/" ( L: in COMPLEX_POLAR;  R: in REAL) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error
        --
        variable ZR : COMPLEX_POLAR;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if (R = 0.0) then
                assert FALSE
                        report "Attempt to divide COMPLEX_POLAR by 0.0"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, 0.0);
        end if;

        if ( L.ARG = -MATH_PI ) then
                assert FALSE
                        report "L.ARG = -MATH_PI in /(L,R)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, 0.0);
        end if;

        -- Get principal value
        ZR.MAG := POSITIVE_REAL'(ABS(R));
        if R < 0.0 then
                ZR.ARG := MATH_PI;
        else
                ZR.ARG := 0.0;
        end if;

        ZOUT.MAG := L.MAG/ZR.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG - ZR.ARG);

        return ZOUT;
    end "/";

    function "/" ( L: in REAL;  R: in COMPLEX_POLAR) return COMPLEX_POLAR is
        -- Description:
        --        See function declaration in IEEE Std 1076.2-1996
        -- Notes:
        --        a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error
        --
        variable ZL : COMPLEX_POLAR;
        variable ZOUT : COMPLEX_POLAR;
    begin
        -- Check validity of input arguments
        if (R.MAG = 0.0) then
                assert FALSE
                        report "Attempt to divide COMPLEX_POLAR by (0.0, 0.0)"
                        severity ERROR;
                return COMPLEX_POLAR'(REAL'HIGH, 0.0);
        end if;

        if ( R.ARG = -MATH_PI ) then
                assert FALSE
                        report "R.ARG = -MATH_P in /(L,R)"
                        severity ERROR;
                return COMPLEX_POLAR'(0.0, 0.0);
        end if;

        -- Get principal value
        ZL.MAG := POSITIVE_REAL'(ABS(L));
        if L < 0.0 then
                ZL.ARG := MATH_PI;
        else
                ZL.ARG := 0.0;
        end if;

        ZOUT.MAG := ZL.MAG/R.MAG;
        ZOUT.ARG := GET_PRINCIPAL_VALUE(ZL.ARG - R.ARG);

        return ZOUT;
    end "/";

end  MATH_COMPLEX;
