7 #include "cln/complex.h"
15 #include "cln/rational.h"
25 // Falls y=0: Ergebnis 1,
26 // [Nach CLTL folgendermaßen:
28 // x rational -> Fixnum 1
29 // x Float -> (float 1 x)
31 // x komplex rational -> Fixnum 1
32 // sonst: #C(1.0 0.0) im Float-Format des Real- bzw. Imaginärteils von x
34 // Falls x rational oder komplex rational oder |y| klein:
35 // x^|y| durch wiederholtes Quadrieren und Multiplizieren und evtl.
36 // Kehrwert-Bilden ermitteln.
37 // Sonst wie bei 'y Float'.
39 // Es gilt (expt x m/n) = (expt (expt x 1/n) m).
40 // Falls x in Q(i) liegt (also rational oder komplex rational ist):
41 // Sollte x^(m/n) in Q(i) liegen, so auch eine n-te Wurzel x^(1/n)
42 // (und bei n=2 oder n=4 damit auch alle n-ten Wurzeln x^(1/n) ).
43 // Falls x rational >=0: n-te Wurzel aus x nehmen. Ist sie rational,
44 // deren m-te Potenz als Ergebnis.
45 // Falls x rational <=0 oder komplex rational und n Zweierpotenz:
46 // n-te Wurzel aus x nehmen (mehrfaches sqrt). Ist sie rational oder
47 // komplex rational, deren m-te Potenz als Ergebnis.
48 // [Beliebige n betrachten!??]
49 // Falls n Zweierpotenz und |m|,n klein: n-te Wurzel aus x nehmen
50 // (mehrfaches sqrt), davon die m-te Potenz durch wiederholtes
51 // Quadrieren und Multiplizieren und evtl. Kehrwert-Bilden.
52 // Sonst wie bei 'y Float'.
53 // Falls y Float oder komplex:
55 // Falls Realteil von y >0 :
56 // liefere 0.0 falls x und y reell, #C(0.0 0.0) sonst.
59 // liefere 1.0 falls x und y reell, #C(1.0 0.0) sonst.
60 // Sonst: (exp (* (log x) y))
61 // Das Ergebnis liegt in Q(i), falls x in Q(i) liegt und 4y ein Integer ist.??
62 // Genauigkeit erhöhen, log2(|y|) Bits mehr??
63 // Bei x oder y rational und der andere Long-Float: bitte kein Single-Float!??
66 inline const cl_N expt_0 (const cl_N& x)
69 // y=0 -> 1 im Format von x.
81 var cl_R f = contagion(realpart(x),imagpart(x));
88 return complex_C(cl_float(1,f),cl_float(0,f));
92 // Exponent exakt 0 -> Ergebnis exakt 1
98 inline const cl_R contagion (const cl_N& x)
105 return contagion(realpart(x),imagpart(x));
109 const cl_N expt (const cl_N& x, const cl_N& y)
114 DeclareType(cl_RA,y);
120 return expt_0(x); // Liefere 1
121 if (fixnump(y)) // |y| klein ?
122 return expt(x,y); // exakt ausrechnen
126 DeclareType(cl_RA,x);
127 return expt(x,y); // exakt ausrechnen
131 if (rationalp(realpart(x)) && rationalp(imagpart(x)))
132 return expt(x,y); // exakt ausrechnen
134 // x nicht exakt und |y| groß
136 DeclareType(cl_RT,y);
138 var const cl_I& m = numerator(y);
139 var const cl_I& n = denominator(y);
143 DeclareType(cl_RA,x);
145 goto complex_rational;
148 if (rootp(x,n,&w)) // Wurzel rational?
153 if (rationalp(realpart(x)) && rationalp(imagpart(x)))
154 goto complex_rational;
159 var uintL k = power2p(n);
161 // n Zweierpotenz = 2^(k-1). n>1, also k>1
169 if (fixnump(m) && fixnump(n)) { // |m| und n klein?
170 var uintL _n = FN_to_UL(n);
171 if ((_n & (_n-1)) == 0) { // n Zweierpotenz?
173 until ((_n = _n >> 1) == 0)
181 // allgemeiner Fall (z.B. y Float oder komplex):
182 if (zerop(x)) { // x=0.0 ?
183 if (!plusp(realpart(y))) // Realteil von y <=0 ?
184 { cl_error_division_by_0(); }
185 if (realp(x) && realp(y)) {
188 var cl_R f = contagion(x,y);
189 // ein Float, da sonst x = Fixnum 0 gewesen wäre
190 { DeclareType(cl_F,f);
191 return cl_float(0,f); // 0.0
194 var cl_R f = contagion(contagion(x),contagion(y));
195 // ein Float, da sonst x = Fixnum 0 gewesen wäre
196 { DeclareType(cl_F,f);
197 var cl_F f0 = cl_float(0,f);
198 return complex_C(f0,f0); // #C(0.0 0.0)
202 if (zerop(y)) { // y=0.0 ?
203 if (realp(x) && realp(y)) {
206 var cl_R f = contagion(x,y);
207 // ein Float, da sonst y = Fixnum 0 gewesen wäre
208 { DeclareType(cl_F,f);
209 return cl_float(1,f);
212 var cl_R f = contagion(contagion(x),contagion(y));
213 // ein Float, da sonst y = Fixnum 0 gewesen wäre
214 { DeclareType(cl_F,f);
215 return complex_C(cl_float(1,f),cl_float(0,f));
219 return exp(log(x)*y);