Add an UNSPEC_PROLOGUE_USE to prevent the link register from being considered dead.
[official-gcc.git] / gcc / ada / a-ngcefu.adb
blobd6cde0cd564ce447ef535753cca0aea7a8175641
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUNTIME COMPONENTS --
4 -- --
5 -- ADA.NUMERICS.GENERIC_COMPLEX_ELEMENTARY_FUNCTIONS --
6 -- --
7 -- B o d y --
8 -- --
9 -- --
10 -- Copyright (C) 1992-2001 Free Software Foundation, Inc.
11 -- --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 2, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING. If not, write --
20 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
21 -- MA 02111-1307, USA. --
22 -- --
23 -- As a special exception, if other files instantiate generics from this --
24 -- unit, or you link this unit with other files to produce an executable, --
25 -- this unit does not by itself cause the resulting executable to be --
26 -- covered by the GNU General Public License. This exception does not --
27 -- however invalidate any other reasons why the executable file might be --
28 -- covered by the GNU Public License. --
29 -- --
30 -- GNAT was originally developed by the GNAT team at New York University. --
31 -- Extensive contributions were provided by Ada Core Technologies Inc. --
32 -- --
33 ------------------------------------------------------------------------------
35 with Ada.Numerics.Generic_Elementary_Functions;
37 package body Ada.Numerics.Generic_Complex_Elementary_Functions is
39 package Elementary_Functions is new
40 Ada.Numerics.Generic_Elementary_Functions (Real'Base);
41 use Elementary_Functions;
43 PI : constant := 3.14159_26535_89793_23846_26433_83279_50288_41971;
44 PI_2 : constant := PI / 2.0;
45 Sqrt_Two : constant := 1.41421_35623_73095_04880_16887_24209_69807_85696;
46 Log_Two : constant := 0.69314_71805_59945_30941_72321_21458_17656_80755;
48 subtype T is Real'Base;
50 Epsilon : constant T := 2.0 ** (1 - T'Model_Mantissa);
51 Square_Root_Epsilon : constant T := Sqrt_Two ** (1 - T'Model_Mantissa);
52 Inv_Square_Root_Epsilon : constant T := Sqrt_Two ** (T'Model_Mantissa - 1);
53 Root_Root_Epsilon : constant T := Sqrt_Two **
54 ((1 - T'Model_Mantissa) / 2);
55 Log_Inverse_Epsilon_2 : constant T := T (T'Model_Mantissa - 1) / 2.0;
57 Complex_Zero : constant Complex := (0.0, 0.0);
58 Complex_One : constant Complex := (1.0, 0.0);
59 Complex_I : constant Complex := (0.0, 1.0);
60 Half_Pi : constant Complex := (PI_2, 0.0);
62 --------
63 -- ** --
64 --------
66 function "**" (Left : Complex; Right : Complex) return Complex is
67 begin
68 if Re (Right) = 0.0
69 and then Im (Right) = 0.0
70 and then Re (Left) = 0.0
71 and then Im (Left) = 0.0
72 then
73 raise Argument_Error;
75 elsif Re (Left) = 0.0
76 and then Im (Left) = 0.0
77 and then Re (Right) < 0.0
78 then
79 raise Constraint_Error;
81 elsif Re (Left) = 0.0 and then Im (Left) = 0.0 then
82 return Left;
84 elsif Right = (0.0, 0.0) then
85 return Complex_One;
87 elsif Re (Right) = 0.0 and then Im (Right) = 0.0 then
88 return 1.0 + Right;
90 elsif Re (Right) = 1.0 and then Im (Right) = 0.0 then
91 return Left;
93 else
94 return Exp (Right * Log (Left));
95 end if;
96 end "**";
98 function "**" (Left : Real'Base; Right : Complex) return Complex is
99 begin
100 if Re (Right) = 0.0 and then Im (Right) = 0.0 and then Left = 0.0 then
101 raise Argument_Error;
103 elsif Left = 0.0 and then Re (Right) < 0.0 then
104 raise Constraint_Error;
106 elsif Left = 0.0 then
107 return Compose_From_Cartesian (Left, 0.0);
109 elsif Re (Right) = 0.0 and then Im (Right) = 0.0 then
110 return Complex_One;
112 elsif Re (Right) = 1.0 and then Im (Right) = 0.0 then
113 return Compose_From_Cartesian (Left, 0.0);
115 else
116 return Exp (Log (Left) * Right);
117 end if;
118 end "**";
120 function "**" (Left : Complex; Right : Real'Base) return Complex is
121 begin
122 if Right = 0.0
123 and then Re (Left) = 0.0
124 and then Im (Left) = 0.0
125 then
126 raise Argument_Error;
128 elsif Re (Left) = 0.0
129 and then Im (Left) = 0.0
130 and then Right < 0.0
131 then
132 raise Constraint_Error;
134 elsif Re (Left) = 0.0 and then Im (Left) = 0.0 then
135 return Left;
137 elsif Right = 0.0 then
138 return Complex_One;
140 elsif Right = 1.0 then
141 return Left;
143 else
144 return Exp (Right * Log (Left));
145 end if;
146 end "**";
148 ------------
149 -- Arccos --
150 ------------
152 function Arccos (X : Complex) return Complex is
153 Result : Complex;
155 begin
156 if X = Complex_One then
157 return Complex_Zero;
159 elsif abs Re (X) < Square_Root_Epsilon and then
160 abs Im (X) < Square_Root_Epsilon
161 then
162 return Half_Pi - X;
164 elsif abs Re (X) > Inv_Square_Root_Epsilon or else
165 abs Im (X) > Inv_Square_Root_Epsilon
166 then
167 return -2.0 * Complex_I * Log (Sqrt ((1.0 + X) / 2.0) +
168 Complex_I * Sqrt ((1.0 - X) / 2.0));
169 end if;
171 Result := -Complex_I * Log (X + Complex_I * Sqrt (1.0 - X * X));
173 if Im (X) = 0.0
174 and then abs Re (X) <= 1.00
175 then
176 Set_Im (Result, Im (X));
177 end if;
179 return Result;
180 end Arccos;
182 -------------
183 -- Arccosh --
184 -------------
186 function Arccosh (X : Complex) return Complex is
187 Result : Complex;
189 begin
190 if X = Complex_One then
191 return Complex_Zero;
193 elsif abs Re (X) < Square_Root_Epsilon and then
194 abs Im (X) < Square_Root_Epsilon
195 then
196 Result := Compose_From_Cartesian (-Im (X), -PI_2 + Re (X));
198 elsif abs Re (X) > Inv_Square_Root_Epsilon or else
199 abs Im (X) > Inv_Square_Root_Epsilon
200 then
201 Result := Log_Two + Log (X);
203 else
204 Result := 2.0 * Log (Sqrt ((1.0 + X) / 2.0) +
205 Sqrt ((X - 1.0) / 2.0));
206 end if;
208 if Re (Result) <= 0.0 then
209 Result := -Result;
210 end if;
212 return Result;
213 end Arccosh;
215 ------------
216 -- Arccot --
217 ------------
219 function Arccot (X : Complex) return Complex is
220 Xt : Complex;
222 begin
223 if abs Re (X) < Square_Root_Epsilon and then
224 abs Im (X) < Square_Root_Epsilon
225 then
226 return Half_Pi - X;
228 elsif abs Re (X) > 1.0 / Epsilon or else
229 abs Im (X) > 1.0 / Epsilon
230 then
231 Xt := Complex_One / X;
233 if Re (X) < 0.0 then
234 Set_Re (Xt, PI - Re (Xt));
235 return Xt;
236 else
237 return Xt;
238 end if;
239 end if;
241 Xt := Complex_I * Log ((X - Complex_I) / (X + Complex_I)) / 2.0;
243 if Re (Xt) < 0.0 then
244 Xt := PI + Xt;
245 end if;
247 return Xt;
248 end Arccot;
250 --------------
251 -- Arctcoth --
252 --------------
254 function Arccoth (X : Complex) return Complex is
255 R : Complex;
257 begin
258 if X = (0.0, 0.0) then
259 return Compose_From_Cartesian (0.0, PI_2);
261 elsif abs Re (X) < Square_Root_Epsilon
262 and then abs Im (X) < Square_Root_Epsilon
263 then
264 return PI_2 * Complex_I + X;
266 elsif abs Re (X) > 1.0 / Epsilon or else
267 abs Im (X) > 1.0 / Epsilon
268 then
269 if Im (X) > 0.0 then
270 return (0.0, 0.0);
271 else
272 return PI * Complex_I;
273 end if;
275 elsif Im (X) = 0.0 and then Re (X) = 1.0 then
276 raise Constraint_Error;
278 elsif Im (X) = 0.0 and then Re (X) = -1.0 then
279 raise Constraint_Error;
280 end if;
282 begin
283 R := Log ((1.0 + X) / (X - 1.0)) / 2.0;
285 exception
286 when Constraint_Error =>
287 R := (Log (1.0 + X) - Log (X - 1.0)) / 2.0;
288 end;
290 if Im (R) < 0.0 then
291 Set_Im (R, PI + Im (R));
292 end if;
294 if Re (X) = 0.0 then
295 Set_Re (R, Re (X));
296 end if;
298 return R;
299 end Arccoth;
301 ------------
302 -- Arcsin --
303 ------------
305 function Arcsin (X : Complex) return Complex is
306 Result : Complex;
308 begin
309 if abs Re (X) < Square_Root_Epsilon and then
310 abs Im (X) < Square_Root_Epsilon
311 then
312 return X;
314 elsif abs Re (X) > Inv_Square_Root_Epsilon or else
315 abs Im (X) > Inv_Square_Root_Epsilon
316 then
317 Result := -Complex_I * (Log (Complex_I * X) + Log (2.0 * Complex_I));
319 if Im (Result) > PI_2 then
320 Set_Im (Result, PI - Im (X));
322 elsif Im (Result) < -PI_2 then
323 Set_Im (Result, -(PI + Im (X)));
324 end if;
325 end if;
327 Result := -Complex_I * Log (Complex_I * X + Sqrt (1.0 - X * X));
329 if Re (X) = 0.0 then
330 Set_Re (Result, Re (X));
332 elsif Im (X) = 0.0
333 and then abs Re (X) <= 1.00
334 then
335 Set_Im (Result, Im (X));
336 end if;
338 return Result;
339 end Arcsin;
341 -------------
342 -- Arcsinh --
343 -------------
345 function Arcsinh (X : Complex) return Complex is
346 Result : Complex;
348 begin
349 if abs Re (X) < Square_Root_Epsilon and then
350 abs Im (X) < Square_Root_Epsilon
351 then
352 return X;
354 elsif abs Re (X) > Inv_Square_Root_Epsilon or else
355 abs Im (X) > Inv_Square_Root_Epsilon
356 then
357 Result := Log_Two + Log (X); -- may have wrong sign
359 if (Re (X) < 0.0 and Re (Result) > 0.0)
360 or else (Re (X) > 0.0 and Re (Result) < 0.0)
361 then
362 Set_Re (Result, -Re (Result));
363 end if;
365 return Result;
366 end if;
368 Result := Log (X + Sqrt (1.0 + X * X));
370 if Re (X) = 0.0 then
371 Set_Re (Result, Re (X));
372 elsif Im (X) = 0.0 then
373 Set_Im (Result, Im (X));
374 end if;
376 return Result;
377 end Arcsinh;
379 ------------
380 -- Arctan --
381 ------------
383 function Arctan (X : Complex) return Complex is
384 begin
385 if abs Re (X) < Square_Root_Epsilon and then
386 abs Im (X) < Square_Root_Epsilon
387 then
388 return X;
390 else
391 return -Complex_I * (Log (1.0 + Complex_I * X)
392 - Log (1.0 - Complex_I * X)) / 2.0;
393 end if;
394 end Arctan;
396 -------------
397 -- Arctanh --
398 -------------
400 function Arctanh (X : Complex) return Complex is
401 begin
402 if abs Re (X) < Square_Root_Epsilon and then
403 abs Im (X) < Square_Root_Epsilon
404 then
405 return X;
406 else
407 return (Log (1.0 + X) - Log (1.0 - X)) / 2.0;
408 end if;
409 end Arctanh;
411 ---------
412 -- Cos --
413 ---------
415 function Cos (X : Complex) return Complex is
416 begin
417 return
418 Compose_From_Cartesian
419 (Cos (Re (X)) * Cosh (Im (X)),
420 -Sin (Re (X)) * Sinh (Im (X)));
421 end Cos;
423 ----------
424 -- Cosh --
425 ----------
427 function Cosh (X : Complex) return Complex is
428 begin
429 return
430 Compose_From_Cartesian
431 (Cosh (Re (X)) * Cos (Im (X)),
432 Sinh (Re (X)) * Sin (Im (X)));
433 end Cosh;
435 ---------
436 -- Cot --
437 ---------
439 function Cot (X : Complex) return Complex is
440 begin
441 if abs Re (X) < Square_Root_Epsilon and then
442 abs Im (X) < Square_Root_Epsilon
443 then
444 return Complex_One / X;
446 elsif Im (X) > Log_Inverse_Epsilon_2 then
447 return -Complex_I;
449 elsif Im (X) < -Log_Inverse_Epsilon_2 then
450 return Complex_I;
451 end if;
453 return Cos (X) / Sin (X);
454 end Cot;
456 ----------
457 -- Coth --
458 ----------
460 function Coth (X : Complex) return Complex is
461 begin
462 if abs Re (X) < Square_Root_Epsilon and then
463 abs Im (X) < Square_Root_Epsilon
464 then
465 return Complex_One / X;
467 elsif Re (X) > Log_Inverse_Epsilon_2 then
468 return Complex_One;
470 elsif Re (X) < -Log_Inverse_Epsilon_2 then
471 return -Complex_One;
473 else
474 return Cosh (X) / Sinh (X);
475 end if;
476 end Coth;
478 ---------
479 -- Exp --
480 ---------
482 function Exp (X : Complex) return Complex is
483 EXP_RE_X : Real'Base := Exp (Re (X));
485 begin
486 return Compose_From_Cartesian (EXP_RE_X * Cos (Im (X)),
487 EXP_RE_X * Sin (Im (X)));
488 end Exp;
491 function Exp (X : Imaginary) return Complex is
492 ImX : Real'Base := Im (X);
494 begin
495 return Compose_From_Cartesian (Cos (ImX), Sin (ImX));
496 end Exp;
498 ---------
499 -- Log --
500 ---------
502 function Log (X : Complex) return Complex is
503 ReX : Real'Base;
504 ImX : Real'Base;
505 Z : Complex;
507 begin
508 if Re (X) = 0.0 and then Im (X) = 0.0 then
509 raise Constraint_Error;
511 elsif abs (1.0 - Re (X)) < Root_Root_Epsilon
512 and then abs Im (X) < Root_Root_Epsilon
513 then
514 Z := X;
515 Set_Re (Z, Re (Z) - 1.0);
517 return (1.0 - (1.0 / 2.0 -
518 (1.0 / 3.0 - (1.0 / 4.0) * Z) * Z) * Z) * Z;
519 end if;
521 begin
522 ReX := Log (Modulus (X));
524 exception
525 when Constraint_Error =>
526 ReX := Log (Modulus (X / 2.0)) - Log_Two;
527 end;
529 ImX := Arctan (Im (X), Re (X));
531 if ImX > PI then
532 ImX := ImX - 2.0 * PI;
533 end if;
535 return Compose_From_Cartesian (ReX, ImX);
536 end Log;
538 ---------
539 -- Sin --
540 ---------
542 function Sin (X : Complex) return Complex is
543 begin
544 if abs Re (X) < Square_Root_Epsilon and then
545 abs Im (X) < Square_Root_Epsilon then
546 return X;
547 end if;
549 return
550 Compose_From_Cartesian
551 (Sin (Re (X)) * Cosh (Im (X)),
552 Cos (Re (X)) * Sinh (Im (X)));
553 end Sin;
555 ----------
556 -- Sinh --
557 ----------
559 function Sinh (X : Complex) return Complex is
560 begin
561 if abs Re (X) < Square_Root_Epsilon and then
562 abs Im (X) < Square_Root_Epsilon
563 then
564 return X;
566 else
567 return Compose_From_Cartesian (Sinh (Re (X)) * Cos (Im (X)),
568 Cosh (Re (X)) * Sin (Im (X)));
569 end if;
570 end Sinh;
572 ----------
573 -- Sqrt --
574 ----------
576 function Sqrt (X : Complex) return Complex is
577 ReX : constant Real'Base := Re (X);
578 ImX : constant Real'Base := Im (X);
579 XR : constant Real'Base := abs Re (X);
580 YR : constant Real'Base := abs Im (X);
581 R : Real'Base;
582 R_X : Real'Base;
583 R_Y : Real'Base;
585 begin
586 -- Deal with pure real case, see (RM G.1.2(39))
588 if ImX = 0.0 then
589 if ReX > 0.0 then
590 return
591 Compose_From_Cartesian
592 (Sqrt (ReX), 0.0);
594 elsif ReX = 0.0 then
595 return X;
597 else
598 return
599 Compose_From_Cartesian
600 (0.0, Real'Copy_Sign (Sqrt (-ReX), ImX));
601 end if;
603 elsif ReX = 0.0 then
604 R_X := Sqrt (YR / 2.0);
606 if ImX > 0.0 then
607 return Compose_From_Cartesian (R_X, R_X);
608 else
609 return Compose_From_Cartesian (R_X, -R_X);
610 end if;
612 else
613 R := Sqrt (XR ** 2 + YR ** 2);
615 -- If the square of the modulus overflows, try rescaling the
616 -- real and imaginary parts. We cannot depend on an exception
617 -- being raised on all targets.
619 if R > Real'Base'Last then
620 raise Constraint_Error;
621 end if;
623 -- We are solving the system
625 -- XR = R_X ** 2 - Y_R ** 2 (1)
626 -- YR = 2.0 * R_X * R_Y (2)
628 -- The symmetric solution involves square roots for both R_X and
629 -- R_Y, but it is more accurate to use the square root with the
630 -- larger argument for either R_X or R_Y, and equation (2) for the
631 -- other.
633 if ReX < 0.0 then
634 R_Y := Sqrt (0.5 * (R - ReX));
635 R_X := YR / (2.0 * R_Y);
637 else
638 R_X := Sqrt (0.5 * (R + ReX));
639 R_Y := YR / (2.0 * R_X);
640 end if;
641 end if;
643 if Im (X) < 0.0 then -- halve angle, Sqrt of magnitude
644 R_Y := -R_Y;
645 end if;
646 return Compose_From_Cartesian (R_X, R_Y);
648 exception
649 when Constraint_Error =>
651 -- Rescale and try again.
653 R := Modulus (Compose_From_Cartesian (Re (X / 4.0), Im (X / 4.0)));
654 R_X := 2.0 * Sqrt (0.5 * R + 0.5 * Re (X / 4.0));
655 R_Y := 2.0 * Sqrt (0.5 * R - 0.5 * Re (X / 4.0));
657 if Im (X) < 0.0 then -- halve angle, Sqrt of magnitude
658 R_Y := -R_Y;
659 end if;
661 return Compose_From_Cartesian (R_X, R_Y);
662 end Sqrt;
664 ---------
665 -- Tan --
666 ---------
668 function Tan (X : Complex) return Complex is
669 begin
670 if abs Re (X) < Square_Root_Epsilon and then
671 abs Im (X) < Square_Root_Epsilon
672 then
673 return X;
675 elsif Im (X) > Log_Inverse_Epsilon_2 then
676 return Complex_I;
678 elsif Im (X) < -Log_Inverse_Epsilon_2 then
679 return -Complex_I;
681 else
682 return Sin (X) / Cos (X);
683 end if;
684 end Tan;
686 ----------
687 -- Tanh --
688 ----------
690 function Tanh (X : Complex) return Complex is
691 begin
692 if abs Re (X) < Square_Root_Epsilon and then
693 abs Im (X) < Square_Root_Epsilon
694 then
695 return X;
697 elsif Re (X) > Log_Inverse_Epsilon_2 then
698 return Complex_One;
700 elsif Re (X) < -Log_Inverse_Epsilon_2 then
701 return -Complex_One;
703 else
704 return Sinh (X) / Cosh (X);
705 end if;
706 end Tanh;
708 end Ada.Numerics.Generic_Complex_Elementary_Functions;