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 (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 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 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 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 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}