Skip to main content

f256/math/
pow.rs

1// ---------------------------------------------------------------------------
2// Copyright:   (c) 2024 ff. Michael Amrhein (michael@adrhinum.de)
3// License:     This program is part of a larger application. For license
4//              details please read the file LICENSE.TXT provided together
5//              with the application.
6// ---------------------------------------------------------------------------
7// $Source: src/math/pow.rs $
8// $Revision: 2025-11-22T13:28:04+01:00 $
9
10use core::num::FpCategory;
11
12use super::bkm::{bkm_e, bkm_l};
13use super::exp::approx_exp;
14use super::log::approx_ln;
15use super::{BigUInt, Float512, HiLo, Parity};
16use crate::{
17    abs_bits, exp, f256, norm_signif_exp, EMAX, EMIN, FRACTION_BITS,
18};
19
20enum Lim {
21    Ok,
22    Overflow,
23    Underflow,
24}
25
26impl Lim {
27    // Check the range of exponents n where xⁿ is guarantied to be infinite.
28    #[inline(always)]
29    #[allow(clippy::cast_possible_wrap)]
30    fn powi(x: &f256, n: i32) -> Self {
31        let (m, mut e) = norm_signif_exp(&abs_bits(x));
32        // Now we have |x| = m⋅2ᵉ with 1 <= m < 2 and Eₘᵢₙ-P+1 <= e <= Eₘₐₓ
33        // |x|ⁿ = (m⋅2ᵉ)ⁿ = mⁿ⋅(2ᵉ)ⁿ = mⁿ⋅2ᵉⁿ
34        // n > 1 => 1 <= mⁿ < 2ⁿ => 2ᵉⁿ <= mⁿ⋅2ᵉⁿ < 2ⁿ⁺ᵉⁿ
35        // n < 1 => 2ⁿ < mⁿ <= 1 => 2ⁿ⁺ᵉⁿ < mⁿ⋅2ᵉⁿ <= 2ᵉⁿ
36        const LOWER_LIM: i32 = -EMAX - 1 - FRACTION_BITS as i32;
37        const UPPER_LIM: i32 = EMAX + 1;
38        let e_times_n = e.saturating_mul(n);
39        match e_times_n {
40            ..=LOWER_LIM => Self::Underflow,
41            UPPER_LIM.. => Self::Overflow,
42            _ => Self::Ok,
43        }
44    }
45
46    // Check the range of exponents n where xʸ is guarantied to be infinite.
47    #[inline(always)]
48    fn powf(x: &f256, y: &f256) -> Self {
49        match i32::try_from(&y.trunc()) {
50            Ok(n) => Self::powi(x, n),
51            Err(_) => Self::powi(x, [i32::MAX, i32::MIN][y.sign() as usize]),
52        }
53    }
54}
55
56// Calculate xⁿ
57#[inline(always)]
58fn powi(x: &f256, mut n: i32) -> f256 {
59    debug_assert!(x.is_finite() && !x.eq_zero());
60    debug_assert!(n.abs() > 1);
61    // x < 0 => x = -1⋅|x| => xⁿ = (-1)ⁿ⋅|x|ⁿ
62    let s = x.sign() * ((n.abs() % 2) == 1) as u32;
63    match Lim::powi(x, n) {
64        Lim::Overflow => [f256::INFINITY, f256::NEG_INFINITY][s as usize],
65        Lim::Underflow => [f256::ZERO, f256::NEG_ZERO][s as usize],
66        _ => {
67            // Result is most likely finite.
68            f256::from(&Float512::from(x).powi(n))
69        }
70    }
71}
72
73pub(crate) fn approx_powf(mut x: Float512, mut y: Float512) -> Float512 {
74    debug_assert!(y.abs() < Float512::from(i32::MAX));
75    if y.signum() == -1 {
76        x = x.recip();
77        y.flip_sign();
78    }
79    // 0 < y < 2³¹
80    // y = a + b where a ∈ ℤ and 0 <= b < 1
81    // xʸ = xᵅ⁺ᵇ = xᵅ⋅xᵇ = xᵅ⋅eʷ where w = b⋅logₑ x
82    // println!("x = {:e}", f256::from(&x));
83    // println!("y = {:e}", f256::from(&y));
84    let a = y.trunc();
85    // println!("a = {:e}", f256::from(&a));
86    let b = y - a;
87    // println!("b = {:e}", f256::from(&b));
88    let mut a = i32::try_from(&a).unwrap();
89    // println!("a = {a}");
90    let lnx = approx_ln(&x);
91    // println!("l = {lnx:?}");
92    let w = b * lnx;
93    // println!("w = {w:?}");
94    let ew = approx_exp(&w);
95    // println!("ew = {:?}", ew);
96    x.powi(a) * ew
97}
98
99// Compute xʸ
100#[inline(always)]
101fn powf(x: &f256, y: &f256) -> f256 {
102    debug_assert!(x.is_finite() && !x.eq_zero());
103    debug_assert!(y.is_finite() && !y.eq_zero());
104    let x_sign = x.sign();
105    if let Ok(n) = i32::try_from(y) {
106        let s: usize = match (x_sign, (n % 2) == 1) {
107            (0, _) | (1, false) => 0,
108            (1, true) => 1,
109            _ => unreachable!(),
110        };
111        return match Lim::powi(x, n) {
112            Lim::Overflow => [f256::INFINITY, f256::NEG_INFINITY][s],
113            Lim::Underflow => [f256::ZERO, f256::NEG_ZERO][s],
114            _ => powi(x, n),
115        };
116    };
117    if let Some(p) = y.parity() {
118        // y ∈ ℤ and |y| >= 2³¹
119        let s = match (x_sign, p) {
120            (0, _) | (1, Parity::Even) => 0,
121            (1, Parity::Odd) => 1,
122            _ => unreachable!(),
123        };
124        return match Lim::powi(x, [i32::MAX, i32::MIN][y.sign() as usize]) {
125            Lim::Overflow => [f256::INFINITY, f256::NEG_INFINITY][s],
126            Lim::Underflow => [f256::ZERO, f256::NEG_ZERO][s],
127            _ => unreachable!(),
128        };
129    }
130    // y ∉ ℤ
131    if x_sign == 1 {
132        // xʸ = NaN for x < 0 and non-integer y
133        return f256::NAN;
134    };
135    match Lim::powf(x, y) {
136        Lim::Overflow => {
137            [f256::INFINITY, f256::NEG_INFINITY][x_sign as usize]
138        }
139        Lim::Underflow => [f256::ZERO, f256::NEG_ZERO][x_sign as usize],
140        _ => {
141            // Result is most likely finite.
142            f256::from(&approx_powf(Float512::from(x), Float512::from(y)))
143        }
144    }
145}
146
147impl f256 {
148    /// Raises a number to an integer power.
149    #[must_use]
150    pub fn powi(&self, n: i32) -> Self {
151        // x⁰ = 1 for any x, incl. NaN
152        // 1ⁿ = 1 for any n
153        if n == 0 || *self == Self::ONE {
154            return Self::ONE;
155        }
156        // x¹ = x for any x, incl. NaN
157        if n == 1 {
158            return *self;
159        }
160        // x⁻¹ = 1/x for any x, incl. NaN (note: 1/NaN = NaN)
161        if n == -1 {
162            return self.recip();
163        }
164        // This test for special values is redundant, but it reduces the
165        // number of tests for normal cases.
166        if self.is_special() {
167            // NaNⁿ = NaN for n != 0
168            if self.is_nan() {
169                return Self::NAN;
170            }
171            // 0ⁿ = 0 for n > 0
172            // 0ⁿ = ∞ for n < 0
173            if self.eq_zero() {
174                return [Self::ZERO, Self::INFINITY][(n < 0) as usize];
175            }
176            // ∞ⁿ = ∞ for n > 0
177            // ∞ⁿ = 0 for n < 0
178            // (-∞)ⁿ = ∞ for n > 0 and n is even
179            // (-∞)ⁿ = -∞ for n > 0 and n is odd
180            // (-∞)ⁿ = 0 for n < 0 and n is even
181            // (-∞)ⁿ = -0 for n < 0 and n is odd
182            if self.is_infinite() {
183                match (self.sign(), n.signum()) {
184                    (0, 1) => return Self::INFINITY,
185                    (0, -1) => return Self::ZERO,
186                    (1, 1) => {
187                        return [Self::INFINITY, Self::NEG_INFINITY]
188                            [(n & 1 == 1) as usize]
189                    }
190                    (1, -1) => {
191                        return [Self::ZERO, Self::NEG_ZERO]
192                            [(n & 1 == 1) as usize]
193                    }
194                    _ => unreachable!(),
195                }
196            }
197        }
198        // self is finite and != 0, n ∉ [-1…1]
199        powi(self, n)
200    }
201
202    /// Raises a number to a floating point power.
203    #[must_use]
204    pub fn powf(&self, exp: &Self) -> Self {
205        // a⁰ = 1 for any a, incl. NaN
206        // 1ᵇ = 1 for any b, incl. NaN
207        if exp.eq_zero() || *self == Self::ONE {
208            return Self::ONE;
209        }
210        // a¹ = a for any a, incl. NaN
211        if *exp == Self::ONE {
212            return *self;
213        }
214        // a⁻¹ = 1/a for any a, incl. NaN (note: 1/NaN = NaN)
215        if *exp == Self::NEG_ONE {
216            return self.recip();
217        }
218        // This test for special values is redundant, but it reduces the
219        // number of tests for normal cases.
220        if self.is_special() || exp.is_special() {
221            // aᴺᵃᴺ = NaN for a != 1
222            // NaNᵇ = NaN for |b| != 0
223            if self.is_nan() || exp.is_nan() {
224                return Self::NAN;
225            }
226            // 0ᵇ = 0 for b > 0
227            // 0ᵇ = ∞ for b < 0
228            if self.eq_zero() {
229                return [Self::ZERO, Self::INFINITY][exp.sign() as usize];
230            }
231            // ∞ᵇ = ∞ for b > 0
232            // ∞ᵇ = 0 for b < 0
233            // (-∞)ᵇ = ∞ for b > 0 and (b ∉ ℕ or b ∈ ℕ and b is even)
234            // (-∞)ᵇ = -∞ for b > 0 and b ∈ ℕ and b is odd
235            // (-∞)ᵇ = 0 for b < 0 and (|b| ∉ ℕ or |b| ∈ ℕ and |b| is even)
236            // (-∞)ᵇ = -0 for b < 0 and |b| ∈ ℕ and |b| is odd
237            if self.is_infinite() {
238                return match (self.sign(), exp.sign()) {
239                    (0, 0) => Self::INFINITY,
240                    (0, 1) => Self::ZERO,
241                    (1, 0) => match exp.parity() {
242                        Some(Parity::Odd) => Self::NEG_INFINITY,
243                        _ => Self::INFINITY,
244                    },
245                    (1, 1) => match exp.parity() {
246                        Some(Parity::Odd) => Self::NEG_ZERO,
247                        _ => Self::ZERO,
248                    },
249                    _ => unreachable!(),
250                };
251            }
252        }
253        // self is finite and != 0, exp is finite and ∉ [-1, 0, 1]
254        powf(self, exp)
255    }
256}
257
258#[cfg(test)]
259mod powi_tests {
260    use super::*;
261    use crate::{EMAX, FRACTION_BITS, SIGNIFICAND_BITS};
262
263    #[test]
264    #[allow(clippy::cognitive_complexity)]
265    fn test_specials() {
266        for n in [1, 786, i32::MAX] {
267            assert_eq!(f256::INFINITY.powi(n), f256::INFINITY);
268            assert_eq!(f256::ZERO.powi(n), f256::ZERO);
269            assert!(f256::NAN.powi(n).is_nan());
270        }
271        for n in [i32::MIN, -328, -1] {
272            assert_eq!(f256::INFINITY.powi(n), f256::ZERO);
273            assert_eq!(f256::ZERO.powi(n), f256::INFINITY);
274            assert!(f256::NAN.powi(n).is_nan());
275        }
276        for n in [1, 783, i32::MAX] {
277            assert_eq!(f256::NEG_INFINITY.powi(n), f256::NEG_INFINITY);
278        }
279        for n in [4, 780, i32::MAX - 1] {
280            assert_eq!(f256::NEG_INFINITY.powi(n), f256::INFINITY);
281        }
282        for n in [i32::MIN, -328, -8] {
283            let z = f256::NEG_INFINITY.powi(n);
284            assert!(z.eq_zero());
285            assert!(z.is_sign_positive());
286        }
287        for n in [i32::MIN + 1, -321, -5] {
288            let z = f256::NEG_INFINITY.powi(n);
289            assert!(z.eq_zero());
290            assert!(z.is_sign_negative());
291        }
292    }
293
294    #[test]
295    fn test_n_eq_0() {
296        for f in [
297            f256::NAN,
298            f256::NEG_INFINITY,
299            f256::MIN,
300            -f256::TEN,
301            f256::NEG_ONE,
302            f256::NEG_ZERO,
303            f256::ZERO,
304            f256::MIN_GT_ZERO,
305            f256::MIN_POSITIVE,
306            f256::EPSILON,
307            f256::ONE,
308            f256::TWO,
309            f256::MAX,
310            f256::INFINITY,
311        ] {
312            assert_eq!(f.powi(0), f256::ONE);
313        }
314    }
315
316    #[test]
317    #[allow(clippy::integer_division)]
318    fn test_overflow() {
319        let mut f = f256::MAX.sqrt();
320        f += f.ulp();
321        assert_eq!(f.powi(2), f256::INFINITY);
322        let n = -7;
323        let f = f256::from_sign_exp_signif(1, EMAX / n - 1, (0, 1));
324        assert_eq!(f.powi(n), f256::NEG_INFINITY);
325        let n = 1440;
326        let f = f256::from_sign_exp_signif(
327            1,
328            -54,
329            (
330                0x00001be93972f42ce76d0fe4549e8709,
331                0x822fb626bcccea99631b77b8b3c24781,
332            ),
333        );
334        assert_eq!(f.powi(n), f256::INFINITY);
335    }
336
337    #[test]
338    #[allow(clippy::integer_division)]
339    #[allow(clippy::cast_possible_wrap)]
340    fn test_underflow() {
341        let mut f =
342            f256::MAX.sqrt() * f256::from(2_u128.pow(FRACTION_BITS / 2));
343        f += f.ulp();
344        assert_eq!(f.powi(-2), f256::ZERO);
345        let n = 7;
346        let f = f256::from_sign_exp_signif(
347            1,
348            (EMIN - FRACTION_BITS as i32) / n - 1,
349            (0, 1),
350        );
351        assert_eq!(f.powi(n), f256::NEG_ZERO);
352        let mut f = f256::MIN_GT_ZERO.sqrt().div2();
353        assert_eq!(f.powi(2), f256::ZERO);
354    }
355
356    #[test]
357    fn test_subnormal_result() {
358        let f = f256::MIN_GT_ZERO.sqrt();
359        assert_eq!(f.powi(2), f256::MIN_GT_ZERO);
360    }
361
362    #[test]
363    #[allow(clippy::cast_sign_loss)]
364    fn test_int_base_with_n_gt_0() {
365        let m = 73_u64;
366        let f = f256::from(m);
367        let n = 5;
368        assert_eq!(f.powi(n), f256::from(m.pow(n as u32)));
369        let m = 17_u128;
370        let f = f256::from(m);
371        let n = 30;
372        assert_eq!(f.powi(n), f256::from(m.pow(n as u32)));
373    }
374
375    #[test]
376    fn test_int_base_with_n_lt_0() {
377        let m = 69_u64;
378        let f = f256::from(m);
379        let n = -4;
380        assert_eq!(f.powi(n), f256::from(m.pow(n.unsigned_abs())).recip());
381        let m = 7_u128;
382        let f = f256::from(m);
383        let n = -41;
384        assert_eq!(f.powi(n), f256::from(m.pow(n.unsigned_abs())).recip());
385    }
386
387    #[test]
388    fn test_base_near_1() {
389        let f = f256::ONE + f256::EPSILON;
390        let f2 = f.square();
391        assert_eq!(f.powi(2), f2);
392        assert_eq!(f.powi(9), f2.square().square() * f);
393    }
394
395    #[test]
396    fn test_base_near_minus_1() {
397        let f = f256::NEG_ONE + f256::EPSILON;
398        let f2 = f.square();
399        assert_eq!(f.powi(2), f2);
400        assert_eq!(f.powi(5), f2.square() * f);
401    }
402
403    #[test]
404    #[allow(clippy::cast_possible_wrap)]
405    fn test_max() {
406        let f = f256::TWO;
407        let p =
408            (f.powi(EMAX) - f.powi(EMAX - SIGNIFICAND_BITS as i32)).mul2();
409        assert_eq!(p, f256::MAX);
410    }
411
412    #[test]
413    fn test_near_max() {
414        let mut f = f256::TWO;
415        f -= f.ulp();
416        let p = f.powi(f256::MAX_EXP);
417        assert!(p.diff_within_n_bits(&f256::MAX, 19));
418    }
419}
420
421#[cfg(test)]
422mod powf_tests {
423    use super::*;
424    use crate::{EMAX, FIVE, FRACTION_BITS, ONE_HALF};
425
426    #[test]
427    #[allow(clippy::cognitive_complexity)]
428    fn test_specials() {
429        let g = f256::from(123.45_f64);
430        let h = f256::TWO.powi(236) - f256::ONE;
431        for b in [f256::MIN_GT_ZERO, f256::ONE, g, f256::MAX] {
432            // ∞ᵇ = ∞ for b > 0
433            assert_eq!(f256::INFINITY.powf(&b), f256::INFINITY);
434            // 0ᵇ = 0 for b > 0
435            assert_eq!(f256::ZERO.powf(&b), f256::ZERO);
436            // NaNᵇ = NaN for b != 0
437            assert!(f256::NAN.powf(&b).is_nan());
438        }
439        for b in [f256::MIN, -g, f256::NEG_ONE, -f256::MIN_POSITIVE] {
440            // ∞ᵇ = 0 for b < 0
441            assert_eq!(f256::INFINITY.powf(&b), f256::ZERO);
442            // 0ᵇ = ∞ for b < 0
443            assert_eq!(f256::ZERO.powf(&b), f256::INFINITY);
444            // NaNᵇ = NaN for b != 0
445            assert!(f256::NAN.powf(&b).is_nan());
446        }
447        for b in [f256::ONE, FIVE, h] {
448            // (-∞)ᵇ = -∞ for b > 0 and b ∈ ℕ and b is odd
449            assert_eq!(f256::NEG_INFINITY.powf(&b), f256::NEG_INFINITY);
450        }
451        for b in [f256::TWO, g, f256::MAX] {
452            // (-∞)ᵇ = ∞ for b > 0 and (b ∉ ℕ or b ∈ ℕ and b is even)
453            assert_eq!(f256::NEG_INFINITY.powf(&b), f256::INFINITY);
454        }
455        for b in [f256::MIN, -g, -f256::TEN] {
456            // (-∞)ᵇ = 0 for b < 0 and (|b| ∉ ℕ or |b| ∈ ℕ and |b| is even)
457            let z = f256::NEG_INFINITY.powf(&b);
458            assert!(z.eq_zero());
459            assert!(z.is_sign_positive());
460        }
461        for b in [-h, -FIVE] {
462            // (-∞)ᵇ = -0 for b < 0 and |b| ∈ ℕ and |b| is odd
463            let z = f256::NEG_INFINITY.powf(&b);
464            assert!(z.eq_zero());
465            assert!(z.is_sign_negative());
466        }
467        for a in [
468            f256::NAN,
469            f256::NEG_INFINITY,
470            f256::MIN,
471            -f256::TEN,
472            f256::NEG_ONE,
473            f256::NEG_ZERO,
474            f256::ZERO,
475            f256::MIN_GT_ZERO,
476            f256::MIN_POSITIVE,
477            f256::EPSILON,
478            f256::TWO,
479            f256::MAX,
480            f256::INFINITY,
481        ] {
482            // aᴺᵃᴺ = NaN for a != 1
483            assert!(a.powf(&f256::NAN).is_nan());
484        }
485        for b in [
486            f256::NAN,
487            f256::NEG_INFINITY,
488            f256::MIN,
489            -f256::TEN,
490            f256::NEG_ONE,
491            f256::MIN_GT_ZERO,
492            f256::MIN_POSITIVE,
493            f256::EPSILON,
494            f256::ONE,
495            f256::TWO,
496            f256::MAX,
497            f256::INFINITY,
498        ] {
499            // NaNᵇ = NaN for |b| != 0
500            assert!(f256::NAN.powf(&b).is_nan());
501        }
502        for x in [f256::MIN, -g, f256::NEG_ONE, -f256::MIN_POSITIVE] {
503            // xʸ = NaN for x < 0 and non-integer y
504            assert!(x.powf(&g).is_nan());
505        }
506    }
507
508    #[test]
509    fn test_a_pow_0() {
510        for a in [
511            f256::NAN,
512            f256::NEG_INFINITY,
513            f256::MIN,
514            -f256::TEN,
515            f256::NEG_ONE,
516            f256::NEG_ZERO,
517            f256::ZERO,
518            f256::MIN_GT_ZERO,
519            f256::MIN_POSITIVE,
520            f256::EPSILON,
521            f256::ONE,
522            f256::TWO,
523            f256::MAX,
524            f256::INFINITY,
525        ] {
526            // a⁰ = 1 for any a, incl. NaN
527            assert_eq!(a.powf(&f256::ZERO), f256::ONE);
528            assert_eq!(a.powf(&f256::NEG_ZERO), f256::ONE);
529        }
530    }
531
532    #[test]
533    fn test_a_pow_1() {
534        // a¹ = a for any a, incl. NaN
535        for a in [
536            f256::NEG_INFINITY,
537            f256::MIN,
538            -f256::TEN,
539            f256::NEG_ONE,
540            f256::NEG_ZERO,
541            f256::ZERO,
542            f256::MIN_GT_ZERO,
543            f256::MIN_POSITIVE,
544            f256::EPSILON,
545            f256::ONE,
546            f256::TWO,
547            f256::MAX,
548            f256::INFINITY,
549        ] {
550            assert_eq!(a.powf(&f256::ONE), a);
551        }
552        assert!(f256::NAN.powf(&f256::ONE).is_nan());
553    }
554
555    #[test]
556    fn test_1_pow_b() {
557        for b in [
558            f256::NAN,
559            f256::NEG_INFINITY,
560            f256::MIN,
561            -f256::TEN,
562            f256::NEG_ONE,
563            f256::NEG_ZERO,
564            f256::ZERO,
565            f256::MIN_GT_ZERO,
566            f256::MIN_POSITIVE,
567            f256::EPSILON,
568            f256::ONE,
569            f256::TWO,
570            f256::MAX,
571            f256::INFINITY,
572        ] {
573            // 1ᵇ = 1 for any b, incl. NaN
574            assert_eq!(f256::ONE.powf(&b), f256::ONE);
575        }
576    }
577
578    #[test]
579    #[allow(clippy::integer_division)]
580    fn test_overflow() {
581        let mut x = f256::MAX.sqrt();
582        x += x.ulp();
583        assert_eq!(x.powf(&f256::TWO), f256::INFINITY);
584        let n = -7;
585        let mut y = f256::from(n);
586        y -= y.ulp();
587        let x = f256::from_sign_exp_signif(0, EMAX / n - 1, (0, 1));
588        assert_eq!(x.powf(&y), f256::INFINITY);
589        let y = f256::from(1439.907);
590        let x = f256::from_sign_exp_signif(
591            0,
592            -54,
593            (
594                0x00001be93972f42ce76d0fe4549e8709,
595                0x822fb626bcccea99631b77b8b3c24781,
596            ),
597        );
598        assert_eq!(x.powf(&y), f256::INFINITY);
599    }
600
601    #[test]
602    #[allow(clippy::integer_division)]
603    #[allow(clippy::cast_possible_wrap)]
604    fn test_underflow() {
605        let mut x =
606            f256::MAX.sqrt() * f256::from(2_u128.pow(FRACTION_BITS / 2));
607        x += x.ulp();
608        assert_eq!(x.powf(&-f256::TWO), f256::ZERO);
609        let n = 7;
610        let mut y = f256::from(n);
611        y += y.ulp();
612        let x = f256::from_sign_exp_signif(
613            0,
614            (EMIN - FRACTION_BITS as i32) / n - 1,
615            (0, 1),
616        );
617        assert_eq!(x.powf(&y), f256::ZERO);
618        let x = f256::MIN_GT_ZERO.sqrt().div2();
619        let mut y = f256::TWO;
620        y -= y.ulp();
621        assert_eq!(x.powf(&y), f256::ZERO);
622    }
623
624    #[test]
625    fn test_subnormal_result() {
626        let x = f256::MIN_GT_ZERO.sqrt();
627        let mut y = f256::TWO;
628        y -= y.ulp();
629        assert_eq!(x.powf(&y), f256::MIN_GT_ZERO);
630        let x = f256::EPSILON;
631        let y = f256::from(1111.1);
632        let z = x.powf(&y);
633        assert_eq!(
634            z,
635            f256::from_sign_exp_signif(
636                0,
637                -262377,
638                (
639                    0x0000000000000000000000002a3968a7,
640                    0x75598fceb5d84852b84918221a2a837f,
641                )
642            )
643        );
644    }
645
646    #[test]
647    fn test_base_near_1() {
648        let x = f256::ONE + f256::EPSILON;
649        let z = x.square();
650        let mut y = f256::TWO;
651        y -= z.ulp();
652        assert_eq!(x.powf(&y), z);
653        assert_eq!(x.powf(&f256::from(9)), z.square().square() * x);
654    }
655
656    #[test]
657    fn test_base_near_minus_1() {
658        let x = f256::NEG_ONE + f256::EPSILON;
659        let z = x.square();
660        let mut y = f256::TWO;
661        y -= z.ulp();
662        assert_eq!(x.powf(&y), z);
663        assert_eq!(x.powf(&f256::from(5)), z.square() * x);
664    }
665
666    #[test]
667    fn test_int_base_non_int_exp() {
668        let x = FIVE;
669        assert_eq!(x.powf(&f256::from(2.5_f64)), FIVE.square() * FIVE.sqrt());
670    }
671
672    #[test]
673    fn test_non_int_base_non_int_exp() {
674        let x = FIVE - f256::EPSILON.mul_pow2(7);
675        assert_eq!(
676            x.powf(&f256::from(3.25_f64)),
677            x.powi(3) * x.sqrt().sqrt()
678        );
679    }
680}