Skip to content

Commit

Permalink
Merge pull request #3 from bksaiki/cleanup
Browse files Browse the repository at this point in the history
Adds operators and other cleanup
  • Loading branch information
bksaiki authored Oct 11, 2023
2 parents 88b876a + d898076 commit e40a7ab
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 66 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ Supports IEEE-754 floating-point numbers, fixed-point numbers, and more.
Inspired by [FPCore](https://fpbench.org/) and
Bill Zorn's [Titanic](https://github.com/billzorn/titanic) library.

This library is hosted as a crate [here](https://crates.io/crates/mpmfnum).
The documentation can be found [here](https://docs.rs/mpmfnum/latest/mpmfnum/).

## Using mpmfnum

Add `mpmfnum` to your `Cargo.toml` like this:
Run the following Cargo command in your project directory:
```bash
cargo add mpmfnum
```
Or add `mpmfnum` to your `Cargo.toml` like this:
```toml
[dependencies]
mpmfnum = "0.1.0"
Expand Down
15 changes: 15 additions & 0 deletions src/fixed/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,33 @@ macro_rules! rounded_1ary_impl {
}

rounded_1ary_impl!(RoundedNeg, format_neg, neg, mpfr_neg);
rounded_1ary_impl!(RoundedAbs, format_abs, abs, mpfr_abs);
rounded_1ary_impl!(RoundedSqrt, format_sqrt, sqrt, mpfr_sqrt);
rounded_1ary_impl!(RoundedCbrt, format_cbrt, cbrt, mpfr_cbrt);
rounded_1ary_impl!(RoundedRecip, format_recip, recip, mpfr_recip);
rounded_1ary_impl!(
RoundedRecipSqrt,
format_recip_sqrt,
recip_sqrt,
mpfr_recip_sqrt
);
rounded_1ary_impl!(RoundedExp, format_exp, exp, mpfr_exp);
rounded_1ary_impl!(RoundedExp2, format_exp2, exp2, mpfr_exp2);
rounded_1ary_impl!(RoundedLog, format_log, log, mpfr_log);
rounded_1ary_impl!(RoundedLog2, format_log2, log2, mpfr_log2);
rounded_1ary_impl!(RoundedLog10, format_log10, log10, mpfr_log10);
rounded_1ary_impl!(RoundedExpm1, format_expm1, expm1, mpfr_expm1);
rounded_1ary_impl!(RoundedExp2m1, format_exp2m1, exp2m1, mpfr_exp2m1);
rounded_1ary_impl!(RoundedExp10m1, format_exp10m1, exp10m1, mpfr_exp10m1);
rounded_1ary_impl!(RoundedLog1p, format_log1p, log1p, mpfr_log1p);
rounded_1ary_impl!(RoundedLog2p1, format_log2p1, log2p1, mpfr_log2p1);
rounded_1ary_impl!(RoundedLog10p1, format_log10p1, log10p1, mpfr_log10p1);
rounded_1ary_impl!(RoundedSin, format_sin, sin, mpfr_sin);
rounded_1ary_impl!(RoundedCos, format_cos, cos, mpfr_cos);
rounded_1ary_impl!(RoundedTan, format_tan, tan, mpfr_tan);
rounded_1ary_impl!(RoundedSinPi, format_sin_pi, sin_pi, mpfr_sin_pi);
rounded_1ary_impl!(RoundedCosPi, format_cos_pi, cos_pi, mpfr_cos_pi);
rounded_1ary_impl!(RoundedTanPi, format_tan_pi, tan_pi, mpfr_tan_pi);
rounded_1ary_impl!(RoundedAsin, format_asin, asin, mpfr_asin);
rounded_1ary_impl!(RoundedAcos, format_acos, acos, mpfr_acos);
rounded_1ary_impl!(RoundedAtan, format_atan, atan, mpfr_atan);
Expand Down
15 changes: 15 additions & 0 deletions src/float/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,33 @@ macro_rules! rounded_1ary_impl {
}

rounded_1ary_impl!(RoundedNeg, format_neg, neg, mpfr_neg);
rounded_1ary_impl!(RoundedAbs, format_abs, abs, mpfr_abs);
rounded_1ary_impl!(RoundedSqrt, format_sqrt, sqrt, mpfr_sqrt);
rounded_1ary_impl!(RoundedCbrt, format_cbrt, cbrt, mpfr_cbrt);
rounded_1ary_impl!(RoundedRecip, format_recip, recip, mpfr_recip);
rounded_1ary_impl!(
RoundedRecipSqrt,
format_recip_sqrt,
recip_sqrt,
mpfr_recip_sqrt
);
rounded_1ary_impl!(RoundedExp, format_exp, exp, mpfr_exp);
rounded_1ary_impl!(RoundedExp2, format_exp2, exp2, mpfr_exp2);
rounded_1ary_impl!(RoundedLog, format_log, log, mpfr_log);
rounded_1ary_impl!(RoundedLog2, format_log2, log2, mpfr_log2);
rounded_1ary_impl!(RoundedLog10, format_log10, log10, mpfr_log10);
rounded_1ary_impl!(RoundedExpm1, format_expm1, expm1, mpfr_expm1);
rounded_1ary_impl!(RoundedExp2m1, format_exp2m1, exp2m1, mpfr_exp2m1);
rounded_1ary_impl!(RoundedExp10m1, format_exp10m1, exp10m1, mpfr_exp10m1);
rounded_1ary_impl!(RoundedLog1p, format_log1p, log1p, mpfr_log1p);
rounded_1ary_impl!(RoundedLog2p1, format_log2p1, log2p1, mpfr_log2p1);
rounded_1ary_impl!(RoundedLog10p1, format_log10p1, log10p1, mpfr_log10p1);
rounded_1ary_impl!(RoundedSin, format_sin, sin, mpfr_sin);
rounded_1ary_impl!(RoundedCos, format_cos, cos, mpfr_cos);
rounded_1ary_impl!(RoundedTan, format_tan, tan, mpfr_tan);
rounded_1ary_impl!(RoundedSinPi, format_sin_pi, sin_pi, mpfr_sin_pi);
rounded_1ary_impl!(RoundedCosPi, format_cos_pi, cos_pi, mpfr_cos_pi);
rounded_1ary_impl!(RoundedTanPi, format_tan_pi, tan_pi, mpfr_tan_pi);
rounded_1ary_impl!(RoundedAsin, format_asin, asin, mpfr_asin);
rounded_1ary_impl!(RoundedAcos, format_acos, acos, mpfr_acos);
rounded_1ary_impl!(RoundedAtan, format_atan, atan, mpfr_atan);
Expand Down
15 changes: 15 additions & 0 deletions src/ieee754/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,33 @@ macro_rules! rounded_1ary_impl {
}

rounded_1ary_impl!(RoundedNeg, format_neg, neg, mpfr_neg);
rounded_1ary_impl!(RoundedAbs, format_abs, abs, mpfr_abs);
rounded_1ary_impl!(RoundedSqrt, format_sqrt, sqrt, mpfr_sqrt);
rounded_1ary_impl!(RoundedCbrt, format_cbrt, cbrt, mpfr_cbrt);
rounded_1ary_impl!(RoundedRecip, format_recip, recip, mpfr_recip);
rounded_1ary_impl!(
RoundedRecipSqrt,
format_recip_sqrt,
recip_sqrt,
mpfr_recip_sqrt
);
rounded_1ary_impl!(RoundedExp, format_exp, exp, mpfr_exp);
rounded_1ary_impl!(RoundedExp2, format_exp2, exp2, mpfr_exp2);
rounded_1ary_impl!(RoundedLog, format_log, log, mpfr_log);
rounded_1ary_impl!(RoundedLog2, format_log2, log2, mpfr_log2);
rounded_1ary_impl!(RoundedLog10, format_log10, log10, mpfr_log10);
rounded_1ary_impl!(RoundedExpm1, format_expm1, expm1, mpfr_expm1);
rounded_1ary_impl!(RoundedExp2m1, format_exp2m1, exp2m1, mpfr_exp2m1);
rounded_1ary_impl!(RoundedExp10m1, format_exp10m1, exp10m1, mpfr_exp10m1);
rounded_1ary_impl!(RoundedLog1p, format_log1p, log1p, mpfr_log1p);
rounded_1ary_impl!(RoundedLog2p1, format_log2p1, log2p1, mpfr_log2p1);
rounded_1ary_impl!(RoundedLog10p1, format_log10p1, log10p1, mpfr_log10p1);
rounded_1ary_impl!(RoundedSin, format_sin, sin, mpfr_sin);
rounded_1ary_impl!(RoundedCos, format_cos, cos, mpfr_cos);
rounded_1ary_impl!(RoundedTan, format_tan, tan, mpfr_tan);
rounded_1ary_impl!(RoundedSinPi, format_sin_pi, sin_pi, mpfr_sin_pi);
rounded_1ary_impl!(RoundedCosPi, format_cos_pi, cos_pi, mpfr_cos_pi);
rounded_1ary_impl!(RoundedTanPi, format_tan_pi, tan_pi, mpfr_tan_pi);
rounded_1ary_impl!(RoundedAsin, format_asin, asin, mpfr_asin);
rounded_1ary_impl!(RoundedAcos, format_acos, acos, mpfr_acos);
rounded_1ary_impl!(RoundedAtan, format_atan, atan, mpfr_atan);
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
//! rounds a [`Real`] value to a floating-point number as described by
//! the IEEE 754 standard,
//! - [`FixedContext`][crate::fixed::FixedContext]
//! rounds a [`Real`] value to a fixed-point,
//! rounds a [`Real`] value to a fixed-point numbers.
//!
//! Planned support for posits and more!
//!
Expand Down
70 changes: 52 additions & 18 deletions src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ pub struct RTOResult {
}

impl RTOResult {
/// Constructs an [`RTOResult`] from an MPFR result.
pub fn new(val: Float, t: i32, flags: MPFRFlags, prec: usize) -> Self {
Self {
num: RFloat::from(val).with_ternary(t),
prec,
flags,
}
}

/// The numerical result of an operation.
pub fn num(&self) -> &RFloat {
&self.num
Expand Down Expand Up @@ -87,12 +96,8 @@ macro_rules! mpfr_1ary {
(t, mpfr_flags())
};

// apply correction to get the last bit and compose
RTOResult {
num: RFloat::from(dst).with_ternary(t),
prec: p,
flags,
}
// compose result
RTOResult::new(dst, t, flags, p)
}
};
}
Expand Down Expand Up @@ -126,12 +131,8 @@ macro_rules! mpfr_2ary {
(t, mpfr_flags())
};

// apply correction to get the last bit and compose
RTOResult {
num: RFloat::from(dst).with_ternary(t),
prec: p,
flags,
}
// compose result
RTOResult::new(dst, t, flags, p)
}
};
}
Expand Down Expand Up @@ -167,31 +168,36 @@ macro_rules! mpfr_3ary {
(t, mpfr_flags())
};

// apply correction to get the last bit and compose
RTOResult {
num: RFloat::from(dst).with_ternary(t),
prec: p,
flags,
}
// compose result
RTOResult::new(dst, t, flags, p)
}
};
}

// Unary operators
mpfr_1ary!(mpfr_neg, neg, "(- x)");
mpfr_1ary!(mpfr_abs, abs, "|x|");
mpfr_1ary!(mpfr_sqrt, sqrt, "sqrt(x)");
mpfr_1ary!(mpfr_cbrt, cbrt, "cbrt(x)");
mpfr_1ary!(mpfr_recip_sqrt, rec_sqrt, "1/sqrt(x)");
mpfr_1ary!(mpfr_exp, exp, "exp(x)");
mpfr_1ary!(mpfr_exp2, exp2, "2^x");
mpfr_1ary!(mpfr_exp10, exp10, "exp10(x)");
mpfr_1ary!(mpfr_log, log, "ln(x)");
mpfr_1ary!(mpfr_log2, log2, "log2(x)");
mpfr_1ary!(mpfr_log10, log10, "log10(x)");
mpfr_1ary!(mpfr_expm1, expm1, "e^x - 1");
mpfr_1ary!(mpfr_exp2m1, exp2m1, "2^x - 1");
mpfr_1ary!(mpfr_exp10m1, exp10m1, "10^x - 1");
mpfr_1ary!(mpfr_log1p, log1p, "ln(x + 1)");
mpfr_1ary!(mpfr_log2p1, log2p1, "log2(x + 1)");
mpfr_1ary!(mpfr_log10p1, log10p1, "log10(x + 1)");
mpfr_1ary!(mpfr_sin, sin, "sin(x)");
mpfr_1ary!(mpfr_cos, cos, "cos(x)");
mpfr_1ary!(mpfr_tan, tan, "tan(x)");
mpfr_1ary!(mpfr_sin_pi, sinpi, "sin(pi * x)");
mpfr_1ary!(mpfr_cos_pi, cospi, "cos(pi * x)");
mpfr_1ary!(mpfr_tan_pi, tanpi, "tan(pi * x)");
mpfr_1ary!(mpfr_asin, asin, "arcsin(x)");
mpfr_1ary!(mpfr_acos, acos, "arccos(x)");
mpfr_1ary!(mpfr_atan, atan, "arctan(x)");
Expand Down Expand Up @@ -219,3 +225,31 @@ mpfr_2ary!(mpfr_atan2, atan2, "arctan(y / x)");

// Ternary operators
mpfr_3ary!(mpfr_fma, fma, "a * b + c");

// Special operators

/// Computes `1/x` to `p` binary digits of precision, rounding to odd.
pub fn mpfr_recip(src: RFloat, p: usize) -> RTOResult {
assert!(
p as i64 > mpfr::PREC_MIN && p as i64 <= mpfr::PREC_MAX,
"precision must be between {} and {}",
mpfr::PREC_MIN + 1,
mpfr::PREC_MAX
);

// compute with `p - 1` bits
let mut dst = Float::new((p - 1) as u32);
let src = Float::from(src);
let (t, flags) = unsafe {
mpfr::clear_flags();
let t = mpfr::ui_div(dst.as_raw_mut(), 1, src.as_raw(), mpfr::rnd_t::RNDZ);
(t, mpfr_flags())
};

// apply correction to get the last bit and compose
RTOResult {
num: RFloat::from(dst).with_ternary(t),
prec: p,
flags,
}
}
26 changes: 18 additions & 8 deletions src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use crate::{Real, RoundingContext};

macro_rules! rounded_1ary {
($trait:ident, $imp:ident, $mpmf:ident, $descr:expr) => {
#[doc = "Rounded "]
#[doc = "Rounded `"]
#[doc = $descr]
#[doc = " for rounding contexts."]
#[doc = "` for rounding contexts."]
pub trait $trait: RoundingContext {
#[doc = "Performs rounded `"]
#[doc = $descr]
Expand All @@ -31,18 +31,28 @@ macro_rules! rounded_1ary {

// Traits for 1-ary operators
rounded_1ary!(RoundedNeg, format_neg, neg, "-x");
rounded_1ary!(RoundedAbs, format_abs, abs, "|x|");
rounded_1ary!(RoundedSqrt, format_sqrt, sqrt, "sqrt(x)");
rounded_1ary!(RoundedCbrt, format_cbrt, cbrt, "cbrt(x)");
rounded_1ary!(RoundedRecip, format_recip, recip, "1/x");
rounded_1ary!(RoundedRecipSqrt, format_recip_sqrt, recip_sqrt, "1/sqrt(x)");
rounded_1ary!(RoundedExp, format_exp, exp, "exp(x)");
rounded_1ary!(RoundedExp2, format_exp2, exp2, "2^x");
rounded_1ary!(RoundedLog, format_log, log, "ln(x)");
rounded_1ary!(RoundedLog2, format_log2, log2, "log2(x)");
rounded_1ary!(RoundedLog10, format_log10, log10, "log10(x)");
rounded_1ary!(RoundedExpm1, format_expm1, expm1, "expm1(x)");
rounded_1ary!(RoundedLog1p, format_log1p, log1p, "log1p(x)");
rounded_1ary!(RoundedExpm1, format_expm1, expm1, "e^x - 1");
rounded_1ary!(RoundedExp2m1, format_exp2m1, exp2m1, "2^x - 1");
rounded_1ary!(RoundedExp10m1, format_exp10m1, exp10m1, "10^x - 1");
rounded_1ary!(RoundedLog1p, format_log1p, log1p, "log(x + 1)");
rounded_1ary!(RoundedLog2p1, format_log2p1, log2p1, "log2(x + 1)");
rounded_1ary!(RoundedLog10p1, format_log10p1, log10p1, "log10(x + 1)");
rounded_1ary!(RoundedSin, format_sin, sin, "sin(x)");
rounded_1ary!(RoundedCos, format_cos, cos, "cos(x)");
rounded_1ary!(RoundedTan, format_tan, tan, "tan(x)");
rounded_1ary!(RoundedSinPi, format_sin_pi, sin_pi, "sin(pi * x)");
rounded_1ary!(RoundedCosPi, format_cos_pi, cos_pi, "cos(pi * x)");
rounded_1ary!(RoundedTanPi, format_tan_pi, tan_pi, "tan(pi * x)");
rounded_1ary!(RoundedAsin, format_asin, asin, "arcsin(x)");
rounded_1ary!(RoundedAcos, format_acos, acos, "arccos(x)");
rounded_1ary!(RoundedAtan, format_atan, atan, "arctan(x)");
Expand All @@ -59,9 +69,9 @@ rounded_1ary!(RoundedLgamma, format_lgamma, lgamma, "lgamma(x)");

macro_rules! rounded_2ary {
($trait:ident, $imp:ident, $mpmf:ident, $descr:expr) => {
#[doc = "Rounded "]
#[doc = "Rounded `"]
#[doc = $descr]
#[doc = " for rounding contexts."]
#[doc = "` for rounding contexts."]
pub trait $trait: RoundingContext {
#[doc = "Performs rounded `"]
#[doc = $descr]
Expand Down Expand Up @@ -99,9 +109,9 @@ rounded_2ary!(RoundedAtan2, format_atan2, atan2, "arctan(y / x)");

macro_rules! rounded_3ary {
($trait:ident, $imp:ident, $mpmf:ident, $descr:expr) => {
#[doc = "Rounded "]
#[doc = "Rounded `"]
#[doc = $descr]
#[doc = " for rounding contexts."]
#[doc = "` for rounding contexts."]
pub trait $trait: RoundingContext {
#[doc = "Performs rounded `"]
#[doc = $descr]
Expand Down
13 changes: 12 additions & 1 deletion src/real/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use crate::{
ops::{RoundedAdd, RoundedMul, RoundedNeg, RoundedSub},
ops::{RoundedAbs, RoundedAdd, RoundedMul, RoundedNeg, RoundedSub},
rfloat::RFloat,
Real, RoundingContext,
};
Expand All @@ -22,6 +22,17 @@ impl RoundedNeg for RealContext {
}
}

impl RoundedAbs for RealContext {
fn abs<N: Real>(&self, src: &N) -> Self::Rounded {
let src = self.round(src); // convert (exactly) to RFloat
match src {
RFloat::Real(_, exp, c) => RFloat::Real(false, exp, c),
RFloat::Infinite(_) => RFloat::Infinite(false),
RFloat::Nan => RFloat::Nan,
}
}
}

impl RoundedAdd for RealContext {
fn add<N1, N2>(&self, src1: &N1, src2: &N2) -> Self::Rounded
where
Expand Down
Loading

0 comments on commit e40a7ab

Please sign in to comment.