rateslib/dual/dual_ops/
pow.rs

1use crate::dual::dual::{Dual, Dual2, Vars, VarsRelationship};
2use crate::dual::enums::Number;
3use crate::dual::linalg::fouter11_;
4use num_traits::Pow;
5use std::sync::Arc;
6
7impl Pow<&Dual> for f64 {
8    type Output = Dual;
9    fn pow(self, power: &Dual) -> Self::Output {
10        Dual {
11            real: self.pow(power.real),
12            vars: Arc::clone(power.vars()),
13            dual: &power.dual * self.pow(power.real) * self.ln(),
14        }
15    }
16}
17
18impl Pow<Dual> for f64 {
19    type Output = Dual;
20    fn pow(self, power: Dual) -> Self::Output {
21        Dual {
22            real: self.pow(power.real),
23            vars: power.vars,
24            dual: power.dual * self.pow(power.real) * self.ln(),
25        }
26    }
27}
28
29impl Pow<&Dual> for &f64 {
30    type Output = Dual;
31    fn pow(self, power: &Dual) -> Self::Output {
32        (*self).pow(power)
33    }
34}
35
36impl Pow<Dual> for &f64 {
37    type Output = Dual;
38    fn pow(self, power: Dual) -> Self::Output {
39        (*self).pow(power)
40    }
41}
42
43impl Pow<&Dual2> for f64 {
44    type Output = Dual2;
45    fn pow(self, power: &Dual2) -> Self::Output {
46        let df_dp = self.ln() * self.pow(power.real);
47        let d2f_dp2 = df_dp * self.ln();
48        Dual2 {
49            real: self.pow(power.real),
50            vars: Arc::clone(power.vars()),
51            dual: &power.dual * self.pow(power.real) * self.ln(),
52            dual2: df_dp * &power.dual2
53                + 0.5_f64 * d2f_dp2 * fouter11_(&power.dual.view(), &power.dual.view()),
54        }
55    }
56}
57
58impl Pow<Dual2> for f64 {
59    type Output = Dual2;
60    fn pow(self, power: Dual2) -> Self::Output {
61        let df_dp = self.ln() * self.pow(power.real);
62        let d2f_dp2 = df_dp * self.ln();
63        Dual2 {
64            real: self.pow(power.real),
65            vars: power.vars,
66            dual: &power.dual * self.pow(power.real) * self.ln(),
67            dual2: df_dp * &power.dual2
68                + 0.5_f64 * d2f_dp2 * fouter11_(&power.dual.view(), &power.dual.view()),
69        }
70    }
71}
72
73impl Pow<&Dual2> for &f64 {
74    type Output = Dual2;
75    fn pow(self, power: &Dual2) -> Self::Output {
76        (*self).pow(power)
77    }
78}
79
80impl Pow<Dual2> for &f64 {
81    type Output = Dual2;
82    fn pow(self, power: Dual2) -> Self::Output {
83        (*self).pow(power)
84    }
85}
86
87impl Pow<f64> for Dual {
88    type Output = Dual;
89    fn pow(self, power: f64) -> Self::Output {
90        Dual {
91            real: self.real.pow(power),
92            vars: self.vars,
93            dual: self.dual * power * self.real.pow(power - 1.0),
94        }
95    }
96}
97
98impl Pow<&f64> for Dual {
99    type Output = Dual;
100    fn pow(self, power: &f64) -> Self::Output {
101        self.pow(*power)
102    }
103}
104
105impl Pow<f64> for &Dual {
106    type Output = Dual;
107    fn pow(self, power: f64) -> Self::Output {
108        Dual {
109            real: self.real.pow(power),
110            vars: Arc::clone(self.vars()),
111            dual: &self.dual * power * self.real.pow(power - 1.0),
112        }
113    }
114}
115
116impl Pow<&f64> for &Dual {
117    type Output = Dual;
118    fn pow(self, power: &f64) -> Self::Output {
119        self.pow(*power)
120    }
121}
122
123impl Pow<&Dual> for &Dual {
124    type Output = Dual;
125    fn pow(self, power: &Dual) -> Self::Output {
126        let state = self.vars_cmp(power.vars());
127        match state {
128            VarsRelationship::ArcEquivalent | VarsRelationship::ValueEquivalent => Dual {
129                real: self.real.pow(power.real),
130                vars: Arc::clone(&self.vars),
131                dual: power.real * self.real.pow(power.real - 1_f64) * &self.dual
132                    + self.real.ln() * self.real.pow(power.real) * &power.dual,
133            },
134            _ => {
135                let (z, p) = self.to_union_vars(power, None);
136                Dual {
137                    real: z.real.pow(p.real),
138                    vars: Arc::clone(z.vars()),
139                    dual: p.real * z.real.pow(p.real - 1_f64) * &z.dual
140                        + z.real.ln() * z.real.pow(p.real) * &p.dual,
141                }
142            }
143        }
144    }
145}
146
147impl Pow<&Dual> for Dual {
148    type Output = Dual;
149    fn pow(self, power: &Dual) -> Self::Output {
150        (&self).pow(power)
151    }
152}
153
154impl Pow<Dual> for &Dual {
155    type Output = Dual;
156    fn pow(self, power: Dual) -> Self::Output {
157        self.pow(&power)
158    }
159}
160
161impl Pow<Dual> for Dual {
162    type Output = Dual;
163    fn pow(self, power: Dual) -> Self::Output {
164        (&self).pow(&power)
165    }
166}
167
168impl Pow<f64> for Dual2 {
169    type Output = Dual2;
170    fn pow(self, power: f64) -> Self::Output {
171        let coeff = power * self.real.powf(power - 1.);
172        let coeff2 = 0.5 * power * (power - 1.) * self.real.powf(power - 2.);
173        let beta_cross = fouter11_(&self.dual.view(), &self.dual.view());
174        Dual2 {
175            real: self.real.powf(power),
176            vars: self.vars,
177            dual: self.dual * coeff,
178            dual2: self.dual2 * coeff + beta_cross * coeff2,
179        }
180    }
181}
182
183impl Pow<&f64> for Dual2 {
184    type Output = Dual2;
185    fn pow(self, power: &f64) -> Self::Output {
186        self.pow(*power)
187    }
188}
189
190impl Pow<f64> for &Dual2 {
191    type Output = Dual2;
192    fn pow(self, power: f64) -> Self::Output {
193        let coeff = power * self.real.powf(power - 1.);
194        let coeff2 = 0.5 * power * (power - 1.) * self.real.powf(power - 2.);
195        let beta_cross = fouter11_(&self.dual.view(), &self.dual.view());
196        Dual2 {
197            real: self.real.powf(power),
198            vars: Arc::clone(self.vars()),
199            dual: &self.dual * coeff,
200            dual2: &self.dual2 * coeff + beta_cross * coeff2,
201        }
202    }
203}
204
205impl Pow<&f64> for &Dual2 {
206    type Output = Dual2;
207    fn pow(self, power: &f64) -> Self::Output {
208        self.pow(*power)
209    }
210}
211
212impl Pow<&Dual2> for &Dual2 {
213    type Output = Dual2;
214    fn pow(self, power: &Dual2) -> Self::Output {
215        let state = self.vars_cmp(power.vars());
216        match state {
217            VarsRelationship::ArcEquivalent | VarsRelationship::ValueEquivalent => {
218                let f_z = power.real * self.real.pow(power.real - 1_f64);
219                let f_p = self.real.pow(power.real) * self.real.ln();
220                let f_zz = power.real * (power.real - 1_f64) * self.real.pow(power.real - 2_f64);
221                let f_pp = self.real.ln() * self.real.ln() * self.real.pow(power.real);
222                let f_pz =
223                    (power.real * self.real.ln() + 1_f64) * self.real.pow(power.real - 1_f64);
224                let cross_beta = fouter11_(&power.dual.view(), &self.dual.view());
225                Dual2 {
226                    real: self.real.pow(power.real),
227                    vars: Arc::clone(self.vars()),
228                    dual: f_z * &self.dual + f_p * &power.dual,
229                    dual2: f_z * &self.dual2
230                        + f_p * &power.dual2
231                        + 0.5_f64 * f_zz * fouter11_(&self.dual.view(), &self.dual.view())
232                        + 0.5_f64 * f_pz * (&cross_beta + &cross_beta.t())
233                        + 0.5_f64 * f_pp * fouter11_(&power.dual.view(), &power.dual.view()),
234                }
235            }
236            _ => {
237                let (z, p) = self.to_union_vars(power, None);
238                let f_z = p.real * z.real.pow(p.real - 1_f64);
239                let f_p = z.real.pow(p.real) * z.real.ln();
240                let f_zz = p.real * (p.real - 1_f64) * z.real.pow(p.real - 2_f64);
241                let f_pp = z.real.ln() * z.real.ln() * z.real.pow(p.real);
242                let f_pz = (p.real * z.real.ln() + 1_f64) * z.real.pow(p.real - 1_f64);
243                let cross_beta = fouter11_(&p.dual.view(), &z.dual.view());
244                Dual2 {
245                    real: z.real.pow(p.real),
246                    vars: Arc::clone(z.vars()),
247                    dual: f_z * &z.dual + f_p * &p.dual,
248                    dual2: f_z * &z.dual2
249                        + f_p * &p.dual2
250                        + 0.5_f64 * f_zz * fouter11_(&z.dual.view(), &z.dual.view())
251                        + 0.5_f64 * f_pz * (&cross_beta + &cross_beta.t())
252                        + 0.5_f64 * f_pp * fouter11_(&p.dual.view(), &p.dual.view()),
253                }
254            }
255        }
256    }
257}
258
259impl Pow<&Dual2> for Dual2 {
260    type Output = Dual2;
261    fn pow(self, power: &Dual2) -> Self::Output {
262        (&self).pow(power)
263    }
264}
265
266impl Pow<Dual2> for &Dual2 {
267    type Output = Dual2;
268    fn pow(self, power: Dual2) -> Self::Output {
269        self.pow(&power)
270    }
271}
272
273impl Pow<Dual2> for Dual2 {
274    type Output = Dual2;
275    fn pow(self, power: Dual2) -> Self::Output {
276        (&self).pow(&power)
277    }
278}
279
280impl Pow<f64> for Number {
281    type Output = Number;
282    fn pow(self, power: f64) -> Self::Output {
283        match self {
284            Number::F64(f) => Number::F64(f.pow(power)),
285            Number::Dual(d) => Number::Dual(d.pow(power)),
286            Number::Dual2(d) => Number::Dual2(d.pow(power)),
287        }
288    }
289}
290
291impl Pow<&f64> for Number {
292    type Output = Number;
293    fn pow(self, power: &f64) -> Self::Output {
294        match self {
295            Number::F64(f) => Number::F64(f.pow(power)),
296            Number::Dual(d) => Number::Dual(d.pow(power)),
297            Number::Dual2(d) => Number::Dual2(d.pow(power)),
298        }
299    }
300}
301
302impl Pow<f64> for &Number {
303    type Output = Number;
304    fn pow(self, power: f64) -> Self::Output {
305        match self {
306            Number::F64(f) => Number::F64(f.pow(power)),
307            Number::Dual(d) => Number::Dual(d.pow(power)),
308            Number::Dual2(d) => Number::Dual2(d.pow(power)),
309        }
310    }
311}
312
313impl Pow<&f64> for &Number {
314    type Output = Number;
315    fn pow(self, power: &f64) -> Self::Output {
316        match self {
317            Number::F64(f) => Number::F64(f.pow(power)),
318            Number::Dual(d) => Number::Dual(d.pow(power)),
319            Number::Dual2(d) => Number::Dual2(d.pow(power)),
320        }
321    }
322}
323
324impl Pow<Number> for Number {
325    type Output = Number;
326    fn pow(self, power: Number) -> Self::Output {
327        match (self, power) {
328            (Number::F64(f), Number::F64(f2)) => Number::F64(f.pow(f2)),
329            (Number::F64(f), Number::Dual(d2)) => Number::Dual(f.pow(d2)),
330            (Number::F64(f), Number::Dual2(d2)) => Number::Dual2(f.pow(d2)),
331            (Number::Dual(d), Number::F64(f2)) => Number::Dual(d.pow(f2)),
332            (Number::Dual(d), Number::Dual(d2)) => Number::Dual(d.pow(d2)),
333            (Number::Dual(_), Number::Dual2(_)) => {
334                panic!("Cannot mix dual types: Dual/Dual2")
335            }
336            (Number::Dual2(d), Number::F64(f2)) => Number::Dual2(d.pow(f2)),
337            (Number::Dual2(_), Number::Dual(_)) => {
338                panic!("Cannot mix dual types: Dual2/Dual")
339            }
340            (Number::Dual2(d), Number::Dual2(d2)) => Number::Dual2(d.pow(d2)),
341        }
342    }
343}
344
345impl Pow<&Number> for Number {
346    type Output = Number;
347    fn pow(self, power: &Number) -> Self::Output {
348        match (self, power) {
349            (Number::F64(f), Number::F64(f2)) => Number::F64(f.pow(f2)),
350            (Number::F64(f), Number::Dual(d2)) => Number::Dual(f.pow(d2)),
351            (Number::F64(f), Number::Dual2(d2)) => Number::Dual2(f.pow(d2)),
352            (Number::Dual(d), Number::F64(f2)) => Number::Dual(d.pow(f2)),
353            (Number::Dual(d), Number::Dual(d2)) => Number::Dual(d.pow(d2)),
354            (Number::Dual(_), Number::Dual2(_)) => {
355                panic!("Cannot mix dual types: Dual/Dual2")
356            }
357            (Number::Dual2(d), Number::F64(f2)) => Number::Dual2(d.pow(f2)),
358            (Number::Dual2(_), Number::Dual(_)) => {
359                panic!("Cannot mix dual types: Dual2/Dual")
360            }
361            (Number::Dual2(d), Number::Dual2(d2)) => Number::Dual2(d.pow(d2)),
362        }
363    }
364}
365
366impl Pow<Number> for &Number {
367    type Output = Number;
368    fn pow(self, power: Number) -> Self::Output {
369        match (self, power) {
370            (Number::F64(f), Number::F64(f2)) => Number::F64(f.pow(f2)),
371            (Number::F64(f), Number::Dual(d2)) => Number::Dual(f.pow(d2)),
372            (Number::F64(f), Number::Dual2(d2)) => Number::Dual2(f.pow(d2)),
373            (Number::Dual(d), Number::F64(f2)) => Number::Dual(d.pow(f2)),
374            (Number::Dual(d), Number::Dual(d2)) => Number::Dual(d.pow(d2)),
375            (Number::Dual(_), Number::Dual2(_)) => {
376                panic!("Cannot mix dual types: Dual/Dual2")
377            }
378            (Number::Dual2(d), Number::F64(f2)) => Number::Dual2(d.pow(f2)),
379            (Number::Dual2(_), Number::Dual(_)) => {
380                panic!("Cannot mix dual types: Dual2/Dual")
381            }
382            (Number::Dual2(d), Number::Dual2(d2)) => Number::Dual2(d.pow(d2)),
383        }
384    }
385}
386
387impl Pow<&Number> for &Number {
388    type Output = Number;
389    fn pow(self, power: &Number) -> Self::Output {
390        match (self, power) {
391            (Number::F64(f), Number::F64(f2)) => Number::F64(f.pow(f2)),
392            (Number::F64(f), Number::Dual(d2)) => Number::Dual(f.pow(d2)),
393            (Number::F64(f), Number::Dual2(d2)) => Number::Dual2(f.pow(d2)),
394            (Number::Dual(d), Number::F64(f2)) => Number::Dual(d.pow(f2)),
395            (Number::Dual(d), Number::Dual(d2)) => Number::Dual(d.pow(d2)),
396            (Number::Dual(_), Number::Dual2(_)) => {
397                panic!("Cannot mix dual types: Dual/Dual2")
398            }
399            (Number::Dual2(d), Number::F64(f2)) => Number::Dual2(d.pow(f2)),
400            (Number::Dual2(_), Number::Dual(_)) => {
401                panic!("Cannot mix dual types: Dual2/Dual")
402            }
403            (Number::Dual2(d), Number::Dual2(d2)) => Number::Dual2(d.pow(d2)),
404        }
405    }
406}
407
408#[cfg(test)]
409mod tests {
410    use super::*;
411    use crate::dual::dual_ops::math_funcs::MathFuncs;
412    use ndarray::Array1;
413
414    fn is_close(a: &f64, b: &f64, abs_tol: Option<f64>) -> bool {
415        // used rather than equality for float numbers
416        (a - b).abs() < abs_tol.unwrap_or(1e-8)
417    }
418
419    fn assert_is_close_vecs(v1: &Vec<f64>, v2: &Vec<f64>) {
420        let v: Vec<bool> = v1
421            .iter()
422            .zip(v2.iter())
423            .map(|(x, y)| is_close(&x, &y, None))
424            .collect();
425        assert!(v.iter().all(|x| *x));
426    }
427
428    #[test]
429    fn inv() {
430        let d1 = Dual::try_new(
431            1.0,
432            vec!["v0".to_string(), "v1".to_string()],
433            vec![1.0, 2.0],
434        )
435        .unwrap();
436        let result = d1.clone() * d1.pow(-1.0);
437        let expected = Dual::new(1.0, vec![]);
438        assert!(result == expected)
439    }
440
441    #[test]
442    fn pow_ref() {
443        let d1 = Dual::new(3.0, vec!["x".to_string()]);
444        let d2 = (&d1).pow(2.0);
445        assert_eq!(d2.real, 9.0);
446        assert_eq!(d2.dual, Array1::from_vec(vec![6.0]));
447    }
448
449    #[test]
450    fn pow_ref2() {
451        let d1 = Dual2::new(3.0, vec!["x".to_string()]);
452        let d2 = (&d1).pow(2.0);
453        assert_eq!(d2.real, 9.0);
454        assert_eq!(d2.dual, Array1::from_vec(vec![6.0]));
455    }
456
457    #[test]
458    fn inv2() {
459        let d1 = Dual2::try_new(
460            1.0,
461            vec!["v0".to_string(), "v1".to_string()],
462            vec![1.0, 2.0],
463            Vec::new(),
464        )
465        .unwrap();
466        let result = d1.clone() * d1.pow(-1.0);
467        let expected = Dual2::new(1.0, vec![]);
468        assert_eq!(result, expected)
469    }
470
471    #[test]
472    fn test_enum() {
473        let f = Number::F64(2.0);
474        let d = Dual::new(3.0, vec!["x".to_string()]);
475        assert_eq!(Number::F64(4.0_f64), f.pow(2.0_f64));
476
477        let res = (&d).pow(2.0_f64);
478        assert_eq!(Number::Dual(res), Number::Dual(d).pow(2.0_f64));
479    }
480
481    #[test]
482    fn test_dual_dual() {
483        let z = Dual::new(2.0_f64, vec!["x".to_string()]);
484        let p = Dual::new(3.0_f64, vec!["p".to_string()]);
485        let result = (&z).pow(&p);
486        let expected = Dual::try_new(
487            8.0,
488            vec!["x".to_string(), "p".to_string()],
489            vec![12.0, 2.0_f64.ln() * 8.0],
490        )
491        .unwrap();
492        assert_eq!(result, expected);
493
494        let result2 = (&z).pow(p);
495        assert_eq!(result2, expected);
496        let p = Dual::new(3.0_f64, vec!["p".to_string()]);
497        let result3 = (z).pow(&p);
498        assert_eq!(result3, expected);
499        let z = Dual::new(2.0_f64, vec!["x".to_string()]);
500        let result4 = (z).pow(p);
501        assert_eq!(result4, expected);
502    }
503
504    #[test]
505    fn test_f64_dual() {
506        let p = Dual::new(3.0_f64, vec!["p".to_string()]);
507        let result = (&2_f64).pow(&p);
508        let expected = Dual::try_new(8.0, vec!["p".to_string()], vec![2.0_f64.ln() * 8.0]).unwrap();
509        assert_eq!(result, expected);
510
511        let result2 = (&2_f64).pow(p);
512        assert_eq!(result2, expected);
513        let p = Dual::new(3.0_f64, vec!["p".to_string()]);
514        let result3 = (2_f64).pow(&p);
515        assert_eq!(result3, expected);
516        let result4 = (2_f64).pow(p);
517        assert_eq!(result4, expected);
518    }
519
520    #[test]
521    fn test_f64_dual2() {
522        let p = Dual2::new(3.0_f64, vec!["p".to_string()]);
523        let result = (&2_f64).pow(&p);
524        let expected = Dual2::try_new(
525            8.0,
526            vec!["p".to_string()],
527            vec![2.0_f64.ln() * 8.0],
528            vec![2_f64.ln() * 2_f64.ln() * 4_f64],
529        )
530        .unwrap();
531        assert_eq!(result, expected);
532
533        let result2 = (&2_f64).pow(p);
534        assert_eq!(result2, expected);
535        let p = Dual2::new(3.0_f64, vec!["p".to_string()]);
536        let result3 = (2_f64).pow(&p);
537        assert_eq!(result3, expected);
538        let result4 = (2_f64).pow(p);
539        assert_eq!(result4, expected);
540    }
541
542    #[test]
543    fn test_dual2_dual2() {
544        // test all ref and deref binary ops
545        let p = Dual2::new(3.0_f64, vec!["p".to_string()]);
546        let z = Dual2::new(3.0_f64, vec!["z".to_string()]);
547        let x = Dual2::new(3.0_f64, vec!["x".to_string()]);
548        let y = Dual2::new(3.0_f64, vec!["y".to_string()]);
549        let mut _result = (&z).pow(&p);
550        _result = z.pow(&p);
551        _result = (&x).pow(p);
552        _result = x.pow(y);
553    }
554
555    #[test]
556    fn test_dual2_dual2_branch_equivalence() {
557        // test match branches yield the same calculation for Var equivalence and difference
558        let p = Dual2::try_new(
559            3.0_f64,
560            vec!["p".to_string(), "s".to_string()],
561            vec![1.1, 2.1],
562            vec![1.1, 2.2, 2.2, 1.4],
563        )
564        .unwrap();
565        let z = Dual2::try_new(
566            2.0_f64,
567            vec!["s".to_string(), "p".to_string()],
568            vec![1.9, 2.9],
569            vec![3.4, 1.2, 1.2, 0.1],
570        )
571        .unwrap();
572        let z_p = Dual2::try_new_from(
573            &p,
574            2.0_f64,
575            vec!["p".to_string(), "s".to_string()],
576            vec![2.9, 1.9],
577            vec![0.1, 1.2, 1.2, 3.4],
578        )
579        .unwrap();
580        let result1 = (&p).pow(z);
581        let result2 = p.pow(z_p);
582        assert_eq!(result1, result2);
583    }
584
585    #[test]
586    fn test_dual2_dual2_op_equivalence() {
587        // test the analytical derivative calculations match those expected from exp and log
588        let p = Dual2::try_new(
589            3.0_f64,
590            vec!["p".to_string(), "s".to_string()],
591            vec![1.1, 2.1],
592            vec![1.1, 2.2, 2.2, 1.4],
593        )
594        .unwrap();
595        let z = Dual2::try_new(
596            2.0_f64,
597            vec!["s".to_string(), "p".to_string()],
598            vec![1.9, 2.9],
599            vec![3.4, 1.2, 1.2, 0.1],
600        )
601        .unwrap();
602        let r1 = (&z).pow(&p);
603        let r2 = (z.log() * p).exp();
604        assert_is_close_vecs(&r1.dual.to_vec(), &r2.dual.to_vec());
605        assert_is_close_vecs(
606            &r1.dual2.into_raw_vec_and_offset().0,
607            &r2.dual2.into_raw_vec_and_offset().0,
608        );
609    }
610
611    #[test]
612    fn test_number_number() {
613        // test implemented crosses
614        fn x1() -> Number {
615            Number::F64(2.3)
616        }
617        fn x2() -> Number {
618            Number::Dual(Dual::new(2.3, vec![]))
619        }
620        fn x3() -> Number {
621            Number::Dual2(Dual2::new(1.1, vec![]))
622        }
623
624        let mut _res: Number;
625        _res = (&x1()).pow(&x1());
626        _res = (&x1()).pow(&x2());
627        _res = (&x1()).pow(&x3());
628        _res = (&x2()).pow(&x1());
629        _res = (&x2()).pow(&x2());
630        _res = (&x3()).pow(&x1());
631        _res = (&x3()).pow(&x3());
632
633        _res = (x1()).pow(&x1());
634        _res = (x1()).pow(&x2());
635        _res = (x1()).pow(&x3());
636        _res = (x2()).pow(&x1());
637        _res = (x2()).pow(&x2());
638        _res = (x3()).pow(&x1());
639        _res = (x3()).pow(&x3());
640
641        _res = (&x1()).pow(x1());
642        _res = (&x1()).pow(x2());
643        _res = (&x1()).pow(x3());
644        _res = (&x2()).pow(x1());
645        _res = (&x2()).pow(x2());
646        _res = (&x3()).pow(x1());
647        _res = (&x3()).pow(x3());
648
649        _res = (x1()).pow(x1());
650        _res = (x1()).pow(x2());
651        _res = (x1()).pow(x3());
652        _res = (x2()).pow(x1());
653        _res = (x2()).pow(x2());
654        _res = (x3()).pow(x1());
655        _res = (x3()).pow(x3());
656    }
657}