]> www.ginac.de Git - cln.git/blob - src/complex/misc/cl_C_expt_I.cc
35b35f806b3b55c4418efd2ba22afc6e99b4722d
[cln.git] / src / complex / misc / cl_C_expt_I.cc
1 // expt().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_complex.h"
8
9
10 // Implementation.
11
12 #include "cl_C.h"
13 #include "cl_real.h"
14 #include "cl_I.h"
15
16 // Methode:
17 // Für y>0:
18 //   a:=x, b:=y.
19 //   Solange b gerade, setze a:=a*a, b:=b/2. [a^b bleibt invariant, = x^y.]
20 //   c:=a.
21 //   Solange b:=floor(b/2) >0 ist,
22 //     setze a:=a*a, und falls b ungerade, setze c:=a*c.
23 //   Ergebnis c.
24 // Für y=0: Ergebnis 1.
25 // Für y<0: (/ (expt x (- y))).
26
27 // Assume y>0.
28 inline const cl_N expt_pos (const cl_N& x, const cl_I& y)
29 {
30         var cl_N a = x;
31         var cl_I b = y;
32         while (!oddp(b)) { a = square(a); b = b >> 1; }
33         var cl_N c = a;
34         until (eq(b,1))
35           { b = b >> 1;
36             a = square(a);
37             if (oddp(b)) { c = a * c; }
38           }
39         return c;
40 }
41
42 const cl_N expt (const cl_N& x, const cl_I& y)
43 {
44         if (realp(x)) {
45                 DeclareType(cl_R,x);
46                 // x reell -> schnellere Routine
47                 return expt(x,y);
48         }
49         if (eq(y,0)) { return 1; } // y=0 -> Ergebnis 1
50         var cl_boolean y_negative = minusp(y);
51         var cl_I abs_y = (y_negative ? -y : y); // Betrag von y nehmen
52         var cl_N z = expt_pos(x,abs_y); // (expt x (abs y))
53         return (y_negative ? recip(z) : z); // evtl. noch Kehrwert nehmen
54 }