1
------------------------------------------------------------------------
3
-- This source file may be used and distributed without restriction.
4
-- No declarations or definitions shall be added to this package.
5
-- This package cannot be sold or distributed for profit.
7
-- ****************************************************************
11
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
13
-- ****************************************************************
15
-- Title: PACKAGE MATH_REAL
17
-- Library: This package shall be compiled into a library
18
-- symbolically named IEEE.
20
-- Purpose: VHDL declarations for mathematical package MATH_REAL
21
-- which contains common real constants, common real
22
-- functions, and real trascendental functions.
24
-- Author: IEEE VHDL Math Package Study Group
27
-- The package body shall be considered the formal definition of
28
-- the semantics of this package. Tool developers may choose to implement
29
-- the package body in the most efficient manner available to them.
32
-- Version 0.1 (Strawman) Jose A. Torres 6/22/92
33
-- Version 0.2 Jose A. Torres 1/15/93
34
-- Version 0.3 Jose A. Torres 4/13/93
35
-- Version 0.4 Jose A. Torres 4/19/93
36
-- Version 0.5 Jose A. Torres 4/20/93 Added RANDOM()
37
-- Version 0.6 Jose A. Torres 4/23/93 Renamed RANDOM as
40
-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility
42
-------------------------------------------------------------
48
-- commonly used constants
50
constant MATH_E : real := 2.71828_18284_59045_23536;
52
constant MATH_1_E: real := 0.36787_94411_71442_32160;
54
constant MATH_PI : real := 3.14159_26535_89793_23846;
56
constant MATH_1_PI : real := 0.31830_98861_83790_67154;
58
constant MATH_LOG_OF_2: real := 0.69314_71805_59945_30942;
60
constant MATH_LOG_OF_10: real := 2.30258_50929_94045_68402;
62
constant MATH_LOG2_OF_E: real := 1.44269_50408_88963_4074;
64
constant MATH_LOG10_OF_E: real := 0.43429_44819_03251_82765;
66
constant MATH_SQRT2: real := 1.41421_35623_73095_04880;
68
constant MATH_SQRT1_2: real := 0.70710_67811_86547_52440;
70
constant MATH_SQRT_PI: real := 1.77245_38509_05516_02730;
72
constant MATH_DEG_TO_RAD: real := 0.01745_32925_19943_29577;
73
-- conversion factor from degree to radian
74
constant MATH_RAD_TO_DEG: real := 57.29577_95130_82320_87685;
75
-- conversion factor from radian to degree
78
-- attribute for functions whose implementation is foreign (C native)
80
attribute FOREIGN : string; -- predefined attribute in VHDL-1992
83
-- function declarations
85
function SIGN (X: real ) return real;
86
-- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0
88
function CEIL (X : real ) return real;
89
-- returns smallest integer value (as real) not less than X
91
function FLOOR (X : real ) return real;
92
-- returns largest integer value (as real) not greater than X
94
function ROUND (X : real ) return real;
95
-- returns integer FLOOR(X + 0.5) if X > 0;
96
-- return integer CEIL(X - 0.5) if X < 0
98
function FMAX (X, Y : real ) return real;
99
-- returns the algebraically larger of X and Y
101
function FMIN (X, Y : real ) return real;
102
-- returns the algebraically smaller of X and Y
104
procedure UNIFORM (variable Seed1,Seed2:inout integer; variable X:out real);
105
-- returns a pseudo-random number with uniform distribution in the
106
-- interval (0.0, 1.0).
107
-- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must
108
-- be initialized to values in the range [1, 2147483562] and
109
-- [1, 2147483398] respectively. The seed values are modified after
110
-- each call to UNIFORM.
111
-- This random number generator is portable for 32-bit computers, and
112
-- it has period ~2.30584*(10**18) for each set of seed values.
114
-- For VHDL-1992, the seeds will be global variables, functions to
115
-- initialize their values (INIT_SEED) will be provided, and the UNIFORM
116
-- procedure call will be modified accordingly.
118
function SRAND (seed: in integer ) return integer;
120
-- sets value of seed for sequence of
121
-- pseudo-random numbers.
122
-- It uses the foreign native C function srand().
123
attribute FOREIGN of SRAND : function is "C_NATIVE";
125
function RAND return integer;
127
-- returns an integer pseudo-random number with uniform distribution.
128
-- It uses the foreign native C function rand().
129
-- Seed for the sequence is initialized with the
130
-- SRAND() function and value of the seed is changed every
131
-- time SRAND() is called, but it is not visible.
132
-- The range of generated values is platform dependent.
133
attribute FOREIGN of RAND : function is "C_NATIVE";
135
function GET_RAND_MAX return integer;
137
-- returns the upper bound of the range of the
138
-- pseudo-random numbers generated by RAND().
139
-- The support for this function is platform dependent, and
140
-- it uses foreign native C functions or constants.
141
-- It may not be available in some platforms.
142
-- Note: the value of (RAND() / GET_RAND_MAX()) is a
143
-- pseudo-random number distributed between 0 & 1.
144
attribute FOREIGN of GET_RAND_MAX : function is "C_NATIVE";
146
function SQRT (X : real ) return real;
147
-- returns square root of X; X >= 0
149
function CBRT (X : real ) return real;
150
-- returns cube root of X
152
function "**" (X : integer; Y : real) return real;
153
-- returns Y power of X ==> X**Y;
154
-- error if X = 0 and Y <= 0.0
155
-- error if X < 0 and Y does not have an integer value
157
function "**" (X : real; Y : real) return real;
158
-- returns Y power of X ==> X**Y;
159
-- error if X = 0.0 and Y <= 0.0
160
-- error if X < 0.0 and Y does not have an integer value
162
function EXP (X : real ) return real;
163
-- returns e**X; where e = MATH_E
165
function LOG (X : real ) return real;
166
-- returns natural logarithm of X; X > 0
168
function LOG (BASE: positive; X : real) return real;
169
-- returns logarithm base BASE of X; X > 0
171
function SIN (X : real ) return real;
172
-- returns sin X; X in radians
174
function COS ( X : real ) return real;
175
-- returns cos X; X in radians
177
function TAN (X : real ) return real;
178
-- returns tan X; X in radians
179
-- X /= ((2k+1) * PI/2), where k is an integer
181
function ASIN (X : real ) return real;
182
-- returns -PI/2 < asin X < PI/2; | X | <= 1
184
function ACOS (X : real ) return real;
185
-- returns 0 < acos X < PI; | X | <= 1
187
function ATAN (X : real) return real;
188
-- returns -PI/2 < atan X < PI/2
190
function ATAN2 (X : real; Y : real) return real;
191
-- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0
193
function SINH (X : real) return real;
194
-- hyperbolic sine; returns (e**X - e**(-X))/2
196
function COSH (X : real) return real;
197
-- hyperbolic cosine; returns (e**X + e**(-X))/2
199
function TANH (X : real) return real;
200
-- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X))
202
function ASINH (X : real) return real;
203
-- returns ln( X + sqrt( X**2 + 1))
205
function ACOSH (X : real) return real;
206
-- returns ln( X + sqrt( X**2 - 1)); X >= 1
208
function ATANH (X : real) return real;
209
-- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1
215
---------------------------------------------------------------
217
-- This source file may be used and distributed without restriction.
218
-- No declarations or definitions shall be included in this package.
219
-- This package cannot be sold or distributed for profit.
221
-- ****************************************************************
225
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
227
-- ****************************************************************
229
-- Title: PACKAGE MATH_COMPLEX
231
-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX
232
-- which contains common complex constants and basic complex
233
-- functions and operations.
235
-- Author: IEEE VHDL Math Package Study Group
238
-- The package body uses package IEEE.MATH_REAL
240
-- The package body shall be considered the formal definition of
241
-- the semantics of this package. Tool developers may choose to implement
242
-- the package body in the most efficient manner available to them.
245
-- Version 0.1 (Strawman) Jose A. Torres 6/22/92
246
-- Version 0.2 Jose A. Torres 1/15/93
247
-- Version 0.3 Jose A. Torres 4/13/93
248
-- Version 0.4 Jose A. Torres 4/19/93
249
-- Version 0.5 Jose A. Torres 4/20/93
250
-- Version 0.6 Jose A. Torres 4/23/93 Added unary minus
251
-- and CONJ for polar
252
-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility
253
-- with package body.
254
-------------------------------------------------------------
257
Package MATH_COMPLEX is
260
type COMPLEX is record RE, IM: real; end record;
261
type COMPLEX_VECTOR is array (integer range <>) of COMPLEX;
262
type COMPLEX_POLAR is record MAG: real; ARG: real; end record;
264
constant CBASE_1: complex := COMPLEX'(1.0, 0.0);
265
constant CBASE_j: complex := COMPLEX'(0.0, 1.0);
266
constant CZERO: complex := COMPLEX'(0.0, 0.0);
268
function CABS(Z: in complex ) return real;
269
-- returns absolute value (magnitude) of Z
271
function CARG(Z: in complex ) return real;
272
-- returns argument (angle) in radians of a complex number
274
function CMPLX(X: in real; Y: in real:= 0.0 ) return complex;
275
-- returns complex number X + iY
277
function "-" (Z: in complex ) return complex;
280
function "-" (Z: in complex_polar ) return complex_polar;
283
function CONJ (Z: in complex) return complex;
284
-- returns complex conjugate
286
function CONJ (Z: in complex_polar) return complex_polar;
287
-- returns complex conjugate
289
function CSQRT(Z: in complex ) return complex_vector;
290
-- returns square root of Z; 2 values
292
function CEXP(Z: in complex ) return complex;
295
function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar;
296
-- converts complex to complex_polar
298
function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex;
299
-- converts complex_polar to complex
302
-- arithmetic operators
304
function "+" ( L: in complex; R: in complex ) return complex;
305
function "+" ( L: in complex_polar; R: in complex_polar) return complex;
306
function "+" ( L: in complex_polar; R: in complex ) return complex;
307
function "+" ( L: in complex; R: in complex_polar) return complex;
308
function "+" ( L: in real; R: in complex ) return complex;
309
function "+" ( L: in complex; R: in real ) return complex;
310
function "+" ( L: in real; R: in complex_polar) return complex;
311
function "+" ( L: in complex_polar; R: in real) return complex;
313
function "-" ( L: in complex; R: in complex ) return complex;
314
function "-" ( L: in complex_polar; R: in complex_polar) return complex;
315
function "-" ( L: in complex_polar; R: in complex ) return complex;
316
function "-" ( L: in complex; R: in complex_polar) return complex;
317
function "-" ( L: in real; R: in complex ) return complex;
318
function "-" ( L: in complex; R: in real ) return complex;
319
function "-" ( L: in real; R: in complex_polar) return complex;
320
function "-" ( L: in complex_polar; R: in real) return complex;
322
function "*" ( L: in complex; R: in complex ) return complex;
323
function "*" ( L: in complex_polar; R: in complex_polar) return complex;
324
function "*" ( L: in complex_polar; R: in complex ) return complex;
325
function "*" ( L: in complex; R: in complex_polar) return complex;
326
function "*" ( L: in real; R: in complex ) return complex;
327
function "*" ( L: in complex; R: in real ) return complex;
328
function "*" ( L: in real; R: in complex_polar) return complex;
329
function "*" ( L: in complex_polar; R: in real) return complex;
332
function "/" ( L: in complex; R: in complex ) return complex;
333
function "/" ( L: in complex_polar; R: in complex_polar) return complex;
334
function "/" ( L: in complex_polar; R: in complex ) return complex;
335
function "/" ( L: in complex; R: in complex_polar) return complex;
336
function "/" ( L: in real; R: in complex ) return complex;
337
function "/" ( L: in complex; R: in real ) return complex;
338
function "/" ( L: in real; R: in complex_polar) return complex;
339
function "/" ( L: in complex_polar; R: in real) return complex;
344
---------------------------------------------------------------
346
-- This source file may be used and distributed without restriction.
347
-- No declarations or definitions shall be added to this package.
348
-- This package cannot be sold or distributed for profit.
350
-- ****************************************************************
354
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
356
-- ****************************************************************
358
-- Title: PACKAGE BODY MATH_REAL
360
-- Library: This package shall be compiled into a library
361
-- symbolically named IEEE.
363
-- Purpose: VHDL declarations for mathematical package MATH_REAL
364
-- which contains common real constants, common real
365
-- functions, and real trascendental functions.
367
-- Author: IEEE VHDL Math Package Study Group
370
-- The package body shall be considered the formal definition of
371
-- the semantics of this package. Tool developers may choose to implement
372
-- the package body in the most efficient manner available to them.
374
-- Source code and algorithms for this package body comes from the
375
-- following sources:
376
-- IEEE VHDL Math Package Study Group participants,
377
-- U. of Mississippi, Mentor Graphics, Synopsys,
378
-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol
379
-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable
380
-- Random Number Generators), Handbook of Mathematical Functions
381
-- by Milton Abramowitz and Irene A. Stegun (Dover).
384
-- Version 0.1 Jose A. Torres 4/23/93 First draft
385
-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code
386
-------------------------------------------------------------
389
Package body MATH_REAL is
392
-- some constants for use in the package body only
394
constant Q_PI : real := MATH_PI/4.0;
395
constant HALF_PI : real := MATH_PI/2.0;
396
constant TWO_PI : real := MATH_PI*2.0;
397
constant MAX_ITER: integer := 27; -- max precision factor for cordic
400
-- some type declarations for cordic operations
403
constant KC : REAL := 6.0725293500888142e-01; -- constant for cordic
404
type REAL_VECTOR is array (NATURAL range <>) of REAL;
405
type NATURAL_VECTOR is array (NATURAL range <>) of NATURAL;
406
subtype REAL_VECTOR_N is REAL_VECTOR (0 to max_iter);
407
subtype REAL_ARR_2 is REAL_VECTOR (0 to 1);
408
subtype REAL_ARR_3 is REAL_VECTOR (0 to 2);
409
subtype QUADRANT is INTEGER range 0 to 3;
410
type CORDIC_MODE_TYPE is (ROTATION, VECTORING);
413
-- auxiliary functions for cordic algorithms
415
function POWER_OF_2_SERIES (d : NATURAL_VECTOR; initial_value : REAL;
416
number_of_values : NATURAL) return REAL_VECTOR is
418
variable v : REAL_VECTOR (0 to number_of_values);
419
variable temp : REAL := initial_value;
420
variable flag : boolean := true;
422
for i in 0 to number_of_values loop
424
for p in d'range loop
435
end POWER_OF_2_SERIES;
438
constant two_at_minus : REAL_VECTOR := POWER_OF_2_SERIES(
439
NATURAL_VECTOR'(100, 90),1.0,
442
constant epsilon : REAL_VECTOR_N := (
443
7.8539816339744827e-01,
444
4.6364760900080606e-01,
445
2.4497866312686413e-01,
446
1.2435499454676144e-01,
447
6.2418809995957351e-02,
448
3.1239833430268277e-02,
449
1.5623728620476830e-02,
450
7.8123410601011116e-03,
451
3.9062301319669717e-03,
452
1.9531225164788189e-03,
453
9.7656218955931937e-04,
454
4.8828121119489829e-04,
455
2.4414062014936175e-04,
456
1.2207031189367021e-04,
457
6.1035156174208768e-05,
458
3.0517578115526093e-05,
459
1.5258789061315760e-05,
460
7.6293945311019699e-06,
461
3.8146972656064960e-06,
462
1.9073486328101870e-06,
463
9.5367431640596080e-07,
464
4.7683715820308876e-07,
465
2.3841857910155801e-07,
466
1.1920928955078067e-07,
467
5.9604644775390553e-08,
468
2.9802322387695303e-08,
469
1.4901161193847654e-08,
470
7.4505805969238281e-09
473
function CORDIC ( x0 : REAL;
476
n : NATURAL; -- precision factor
477
CORDIC_MODE : CORDIC_MODE_TYPE -- rotation (z -> 0)
478
-- or vectoring (y -> 0)
479
) return REAL_ARR_3 is
480
variable x : REAL := x0;
481
variable y : REAL := y0;
482
variable z : REAL := z0;
483
variable x_temp : REAL;
485
if CORDIC_MODE = ROTATION then
489
x := x - y * two_at_minus(k);
490
y := y + x_temp * two_at_minus(k);
493
x := x + y * two_at_minus(k);
494
y := y - x_temp * two_at_minus(k);
502
x := x - y * two_at_minus(k);
503
y := y + x_temp * two_at_minus(k);
506
x := x + y * two_at_minus(k);
507
y := y - x_temp * two_at_minus(k);
512
return REAL_ARR_3'(x, y, z);
516
-- non-trascendental functions
518
function SIGN (X: real ) return real is
519
-- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0
523
elsif ( X < 0.0 ) then
530
function CEIL (X : real ) return real is
531
-- returns smallest integer value (as real) not less than X
532
-- No conversion to an integer type is expected, so truncate cannot
533
-- overflow for large arguments.
535
variable large: real := 1073741824.0;
536
type long is range -1073741824 to 1073741824;
537
-- 2**30 is longer than any single-precision mantissa
541
if abs( X) >= large then
544
rd := real ( long( X));
563
function FLOOR (X : real ) return real is
564
-- returns largest integer value (as real) not greater than X
565
-- No conversion to an integer type is expected, so truncate
566
-- cannot overflow for large arguments.
568
variable large: real := 1073741824.0;
569
type long is range -1073741824 to 1073741824;
570
-- 2**30 is longer than any single-precision mantissa
574
if abs( X ) >= large then
577
rd := real ( long( X));
596
function ROUND (X : real ) return real is
597
-- returns integer FLOOR(X + 0.5) if X > 0;
598
-- return integer CEIL(X - 0.5) if X < 0
601
return FLOOR(X + 0.5);
603
return CEIL( X - 0.5);
609
function FMAX (X, Y : real ) return real is
610
-- returns the algebraically larger of X and Y
619
function FMIN (X, Y : real ) return real is
620
-- returns the algebraically smaller of X and Y
630
-- Pseudo-random number generators
633
procedure UNIFORM(variable Seed1,Seed2:inout integer;variable X:out real) is
634
-- returns a pseudo-random number with uniform distribution in the
635
-- interval (0.0, 1.0).
636
-- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must
637
-- be initialized to values in the range [1, 2147483562] and
638
-- [1, 2147483398] respectively. The seed values are modified after
639
-- each call to UNIFORM.
640
-- This random number generator is portable for 32-bit computers, and
641
-- it has period ~2.30584*(10**18) for each set of seed values.
643
-- For VHDL-1992, the seeds will be global variables, functions to
644
-- initialize their values (INIT_SEED) will be provided, and the UNIFORM
645
-- procedure call will be modified accordingly.
647
variable z, k: integer;
650
Seed1 := 40014 * (Seed1 - k * 53668) - k * 12211;
653
Seed1 := Seed1 + 2147483563;
658
Seed2 := 40692 * (Seed2 - k * 52774) - k * 3791;
661
Seed2 := Seed2 + 2147483399;
669
X := REAL(Z)*4.656613e-10;
673
function SRAND (seed: in integer ) return integer is
675
-- sets value of seed for sequence of
676
-- pseudo-random numbers.
677
-- Returns the value of the seed.
678
-- It uses the foreign native C function srand().
682
function RAND return integer is
684
-- returns an integer pseudo-random number with uniform distribution.
685
-- It uses the foreign native C function rand().
686
-- Seed for the sequence is initialized with the
687
-- SRAND() function and value of the seed is changed every
688
-- time SRAND() is called, but it is not visible.
689
-- The range of generated values is platform dependent.
693
function GET_RAND_MAX return integer is
695
-- returns the upper bound of the range of the
696
-- pseudo-random numbers generated by RAND().
697
-- The support for this function is platform dependent, and
698
-- it uses foreign native C functions or constants.
699
-- It may not be available in some platforms.
700
-- Note: the value of (RAND / GET_RAND_MAX) is a
701
-- pseudo-random number distributed between 0 & 1.
706
-- trascendental and trigonometric functions
709
function SQRT (X : real ) return real is
710
-- returns square root of X; X >= 0
712
-- Computes square root using the Newton-Raphson approximation:
713
-- F(n+1) = 0.5*[F(n) + x/F(n)];
716
constant inival: real := 1.5;
717
constant eps : real := 0.000001;
718
constant relative_err : real := eps*X;
720
variable oldval : real ;
721
variable newval : real ;
724
-- check validity of argument
726
assert false report "X < 0 in SQRT(X)"
731
-- get the square root for special cases
736
return 1.0; -- return exact value
740
-- get the square root for general cases
742
newval := (X/oldval + oldval)/2.0;
744
while ( abs(newval -oldval) > relative_err ) loop
746
newval := (X/oldval + oldval)/2.0;
752
function CBRT (X : real ) return real is
753
-- returns cube root of X
754
-- Computes square root using the Newton-Raphson approximation:
755
-- F(n+1) = (1/3)*[2*F(n) + x/F(n)**2];
758
constant inival: real := 1.5;
759
constant eps : real := 0.000001;
760
constant relative_err : real := eps*abs(X);
762
variable xlocal : real := X;
763
variable negative : boolean := X < 0.0;
764
variable oldval : real ;
765
variable newval : real ;
769
-- compute root for special cases
772
elsif ( X = 1.0 ) then
780
-- compute root for general cases
786
newval := (xlocal/(oldval*oldval) + 2.0*oldval)/3.0;
788
while ( abs(newval -oldval) > relative_err ) loop
790
newval :=(xlocal/(oldval*oldval) + 2.0*oldval)/3.0;
801
function "**" (X : integer; Y : real) return real is
802
-- returns Y power of X ==> X**Y;
803
-- error if X = 0 and Y <= 0.0
804
-- error if X < 0 and Y does not have an integer value
806
-- check validity of argument
807
if ( X = 0 ) and ( Y <= 0.0 ) then
808
assert false report "X = 0 and Y <= 0.0 in X**Y"
813
if ( X < 0 ) and ( Y /= REAL(INTEGER(Y)) ) then
814
assert false report "X < 0 and Y \= integer in X**Y"
819
-- compute the result
820
return EXP (Y * LOG (REAL(X)));
823
function "**" (X : real; Y : real) return real is
824
-- returns Y power of X ==> X**Y;
825
-- error if X = 0.0 and Y <= 0.0
826
-- error if X < 0.0 and Y does not have an integer value
828
-- check validity of argument
829
if ( X = 0.0 ) and ( Y <= 0.0 ) then
830
assert false report "X = 0.0 and Y <= 0.0 in X**Y"
835
if ( X < 0.0 ) and ( Y /= REAL(INTEGER(Y)) ) then
836
assert false report "X < 0.0 and Y \= integer in X**Y"
841
-- compute the result
842
return EXP (Y * LOG (X));
845
function EXP (X : real ) return real is
846
-- returns e**X; where e = MATH_E
848
-- This function computes the exponential using the following series:
849
-- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; x > 0
851
constant eps : real := 0.000001; -- precision criteria
853
variable reciprocal: boolean := x < 0.0;-- check sign of argument
854
variable xlocal : real := abs(x); -- use positive value
855
variable oldval: real ; -- following variables are
856
variable num: real ; -- used for series evaluation
857
variable count: integer ;
858
variable denom: real ;
859
variable newval: real ;
862
-- compute value for special cases
871
-- compute value for general cases
876
newval:= oldval + num/denom;
878
while ( abs(newval - oldval) > eps ) loop
882
denom := denom*(real(count));
883
newval := oldval + num/denom;
887
newval := 1.0/newval;
894
function LOG (X : real ) return real is
895
-- returns natural logarithm of X; X > 0
897
-- This function computes the exponential using the following series:
898
-- log(x) = 2[ (x-1)/(x+1) + (((x-1)/(x+1))**3)/3.0 + ...] ; x > 0
901
constant eps : real := 0.000001; -- precision criteria
903
variable xlocal: real ; -- following variables are
904
variable oldval: real ; -- used to evaluate the series
905
variable xlocalsqr: real ;
906
variable factor : real ;
907
variable count: integer ;
908
variable newval: real ;
911
-- check validity of argument
913
assert false report "X <= 0 in LOG(X)"
918
-- compute value for special cases
922
if ( X = MATH_E ) then
927
-- compute value for general cases
928
xlocal := (X - 1.0)/(X + 1.0);
930
xlocalsqr := xlocal*xlocal;
931
factor := xlocal*xlocalsqr;
933
newval := oldval + (factor/real(count));
935
while ( abs(newval - oldval) > eps ) loop
938
factor := factor * xlocalsqr;
939
newval := oldval + factor/real(count);
942
newval := newval * 2.0;
946
function LOG (BASE: positive; X : real) return real is
947
-- returns logarithm base BASE of X; X > 0
949
-- check validity of argument
950
if ( BASE <= 0 ) or ( x <= 0.0 ) then
951
assert false report "BASE <= 0 or X <= 0.0 in LOG(BASE, X)"
957
return ( LOG(X)/LOG(REAL(BASE)));
960
function SIN (X : real ) return real is
961
-- returns sin X; X in radians
962
variable n : INTEGER;
964
if (x < 1.6 ) and (x > -1.6) then
965
return CORDIC( KC, 0.0, x, 27, ROTATION)(1);
968
n := INTEGER( x / HALF_PI );
969
case QUADRANT( n mod 4 ) is
971
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
973
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
975
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
977
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
982
function COS (x : REAL) return REAL is
983
-- returns cos X; X in radians
984
variable n : INTEGER;
986
if (x < 1.6 ) and (x > -1.6) then
987
return CORDIC( KC, 0.0, x, 27, ROTATION)(0);
990
n := INTEGER( x / HALF_PI );
991
case QUADRANT( n mod 4 ) is
993
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
995
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
997
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
999
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
1003
function TAN (x : REAL) return REAL is
1004
-- returns tan X; X in radians
1005
-- X /= ((2k+1) * PI/2), where k is an integer
1006
variable n : INTEGER := INTEGER( x / HALF_PI );
1007
variable v : REAL_ARR_3 :=
1008
CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION);
1017
function ASIN (x : real ) return real is
1018
-- returns -PI/2 < asin X < PI/2; | X | <= 1
1021
assert false report "Out of range parameter passed to ASIN"
1024
elsif abs x < 0.9 then
1025
return atan(x/(sqrt(1.0 - x*x)));
1027
return HALF_PI - atan(sqrt(1.0 - x*x)/x);
1029
return - HALF_PI + atan((sqrt(1.0 - x*x))/x);
1033
function ACOS (x : REAL) return REAL is
1034
-- returns 0 < acos X < PI; | X | <= 1
1037
assert false report "Out of range parameter passed to ACOS"
1040
elsif abs x > 0.9 then
1042
return atan(sqrt(1.0 - x*x)/x);
1044
return MATH_PI - atan(sqrt(1.0 - x*x)/x);
1047
return HALF_PI - atan(x/sqrt(1.0 - x*x));
1051
function ATAN (x : REAL) return REAL is
1052
-- returns -PI/2 < atan X < PI/2
1054
return CORDIC( 1.0, x, 0.0, 27, VECTORING )(2);
1057
function ATAN2 (x : REAL; y : REAL) return REAL is
1058
-- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0
1062
assert false report "atan2(0.0, 0.0) is undetermined, returned 0,0"
1071
return CORDIC( x, y, 0.0, 27, VECTORING )(2);
1073
return MATH_PI + CORDIC( x, y, 0.0, 27, VECTORING )(2);
1078
function SINH (X : real) return real is
1079
-- hyperbolic sine; returns (e**X - e**(-X))/2
1081
return ( (EXP(X) - EXP(-X))/2.0 );
1084
function COSH (X : real) return real is
1085
-- hyperbolic cosine; returns (e**X + e**(-X))/2
1087
return ( (EXP(X) + EXP(-X))/2.0 );
1090
function TANH (X : real) return real is
1091
-- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X))
1093
return ( (EXP(X) - EXP(-X))/(EXP(X) + EXP(-X)) );
1096
function ASINH (X : real) return real is
1097
-- returns ln( X + sqrt( X**2 + 1))
1099
return ( LOG( X + SQRT( X**2 + 1.0)) );
1102
function ACOSH (X : real) return real is
1103
-- returns ln( X + sqrt( X**2 - 1)); X >= 1
1105
if abs x >= 1.0 then
1106
assert false report "Out of range parameter passed to ACOSH"
1111
return ( LOG( X + SQRT( X**2 - 1.0)) );
1114
function ATANH (X : real) return real is
1115
-- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1
1118
assert false report "Out of range parameter passed to ATANH"
1123
return( LOG( (1.0+X)/(1.0-X) )/2.0 );
1130
---------------------------------------------------------------
1132
-- This source file may be used and distributed without restriction.
1133
-- No declarations or definitions shall be included in this package.
1134
-- This package cannot be sold or distributed for profit.
1136
-- ****************************************************************
1138
-- * W A R N I N G *
1140
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
1142
-- ****************************************************************
1144
-- Title: PACKAGE BODY MATH_COMPLEX
1146
-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX
1147
-- which contains common complex constants and basic complex
1148
-- functions and operations.
1150
-- Author: IEEE VHDL Math Package Study Group
1153
-- The package body uses package IEEE.MATH_REAL
1155
-- The package body shall be considered the formal definition of
1156
-- the semantics of this package. Tool developers may choose to implement
1157
-- the package body in the most efficient manner available to them.
1159
-- Source code for this package body comes from the following
1160
-- following sources:
1161
-- IEEE VHDL Math Package Study Group participants,
1162
-- U. of Mississippi, Mentor Graphics, Synopsys,
1163
-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol
1164
-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable
1165
-- Random Number Generators, Handbook of Mathematical Functions
1166
-- by Milton Abramowitz and Irene A. Stegun (Dover).
1169
-- Version 0.1 Jose A. Torres 4/23/93 First draft
1170
-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code
1172
-------------------------------------------------------------
1175
Use IEEE.MATH_REAL.all; -- real trascendental operations
1177
Package body MATH_COMPLEX is
1179
function CABS(Z: in complex ) return real is
1180
-- returns absolute value (magnitude) of Z
1181
variable ztemp : complex_polar;
1183
ztemp := COMPLEX_TO_POLAR(Z);
1187
function CARG(Z: in complex ) return real is
1188
-- returns argument (angle) in radians of a complex number
1189
variable ztemp : complex_polar;
1191
ztemp := COMPLEX_TO_POLAR(Z);
1195
function CMPLX(X: in real; Y: in real := 0.0 ) return complex is
1196
-- returns complex number X + iY
1198
return COMPLEX'(X, Y);
1201
function "-" (Z: in complex ) return complex is
1202
-- unary minus; returns -x -jy for z= x + jy
1204
return COMPLEX'(-z.Re, -z.Im);
1207
function "-" (Z: in complex_polar ) return complex_polar is
1208
-- unary minus; returns (z.mag, z.arg + MATH_PI)
1210
return COMPLEX_POLAR'(z.mag, z.arg + MATH_PI);
1213
function CONJ (Z: in complex) return complex is
1214
-- returns complex conjugate (x-jy for z = x+ jy)
1216
return COMPLEX'(z.Re, -z.Im);
1219
function CONJ (Z: in complex_polar) return complex_polar is
1220
-- returns complex conjugate (z.mag, -z.arg)
1222
return COMPLEX_POLAR'(z.mag, -z.arg);
1225
function CSQRT(Z: in complex ) return complex_vector is
1226
-- returns square root of Z; 2 values
1227
variable ztemp : complex_polar;
1228
variable zout : complex_vector (0 to 1);
1229
variable temp : real;
1231
ztemp := COMPLEX_TO_POLAR(Z);
1232
temp := SQRT(ztemp.mag);
1233
zout(0).re := temp*COS(ztemp.arg/2.0);
1234
zout(0).im := temp*SIN(ztemp.arg/2.0);
1236
zout(1).re := temp*COS(ztemp.arg/2.0 + MATH_PI);
1237
zout(1).im := temp*SIN(ztemp.arg/2.0 + MATH_PI);
1242
function CEXP(Z: in complex ) return complex is
1245
return COMPLEX'(EXP(Z.re)*COS(Z.im), EXP(Z.re)*SIN(Z.im));
1248
function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar is
1249
-- converts complex to complex_polar
1251
return COMPLEX_POLAR'(sqrt(z.re**2 + z.im**2),atan2(z.re,z.im));
1252
end COMPLEX_TO_POLAR;
1254
function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex is
1255
-- converts complex_polar to complex
1257
return COMPLEX'( z.mag*cos(z.arg), z.mag*sin(z.arg) );
1258
end POLAR_TO_COMPLEX;
1262
-- arithmetic operators
1265
function "+" ( L: in complex; R: in complex ) return complex is
1267
return COMPLEX'(L.Re + R.Re, L.Im + R.Im);
1270
function "+" (L: in complex_polar; R: in complex_polar) return complex is
1271
variable zL, zR : complex;
1273
zL := POLAR_TO_COMPLEX( L );
1274
zR := POLAR_TO_COMPLEX( R );
1275
return COMPLEX'(zL.Re + zR.Re, zL.Im + zR.Im);
1278
function "+" ( L: in complex_polar; R: in complex ) return complex is
1279
variable zL : complex;
1281
zL := POLAR_TO_COMPLEX( L );
1282
return COMPLEX'(zL.Re + R.Re, zL.Im + R.Im);
1285
function "+" ( L: in complex; R: in complex_polar) return complex is
1286
variable zR : complex;
1288
zR := POLAR_TO_COMPLEX( R );
1289
return COMPLEX'(L.Re + zR.Re, L.Im + zR.Im);
1292
function "+" ( L: in real; R: in complex ) return complex is
1294
return COMPLEX'(L + R.Re, R.Im);
1297
function "+" ( L: in complex; R: in real ) return complex is
1299
return COMPLEX'(L.Re + R, L.Im);
1302
function "+" ( L: in real; R: in complex_polar) return complex is
1303
variable zR : complex;
1305
zR := POLAR_TO_COMPLEX( R );
1306
return COMPLEX'(L + zR.Re, zR.Im);
1309
function "+" ( L: in complex_polar; R: in real) return complex is
1310
variable zL : complex;
1312
zL := POLAR_TO_COMPLEX( L );
1313
return COMPLEX'(zL.Re + R, zL.Im);
1316
function "-" ( L: in complex; R: in complex ) return complex is
1318
return COMPLEX'(L.Re - R.Re, L.Im - R.Im);
1321
function "-" ( L: in complex_polar; R: in complex_polar) return complex is
1322
variable zL, zR : complex;
1324
zL := POLAR_TO_COMPLEX( L );
1325
zR := POLAR_TO_COMPLEX( R );
1326
return COMPLEX'(zL.Re - zR.Re, zL.Im - zR.Im);
1329
function "-" ( L: in complex_polar; R: in complex ) return complex is
1330
variable zL : complex;
1332
zL := POLAR_TO_COMPLEX( L );
1333
return COMPLEX'(zL.Re - R.Re, zL.Im - R.Im);
1336
function "-" ( L: in complex; R: in complex_polar) return complex is
1337
variable zR : complex;
1339
zR := POLAR_TO_COMPLEX( R );
1340
return COMPLEX'(L.Re - zR.Re, L.Im - zR.Im);
1343
function "-" ( L: in real; R: in complex ) return complex is
1345
return COMPLEX'(L - R.Re, -1.0 * R.Im);
1348
function "-" ( L: in complex; R: in real ) return complex is
1350
return COMPLEX'(L.Re - R, L.Im);
1353
function "-" ( L: in real; R: in complex_polar) return complex is
1354
variable zR : complex;
1356
zR := POLAR_TO_COMPLEX( R );
1357
return COMPLEX'(L - zR.Re, -1.0*zR.Im);
1360
function "-" ( L: in complex_polar; R: in real) return complex is
1361
variable zL : complex;
1363
zL := POLAR_TO_COMPLEX( L );
1364
return COMPLEX'(zL.Re - R, zL.Im);
1367
function "*" ( L: in complex; R: in complex ) return complex is
1369
return COMPLEX'(L.Re * R.Re - L.Im * R.Im, L.Re * R.Im + L.Im * R.Re);
1372
function "*" ( L: in complex_polar; R: in complex_polar) return complex is
1373
variable zout : complex_polar;
1375
zout.mag := L.mag * R.mag;
1376
zout.arg := L.arg + R.arg;
1377
return POLAR_TO_COMPLEX(zout);
1380
function "*" ( L: in complex_polar; R: in complex ) return complex is
1381
variable zL : complex;
1383
zL := POLAR_TO_COMPLEX( L );
1384
return COMPLEX'(zL.Re*R.Re - zL.Im * R.Im, zL.Re * R.Im + zL.Im*R.Re);
1387
function "*" ( L: in complex; R: in complex_polar) return complex is
1388
variable zR : complex;
1390
zR := POLAR_TO_COMPLEX( R );
1391
return COMPLEX'(L.Re*zR.Re - L.Im * zR.Im, L.Re * zR.Im + L.Im*zR.Re);
1394
function "*" ( L: in real; R: in complex ) return complex is
1396
return COMPLEX'(L * R.Re, L * R.Im);
1399
function "*" ( L: in complex; R: in real ) return complex is
1401
return COMPLEX'(L.Re * R, L.Im * R);
1404
function "*" ( L: in real; R: in complex_polar) return complex is
1405
variable zR : complex;
1407
zR := POLAR_TO_COMPLEX( R );
1408
return COMPLEX'(L * zR.Re, L * zR.Im);
1411
function "*" ( L: in complex_polar; R: in real) return complex is
1412
variable zL : complex;
1414
zL := POLAR_TO_COMPLEX( L );
1415
return COMPLEX'(zL.Re * R, zL.Im * R);
1418
function "/" ( L: in complex; R: in complex ) return complex is
1419
variable magrsq : REAL := R.Re ** 2 + R.Im ** 2;
1421
if (magrsq = 0.0) then
1422
assert FALSE report "Attempt to divide by (0,0)"
1424
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1426
return COMPLEX'( (L.Re * R.Re + L.Im * R.Im) / magrsq,
1427
(L.Im * R.Re - L.Re * R.Im) / magrsq);
1431
function "/" ( L: in complex_polar; R: in complex_polar) return complex is
1432
variable zout : complex_polar;
1434
if (R.mag = 0.0) then
1435
assert FALSE report "Attempt to divide by (0,0)"
1437
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1439
zout.mag := L.mag/R.mag;
1440
zout.arg := L.arg - R.arg;
1441
return POLAR_TO_COMPLEX(zout);
1445
function "/" ( L: in complex_polar; R: in complex ) return complex is
1446
variable zL : complex;
1447
variable temp : REAL := R.Re ** 2 + R.Im ** 2;
1449
if (temp = 0.0) then
1450
assert FALSE report "Attempt to divide by (0.0,0.0)"
1452
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1454
zL := POLAR_TO_COMPLEX( L );
1455
return COMPLEX'( (zL.Re * R.Re + zL.Im * R.Im) / temp,
1456
(zL.Im * R.Re - zL.Re * R.Im) / temp);
1460
function "/" ( L: in complex; R: in complex_polar) return complex is
1461
variable zR : complex := POLAR_TO_COMPLEX( R );
1462
variable temp : REAL := zR.Re ** 2 + zR.Im ** 2;
1464
if (R.mag = 0.0) or (temp = 0.0) then
1465
assert FALSE report "Attempt to divide by (0.0,0.0)"
1467
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1469
return COMPLEX'( (L.Re * zR.Re + L.Im * zR.Im) / temp,
1470
(L.Im * zR.Re - L.Re * zR.Im) / temp);
1474
function "/" ( L: in real; R: in complex ) return complex is
1475
variable temp : REAL := R.Re ** 2 + R.Im ** 2;
1477
if (temp = 0.0) then
1478
assert FALSE report "Attempt to divide by (0.0,0.0)"
1480
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1483
return COMPLEX'( temp * R.Re, -temp * R.Im );
1487
function "/" ( L: in complex; R: in real ) return complex is
1490
assert FALSE report "Attempt to divide by (0.0,0.0)"
1492
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1494
return COMPLEX'(L.Re / R, L.Im / R);
1498
function "/" ( L: in real; R: in complex_polar) return complex is
1499
variable zR : complex := POLAR_TO_COMPLEX( R );
1500
variable temp : REAL := zR.Re ** 2 + zR.Im ** 2;
1502
if (R.mag = 0.0) or (temp = 0.0) then
1503
assert FALSE report "Attempt to divide by (0.0,0.0)"
1505
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1508
return COMPLEX'( temp * zR.Re, -temp * zR.Im );
1512
function "/" ( L: in complex_polar; R: in real) return complex is
1513
variable zL : complex := POLAR_TO_COMPLEX( L );
1516
assert FALSE report "Attempt to divide by (0.0,0.0)"
1518
return COMPLEX'(REAL'RIGHT, REAL'RIGHT);
1520
return COMPLEX'(zL.Re / R, zL.Im / R);