Skip to content
Closed
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
180 changes: 177 additions & 3 deletions src/scalar/fixed_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
//! Implementation of traits form fixed-point numbers.
use crate::scalar::{ComplexField, Field, RealField, SubsetOf};
use crate::simd::{PrimitiveSimdValue, SimdValue};
use fixed::traits::ToFixed;
use fixed::traits::{ToFixed, FromFixed};
use fixed::types::extra::{
IsLessOrEqual, LeEqU16, LeEqU32, LeEqU64, LeEqU8, True, Unsigned, U12, U13, U14, U15, U28, U29,
U30, U31, U4, U5, U6, U60, U61, U62, U63, U7,
};
use num::{Bounded, FromPrimitive, Num, One, Signed, Zero};
use num::{Bounded, ToPrimitive, FromPrimitive, Num, One, Signed, Zero};
#[cfg(feature = "serde_serialize")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
use std::iter::{Sum, Product};

macro_rules! impl_fixed_type(
($($FixedI: ident, $Int: ident, $LeEqDim: ident, $LeEqDim1: ident, $LeEqDim2: ident, $LeEqDim3: ident, $LeEqDim4: ident;)*) => {$(
Expand All @@ -27,12 +28,28 @@ macro_rules! impl_fixed_type(
impl<Fract: $LeEqDim> $FixedI<Fract> {
/// Creates a fixed-point number from another number.
#[inline(always)]
pub fn from_num<N: fixed::traits::ToFixed>(val: N) -> Self {
pub fn from_num<N: ToFixed>(val: N) -> Self {
$FixedI(fixed::$FixedI::from_num(val))
}

/// Creates a fixed-point number from another number.
#[inline(always)]
pub fn to_num<N: FromFixed>(self) -> N {
self.0.to_num()
}

/// Creates a fixed-point number from string literal.
#[inline(always)]
pub const fn lit(src: &str) -> Self {
$FixedI(fixed::$FixedI::lit(src))
}
}

impl<Fract> $FixedI<Fract> {
pub const EPSILON: $FixedI<Fract> = Self::from_bits(0b01);
pub const MAX: $FixedI<Fract> = $FixedI(fixed::$FixedI::MAX);
pub const MIN: $FixedI<Fract> = $FixedI(fixed::$FixedI::MIN);

/// Creates a fixed-point number that has a bitwise representation identical to the given integer.
#[inline(always)]
pub const fn from_bits(bits: $Int) -> Self {
Expand All @@ -46,6 +63,12 @@ macro_rules! impl_fixed_type(
}
}

impl<Fract: $LeEqDim> Default for $FixedI<Fract> {
fn default() -> Self {
$FixedI(fixed::$FixedI::default())
}
}

impl<Fract: $LeEqDim> PartialEq for $FixedI<Fract> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
Expand Down Expand Up @@ -138,6 +161,42 @@ macro_rules! impl_fixed_type(
}
}

impl<Fract: $LeEqDim> Sum for $FixedI<Fract> {
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold(
Self::zero(),
|a, b| a + b,
)
}
}

impl<'a, Fract: $LeEqDim> Sum<&'a $FixedI<Fract>> for $FixedI<Fract> {
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold(
Self::zero(),
|a, b| a + *b,
)
}
}

impl<Fract: $LeEqDim> Product for $FixedI<Fract> {
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
iter.fold(
Self::one(),
|a, b| a * b,
)
}
}

impl<'a, Fract: $LeEqDim> Product<&'a $FixedI<Fract> > for $FixedI<Fract> {
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
iter.fold(
Self::one(),
|a, b| a * *b,
)
}
}

impl<Fract: $LeEqDim> Mul for $FixedI<Fract> {
type Output = Self;
#[inline(always)]
Expand Down Expand Up @@ -338,6 +397,28 @@ macro_rules! impl_fixed_type(
}
}

impl<Fract: $LeEqDim> SubsetOf<$FixedI<Fract>> for u32 {
#[inline]
fn to_superset(&self) -> $FixedI<Fract> {
$FixedI(fixed::$FixedI::from_num(*self))
}

#[inline]
fn from_superset(element: &$FixedI<Fract>) -> Option<Self> {
Some(Self::from_superset_unchecked(element))
}

#[inline]
fn from_superset_unchecked(element: &$FixedI<Fract>) -> Self {
element.0.to_num::<u32>()
}

#[inline]
fn is_in_subset(_: &$FixedI<Fract>) -> bool {
true
}
}

impl<Fract: $LeEqDim> approx::AbsDiffEq for $FixedI<Fract> {
type Epsilon = Self;
fn default_epsilon() -> Self::Epsilon {
Expand Down Expand Up @@ -477,6 +558,45 @@ macro_rules! impl_fixed_type(
}
}

impl<Fract: $LeEqDim> ToPrimitive for $FixedI<Fract> {
fn to_i64(&self) -> Option<i64> {
self.0.checked_to_num()
}
fn to_u64(&self) -> Option<u64> {
self.0.checked_to_num()
}
fn to_isize(&self) -> Option<isize> {
self.0.checked_to_num()
}
fn to_i8(&self) -> Option<i8> {
self.0.checked_to_num()
}
fn to_i16(&self) -> Option<i16> {
self.0.checked_to_num()
}
fn to_i32(&self) -> Option<i32> {
self.0.checked_to_num()
}
fn to_usize(&self) -> Option<usize> {
self.0.checked_to_num()
}
fn to_u8(&self) -> Option<u8> {
self.0.checked_to_num()
}
fn to_u16(&self) -> Option<u16> {
self.0.checked_to_num()
}
fn to_u32(&self) -> Option<u32> {
self.0.checked_to_num()
}
fn to_f32(&self) -> Option<f32> {
self.0.checked_to_num()
}
fn to_f64(&self) -> Option<f64> {
self.0.checked_to_num()
}
}

impl<Fract: $LeEqDim> Signed for $FixedI<Fract> {
fn abs(&self) -> Self {
Self(self.0.abs())
Expand Down Expand Up @@ -791,6 +911,11 @@ macro_rules! impl_fixed_type(
self.0.is_negative()
}

#[inline]
fn is_nan(&self) -> bool {
false
}

#[inline]
fn copysign(self, sign: Self) -> Self {
if sign >= Self::zero() {
Expand Down Expand Up @@ -1072,3 +1197,52 @@ pub type FixedI7F57 = FixedI64<fixed::types::extra::U57>;
pub type FixedI6F58 = FixedI64<fixed::types::extra::U58>;
pub type FixedI5F59 = FixedI64<fixed::types::extra::U59>;
pub type FixedI4F60 = FixedI64<fixed::types::extra::U60>;

impl From<f32> for FixedI32F32 {
#[inline]
fn from(val: f32) -> Self {
Self::from_num(val)
}
}

impl From<f64> for FixedI32F32 {
#[inline]
fn from(val: f64) -> Self {
Self::from_num(val)
}
}

impl From<u32> for FixedI32F32 {
#[inline]
fn from(val: u32) -> Self {
Self::from_num(val)
}
}

impl From<i32> for FixedI32F32 {
#[inline]
fn from(val: i32) -> Self {
Self::from_num(val)
}
}

impl From<i16> for FixedI32F32 {
#[inline]
fn from(val: i16) -> Self {
Self::from_num(val)
}
}

impl From<FixedI32F32> for f64 {
#[inline]
fn from(val: FixedI32F32) -> Self {
val.to_num()
}
}

impl From<FixedI32F32> for isize {
#[inline]
fn from(val: FixedI32F32) -> Self {
val.to_num()
}
}
9 changes: 9 additions & 0 deletions src/scalar/real.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ pub trait RealField:
fn is_sign_positive(&self) -> bool;
/// Is the sign of this real number negative?
fn is_sign_negative(&self) -> bool;

// Returns true if the number is NaN.
fn is_nan(&self) -> bool;

/// Copies the sign of `sign` to `self`.
///
/// - Returns `self.simd_abs()` if `sign` is positive or positive-zero.
Expand Down Expand Up @@ -77,6 +81,11 @@ macro_rules! impl_real(
$M::is_sign_negative(*self)
}

#[inline]
fn is_nan(&self) -> bool {
$M::is_nan(*self)
}

#[inline(always)]
fn copysign(self, sign: Self) -> Self {
$cpysgn_mod::copysign(self, sign)
Expand Down
22 changes: 22 additions & 0 deletions src/simd/auto_simd_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use std::{
},
};

#[cfg(feature = "partial_fixed_point_support")]
use crate::scalar::FixedI32F32;

// This is a hack to allow use to reuse `_0` as integers or as identifier,
// depending on whether or not `ident_to_value` has been called in scope.
// This helps writing macros that define both `::new` and `From([T; lanes()])`.
Expand Down Expand Up @@ -230,6 +233,9 @@ impl_scalar_subset_of_simd!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,
#[cfg(feature = "decimal")]
impl_scalar_subset_of_simd!(d128);

#[cfg(feature = "partial_fixed_point_support")]
impl_scalar_subset_of_simd!(FixedI32F32);

macro_rules! impl_simd_value(
($($t: ty, $elt: ty, $lanes: expr, $bool: ty, $($i: ident),*;)*) => ($(
impl ArrTransform for AutoSimd<$t> {
Expand Down Expand Up @@ -1478,6 +1484,13 @@ impl_float_simd!(
[f64; 8], f64, 8, [i64; 8], AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
);

#[cfg(feature = "partial_fixed_point_support")]
impl_float_simd!(
[FixedI32F32; 2], FixedI32F32, 2, [i64; 2], AutoBoolx2, _0, _1;
[FixedI32F32; 4], FixedI32F32, 4, [i64; 4], AutoBoolx4, _0, _1, _2, _3;
[FixedI32F32; 8], FixedI32F32, 8, [i64; 8], AutoBoolx8, _0, _1, _2, _3, _4, _5, _6, _7;
);

impl_int_simd!(
[i128; 1], i128, 1, AutoBoolx1, _0;
[i128; 2], i128, 2, AutoBoolx2, _0, _1;
Expand Down Expand Up @@ -1634,6 +1647,15 @@ pub type AutoBoolx4 = AutoSimd<[bool; 4]>;
// pub type AutoBoolx64 = AutoSimd<[bool; 64]>;
pub type AutoBoolx8 = AutoSimd<[bool; 8]>;

#[cfg(feature = "partial_fixed_point_support")]
pub type AutoFixedI32F32x2 = AutoSimd<[FixedI32F32; 2]>;

#[cfg(feature = "partial_fixed_point_support")]
pub type AutoFixedI32F32x4 = AutoSimd<[FixedI32F32; 4]>;

#[cfg(feature = "partial_fixed_point_support")]
pub type AutoFixedI32F32x8 = AutoSimd<[FixedI32F32; 8]>;

/*
* Helper trait to transform an array.
*/
Expand Down