Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pow #35

Merged
merged 5 commits into from
Nov 4, 2023
Merged

pow #35

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,12 @@ To facilitate comparisons, the methods `is_positive_zero` and `is_negative_zero`

# Methods implemented

All 12 types implement the methods available on [`f32`] and [`f64`] except:
All 12 types implement the methods available on [`f32`] and [`f64`] **except**:

- deprecated and nightly-only methods
- total_cmp(&self, other: &f64) -> Ordering
- sin_cos(self) -> (f64, f64)
- mul_add(self, a: f64, b: f64) -> f64
- powi(self, n: i32) -> f64
- powf(self, n: f64) -> f64
- clamp(self, min: f64, max: f64) -> f64
- LowerExp
- UpperExp
Expand Down
9 changes: 9 additions & 0 deletions typed_floats/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,15 @@ pub trait Atan2<T> {
fn atan2(self, rhs: T) -> Self::Output;
}

/// This trait is used to specify the return type of the [`Powf::powf()`] function.
pub trait Powf<T> {
/// The resulting type after applying [`Powf::powf()`].
type Output;

/// See [`f64::powf()`] for more details.
fn powf(self, rhs: T) -> Self::Output;
}

typed_floats_macros::generate_docs!(
pub trait TypedFloat {}
);
Expand Down
3 changes: 3 additions & 0 deletions typed_floats/tests/powf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use typed_floats::*;

typed_floats_macros::generate_tests_self_rhs!(powf);
3 changes: 3 additions & 0 deletions typed_floats/tests/powi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use typed_floats::*;

typed_floats_macros::generate_tests_self!(powi);
4 changes: 2 additions & 2 deletions typed_floats_macros/src/gen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub(crate) fn generate_tests_self(

// Execute the operation, will throw if the result type is too strict
let res = #test;
println!("{:?} = {:?}",#op_name, res);
println!("{:?}({:?}) = {:?}",#op_name, a, res);

// Get the result as a float
let as_float = #get;
Expand Down Expand Up @@ -263,7 +263,7 @@ pub(crate) fn generate_tests_self_rhs(
println!("{:?} = ...",#op_name);
// This will panic if the result isn't compatible with the return type
let res = #test;
println!("{:?} = {:?}",#op_name, res);
println!("{:?}({:?},{:?}) = {:?}",#op_name, a, b, res);

let f: #float_type = #get;

Expand Down
43 changes: 43 additions & 0 deletions typed_floats_macros/src/impl_self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,5 +1070,48 @@ pub(crate) fn get_impl_self() -> Vec<Op> {
})
}))
.build(),
OpBuilder::new("powi")
.params(quote! {self, n: i32})
.op_fn(Box::new(|_| {
let n = syn::Ident::new("n", proc_macro2::Span::call_site());

quote! { self.get().powi(#n) }
}))
.description(quote! {
/// Raises a number to an integer power.
///
/// Using this function is generally faster than using `powf`.
/// It might have a different sequence of rounding operations than `powf`,
/// so the results are not guaranteed to agree.
///
/// # Examples
///
/// ```
/// # use typed_floats::*;
/// let x: NonNaN = (-2.0).try_into().unwrap();
///
/// assert_eq!(x.powi(3), -8.0);
/// assert_eq!(x.powi(2), 4.0);
/// assert_eq!(x.powi(1), -2.0);
/// assert_eq!(x.powi(0), 1.0);
/// assert_eq!(x.powi(-1), -0.5);
/// assert_eq!(x.powi(-2), 0.25);
/// assert_eq!(x.powi(-3), -0.125);
/// ```
/// See [`f64::powi()`] for more details.
})
.result(Box::new(|float| {
ReturnTypeSpecification::FloatSpecifications(FloatSpecifications {
accept_negative: float.s.accept_negative,
accept_positive: true,
accept_zero: true,
accept_inf: true,
})
}))
.skip_check_return_type_strictness()
.op_test(Box::new(|var| {
quote! { #var.powi(2) }
}))
.build(),
]
}
16 changes: 16 additions & 0 deletions typed_floats_macros/src/impl_self_rhs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,5 +353,21 @@ pub(crate) fn get_impl_self_rhs() -> Vec<OpRhs> {
})
}))
.build(),
OpRhsBuilder::new("Powf", "powf")
.op_test_primitive(Box::new(|var1, var2| quote! { #var1.powf(#var2) }))
.comment("If the base is negative and the exponent is not an integer, the result is `NaN`.")
.result(Box::new(|float, _| {
if float.s.accept_negative {
ReturnTypeSpecification::NativeFloat
} else {
ReturnTypeSpecification::FloatSpecifications(FloatSpecifications {
accept_negative: false,
accept_positive: true,
accept_zero: true,
accept_inf: true,
})
}
}))
.build(),
]
}
25 changes: 0 additions & 25 deletions typed_floats_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,31 +540,6 @@ fn do_generate_floats(floats: &[FloatDefinition]) -> proc_macro2::TokenStream {
pub fn is_positive_zero(&self) -> bool {
self.0 == 0.0 && self.0.is_sign_positive()
}

/// Return the ordering between `self` and `other`.
///
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
/// the `totalOrder` predicate as defined in the IEEE 754 (2008 revision)
/// floating point standard. The values are ordered in the following sequence:
///
/// - negative infinity
/// - negative numbers
/// - negative subnormal numbers
/// - negative zero
/// - positive zero
/// - positive subnormal numbers
/// - positive numbers
/// - positive infinity
///
/// The ordering established by this function does not always agree with the
/// [`PartialOrd`] and [`PartialEq`] implementations of `f64`:
/// they consider negative and positive zero equal, while `total_cmp` doesn't.
#[inline]
#[must_use]
pub fn total_cmp(&self, other: &#float_type) -> core::cmp::Ordering {
self.0.total_cmp(other)
}
}

impl PartialEq for #full_type {
Expand Down
13 changes: 11 additions & 2 deletions typed_floats_macros/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ pub(crate) struct Op {
pub(crate) fn_name: &'static str,
pub(crate) trait_name: Option<&'static str>,
pub(crate) comment: Option<&'static str>,
pub(crate) params: proc_macro2::TokenStream,
pub(crate) description: proc_macro2::TokenStream,
pub(crate) skip_check_return_type_strictness: bool,
op: OpCallback,
Expand All @@ -218,6 +219,7 @@ impl OpBuilder {
key: fn_name,
display: fn_name,
fn_name,
params: quote! { self },
trait_name: None,
description: proc_macro2::TokenStream::new(),
comment: None,
Expand Down Expand Up @@ -254,6 +256,11 @@ impl OpBuilder {
self
}

pub fn params(mut self, params: proc_macro2::TokenStream) -> Self {
self.op.params = params;
self
}

pub fn description(mut self, description: proc_macro2::TokenStream) -> Self {
self.op.description = description;
self
Expand Down Expand Up @@ -327,6 +334,8 @@ impl Op {

let description = &self.description;

let params = &self.params;

if let Some(trait_name) = &self.trait_name {
let trait_name: proc_macro2::TokenStream = trait_name.parse().unwrap();

Expand All @@ -337,7 +346,7 @@ impl Op {
#description
#[inline]
#[must_use]
fn #fn_ident(self) -> Self::Output {
fn #fn_ident(#params) -> Self::Output {
#return_value
}
}
Expand All @@ -348,7 +357,7 @@ impl Op {
#description
#[inline]
#[must_use]
pub fn #fn_ident(self) -> #output_name {
pub fn #fn_ident(#params) -> #output_name {
#return_value
}
}
Expand Down