Skip to content

Commit

Permalink
Fix zero pow
Browse files Browse the repository at this point in the history
  • Loading branch information
cmpute committed Dec 17, 2023
1 parent f17e710 commit 29875ff
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 42 deletions.
8 changes: 4 additions & 4 deletions float/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ fn repr_cmp_same_base<const B: Word, const ABS: bool>(
(true, true) => return Ordering::Equal,
(true, false) => {
// rhs must be positive, otherwise case 2 will return
return Ordering::Less
},
return Ordering::Less;
}
(false, true) => {
// lhs must be positive, otherwise case 2 will return
return Ordering::Greater
},
return Ordering::Greater;
}
_ => {}
}

Expand Down
6 changes: 4 additions & 2 deletions float/src/exp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
repr::{Context, Repr, Word},
round::{Round, Rounded},
};
use dashu_base::{Approximation::*, BitTest, DivRemEuclid, EstimatedLog2, Sign, AbsOrd};
use dashu_base::{AbsOrd, Approximation::*, BitTest, DivRemEuclid, EstimatedLog2, Sign};
use dashu_int::IBig;

impl<R: Round, const B: Word> FBig<R, B> {
Expand Down Expand Up @@ -149,7 +149,7 @@ impl<R: Round> Context<R> {
}

/// Raise the floating point number to an floating point power under this context.
///
///
/// Note that this method will not rely on [FBig::powi] even if the `exp` is actually an integer.
///
/// # Examples
Expand Down Expand Up @@ -180,6 +180,8 @@ impl<R: Round> Context<R> {
} else if exp.is_one() {
let repr = self.repr_round_ref(base);
return repr.map(|v| FBig::new(v, *self));
} else if base.is_zero() {
return Exact(FBig::ZERO);
}
if base.sign() == Sign::Negative {
// TODO: we should allow negative base when exp is an integer
Expand Down
3 changes: 2 additions & 1 deletion float/src/fbig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ impl<R: Round, const B: Word> FBig<R, B> {
let repr = Repr {
significand: IBig::ONE,
exponent: self.repr.exponent + self.repr.digits_lb() as isize
- self.context.precision as isize - 1,
- self.context.precision as isize
- 1,
};
Self::new(repr, self.context)
}
Expand Down
2 changes: 1 addition & 1 deletion float/src/log.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use dashu_base::{Approximation::*, EstimatedLog2, Sign, AbsOrd};
use dashu_base::{AbsOrd, Approximation::*, EstimatedLog2, Sign};
use dashu_int::IBig;

use crate::{
Expand Down
39 changes: 19 additions & 20 deletions float/tests/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,54 +313,53 @@ fn test_add_sub_with_rounding() {

// rhs is about the magnitude of lhs.ulp()
let a = fbig!(0x01).with_rounding::<Zero>();
let b = fbig!(0x1p-8).with_rounding::<Zero>();
let c = fbig!(0xffp-8).with_rounding::<Zero>();
let b = fbig!(0x1p - 8).with_rounding::<Zero>();
let c = fbig!(0xffp - 8).with_rounding::<Zero>();
test_add(&a, &b, &a);
test_sub(&a, &b, &c);

let a = fbig!(0x01).with_rounding::<Up>();
let b = fbig!(0x1p-8).with_rounding::<Up>();
let c = fbig!(0x81p-7).with_rounding::<Up>();
let d = fbig!(0xffp-8).with_rounding::<Up>();
let b = fbig!(0x1p - 8).with_rounding::<Up>();
let c = fbig!(0x81p - 7).with_rounding::<Up>();
let d = fbig!(0xffp - 8).with_rounding::<Up>();
test_add(&a, &b, &c);
test_sub(&a, &b, &d);

let a = fbig!(0x01).with_rounding::<Down>();
let b = fbig!(0x1p-8).with_rounding::<Down>();
let c = fbig!(0xffp-8).with_rounding::<Down>();
let b = fbig!(0x1p - 8).with_rounding::<Down>();
let c = fbig!(0xffp - 8).with_rounding::<Down>();
test_add(&a, &b, &a);
test_sub(&a, &b, &c);

let a = fbig!(0x01).with_rounding::<HalfAway>();
let b = fbig!(0x1p-8).with_rounding::<HalfAway>();
let c = fbig!(0x81p-7).with_rounding::<HalfAway>();
let d = fbig!(0xffp-8).with_rounding::<HalfAway>();
let b = fbig!(0x1p - 8).with_rounding::<HalfAway>();
let c = fbig!(0x81p - 7).with_rounding::<HalfAway>();
let d = fbig!(0xffp - 8).with_rounding::<HalfAway>();
test_add(&a, &b, &c);
test_sub(&a, &b, &d);

let a = fbig!(0x01).with_rounding::<HalfEven>();
let b = fbig!(0x1p-8).with_rounding::<HalfEven>();
let c = fbig!(0xffp-8).with_rounding::<HalfEven>();
let b = fbig!(0x1p - 8).with_rounding::<HalfEven>();
let c = fbig!(0xffp - 8).with_rounding::<HalfEven>();
test_add(&a, &b, &a);
test_sub(&a, &b, &c);


// rhs much less than lhs
let a = fbig!(0x01).with_rounding::<Zero>();
let b = fbig!(0x1p-100).with_rounding::<Zero>();
let c = fbig!(0xffp-8).with_rounding::<Zero>();
let b = fbig!(0x1p - 100).with_rounding::<Zero>();
let c = fbig!(0xffp - 8).with_rounding::<Zero>();
test_add(&a, &b, &a);
test_sub(&a, &b, &c);

let a = fbig!(0x01).with_rounding::<Up>();
let b = fbig!(0x1p-100).with_rounding::<Up>();
let c = fbig!(0x81p-7).with_rounding::<Up>();
let b = fbig!(0x1p - 100).with_rounding::<Up>();
let c = fbig!(0x81p - 7).with_rounding::<Up>();
test_add(&a, &b, &c);
test_sub(&a, &b, &a);

let a = fbig!(0x01).with_rounding::<Down>();
let b = fbig!(0x1p-100).with_rounding::<Down>();
let c = fbig!(0xffp-8).with_rounding::<Down>();
let b = fbig!(0x1p - 100).with_rounding::<Down>();
let c = fbig!(0xffp - 8).with_rounding::<Down>();
test_add(&a, &b, &a);
test_sub(&a, &b, &c);
}
}
26 changes: 19 additions & 7 deletions float/tests/exp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use dashu_base::Approximation::*;
use dashu_float::{round::Rounding::*, FBig, DBig};
use dashu_float::{round::Rounding::*, DBig, FBig};
use dashu_int::Word;

mod helper_macros;
Expand Down Expand Up @@ -344,6 +344,8 @@ fn test_powf_binary() {
assert_eq!(fbig!(0).powf(&fbig!(1)), fbig!(0));
assert_eq!(fbig!(1).powf(&fbig!(1)), fbig!(1));
assert_eq!(fbig!(1).powf(&fbig!(-1)), fbig!(1));
assert_eq!(fbig!(0).powf(&fbig!(0x2)), fbig!(0));
assert_eq!(fbig!(1).powf(&fbig!(0x2)), fbig!(1));

// cases for x^x and x^-x
let xx_inexact_cases = [
Expand Down Expand Up @@ -390,6 +392,8 @@ fn test_powf_decimal() {
assert_eq!(dbig!(0).powf(&dbig!(1)), dbig!(0));
assert_eq!(dbig!(1).powf(&dbig!(1)), dbig!(1));
assert_eq!(dbig!(1).powf(&dbig!(-1)), dbig!(1));
assert_eq!(dbig!(0).powf(&dbig!(2)), dbig!(0));
assert_eq!(dbig!(1).powf(&dbig!(2)), dbig!(1));

// cases for x^x and x^-x
let xx_inexact_cases = [
Expand Down Expand Up @@ -443,18 +447,26 @@ fn test_pow_with_rounding() {
use dashu_base::Abs;
use dashu_float::round::{mode::*, Round};

fn test_powf_with_error<R: Round, OpR: Round, const B: Word>(base: &FBig<R, B>, exp: &FBig<R, B>, target: &FBig<R, B>, atol: &FBig<R, B>) {
let result = base.clone().with_rounding::<OpR>().powf(&exp.clone().with_rounding::<OpR>());
fn test_powf_with_error<R: Round, OpR: Round, const B: Word>(
base: &FBig<R, B>,
exp: &FBig<R, B>,
target: &FBig<R, B>,
atol: &FBig<R, B>,
) {
let result = base
.clone()
.with_rounding::<OpR>()
.powf(&exp.clone().with_rounding::<OpR>());
let result_err = (result.with_rounding::<R>() - target).abs();
assert!(result_err <= *atol, "{}^{}, err: {} (>{})", base, exp, result_err, atol);
}

let binary_cases = [
// base, exp, target result
(fbig!(0x0010), fbig!(0x0001p4), fbig!(0x0001p64)),
(fbig!(0x0010), fbig!(-0x0001p4), fbig!(0x0001p-64)),
(fbig!(0x1234), fbig!(0x1234p-16), fbig!(0xe960p-15)),
(fbig!(0x1234), fbig!(-0x1234p-16), fbig!(0x8c69p-16)),
(fbig!(0x0010), fbig!(-0x0001p4), fbig!(0x0001p - 64)),
(fbig!(0x1234), fbig!(0x1234p - 16), fbig!(0xe960p - 15)),
(fbig!(0x1234), fbig!(-0x1234p - 16), fbig!(0x8c69p - 16)),
];

for (base, exp, target) in binary_cases {
Expand Down
18 changes: 11 additions & 7 deletions float/tests/log.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use dashu_base::Approximation::*;
use dashu_float::{round::Rounding::*, FBig, DBig};
use dashu_float::{round::Rounding::*, DBig, FBig};
use dashu_int::Word;

mod helper_macros;
Expand Down Expand Up @@ -204,18 +204,22 @@ fn test_ln_with_rounding() {
use dashu_base::Abs;
use dashu_float::round::{mode::*, Round};

fn test_ln_with_error<R: Round, OpR: Round, const B: Word>(base: &FBig<R, B>, target: &FBig<R, B>, atol: &FBig<R, B>) {
fn test_ln_with_error<R: Round, OpR: Round, const B: Word>(
base: &FBig<R, B>,
target: &FBig<R, B>,
atol: &FBig<R, B>,
) {
let result = base.clone().with_rounding::<OpR>().ln();
let result_err = (result.with_rounding::<R>() - target).abs();
assert!(result_err <= *atol, "ln({}), err: {} (>{})", base, result_err, atol);
}

let binary_cases = [
// base, target result
(fbig!(0x0010), fbig!(0xb172p-14)),
(fbig!(0x001f), fbig!(0xdbc6p-14)),
(fbig!(0x1234), fbig!(0x8726p-12)),
(fbig!(0x1abc), fbig!(0x8d4cp-12)),
(fbig!(0x0010), fbig!(0xb172p - 14)),
(fbig!(0x001f), fbig!(0xdbc6p - 14)),
(fbig!(0x1234), fbig!(0x8726p - 12)),
(fbig!(0x1abc), fbig!(0x8d4cp - 12)),
];

for (base, target) in binary_cases {
Expand Down

0 comments on commit 29875ff

Please sign in to comment.