blob: 9c06f6aaa31afe8888760f82ea060de023d435ba [file] [log] [blame]
use crate::traits::{Float, Integer, Sealed};
use core::time::Duration;
pub trait ConstPtr_v1_38<T>: Sealed<*const T> {
fn cast<U>(self) -> *const U;
}
impl<T> ConstPtr_v1_38<T> for *const T {
#[inline]
fn cast<U>(self) -> *const U {
self as _
}
}
pub trait MutPtr_v1_38<T>: Sealed<*mut T> {
fn cast<U>(self) -> *mut U;
}
impl<T> MutPtr_v1_38<T> for *mut T {
#[inline]
fn cast<U>(self) -> *mut U {
self as _
}
}
pub trait Duration_v1_38: Sealed<Duration> {
fn as_secs_f32(&self) -> f32;
fn as_secs_f64(&self) -> f64;
fn div_f32(&self, rhs: f32) -> Self;
fn div_f64(&self, rhs: f64) -> Self;
fn from_secs_f32(secs: f32) -> Self;
fn from_secs_f64(secs: f64) -> Self;
fn mul_f32(&self, rhs: f32) -> Self;
fn mul_f64(&self, rhs: f64) -> Self;
}
impl Duration_v1_38 for Duration {
#[inline]
fn as_secs_f32(&self) -> f32 {
(self.as_secs() as f32) + (self.subsec_nanos() as f32) / 1_000_000_000.
}
#[inline]
fn as_secs_f64(&self) -> f64 {
(self.as_secs() as f64) + (self.subsec_nanos() as f64) / 1_000_000_000.
}
#[inline]
fn div_f32(&self, rhs: f32) -> Self {
Self::from_secs_f32(self.as_secs_f32() / rhs)
}
#[inline]
fn div_f64(&self, rhs: f64) -> Self {
Self::from_secs_f64(self.as_secs_f64() / rhs)
}
#[inline]
fn from_secs_f32(secs: f32) -> Self {
const MAX_NANOS_F32: f32 = ((u64::max_value() as u128 + 1) * 1_000_000_000) as f32;
let nanos = secs * 1_000_000_000.;
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
}
if nanos >= MAX_NANOS_F32 {
panic!("overflow when converting float to duration");
}
if nanos < 0.0 {
panic!("underflow when converting float to duration");
}
let nanos = nanos as u128;
Self::new(
(nanos / 1_000_000_000) as u64,
(nanos % 1_000_000_000) as u32,
)
}
#[inline]
fn from_secs_f64(secs: f64) -> Self {
const MAX_NANOS_F64: f64 = ((u64::max_value() as u128 + 1) * 1_000_000_000) as f64;
let nanos = secs * 1_000_000_000.;
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
}
if nanos >= MAX_NANOS_F64 {
panic!("overflow when converting float to duration");
}
if nanos < 0.0 {
panic!("underflow when converting float to duration");
}
let nanos = nanos as u128;
Self::new(
(nanos / 1_000_000_000) as u64,
(nanos % 1_000_000_000) as u32,
)
}
#[inline]
fn mul_f32(&self, rhs: f32) -> Self {
Self::from_secs_f32(rhs * self.as_secs_f32())
}
#[inline]
fn mul_f64(&self, rhs: f64) -> Self {
Self::from_secs_f64(rhs * self.as_secs_f64())
}
}
pub trait Euclid_v1_38: Integer {
fn rem_euclid(self, rhs: Self) -> Self;
fn checked_rem_euclid(self, rhs: Self) -> Option<Self>;
fn wrapping_rem_euclid(self, rhs: Self) -> Self;
fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool);
fn div_euclid(self, rhs: Self) -> Self;
fn checked_div_euclid(self, rhs: Self) -> Option<Self>;
fn wrapping_div_euclid(self, rhs: Self) -> Self;
fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool);
}
macro_rules! impl_euclid_for_signed {
($($type:ty)+) => {$(
impl Euclid_v1_38 for $type {
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn rem_euclid(self, rhs: Self) -> Self {
let r = self % rhs;
if r < 0 {
if rhs < 0 {
r - rhs
} else {
r + rhs
}
} else {
r
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None
} else {
Some(self.rem_euclid(rhs))
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self.overflowing_rem_euclid(rhs).0
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 {
(0, true)
} else {
(self.rem_euclid(rhs), false)
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn div_euclid(self, rhs: Self) -> Self {
let q = self / rhs;
if self % rhs < 0 {
return if rhs > 0 { q - 1 } else { q + 1 };
}
q
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None
} else {
Some(self.div_euclid(rhs))
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn wrapping_div_euclid(self, rhs: Self) -> Self {
self.overflowing_div_euclid(rhs).0
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 {
(self, true)
} else {
(self.div_euclid(rhs), false)
}
}
}
)+};
}
impl_euclid_for_signed![i8 i16 i32 i64 i128 isize];
macro_rules! impl_euclid_for_unsigned {
($($type:ty)+) => {$(
impl Euclid_v1_38 for $type {
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn rem_euclid(self, rhs: Self) -> Self {
self % rhs
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 {
None
} else {
Some(self.rem_euclid(rhs))
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self % rhs
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
(self % rhs, false)
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn div_euclid(self, rhs: Self) -> Self {
self / rhs
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 {
None
} else {
Some(self.div_euclid(rhs))
}
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn wrapping_div_euclid(self, rhs: Self) -> Self {
self / rhs
}
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
(self / rhs, false)
}
}
)+};
}
impl_euclid_for_unsigned![u8 u16 u32 u64 u128 usize];
pub trait EuclidFloat_v1_38: Float {
fn rem_euclid(self, rhs: Self) -> Self;
fn div_euclid(self, rhs: Self) -> Self;
}
#[cfg(feature = "std")]
impl EuclidFloat_v1_38 for f32 {
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
fn rem_euclid(self, rhs: f32) -> f32 {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
fn div_euclid(self, rhs: f32) -> f32 {
let q = (self / rhs).trunc();
if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
}
q
}
}
#[cfg(feature = "std")]
impl EuclidFloat_v1_38 for f64 {
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
fn rem_euclid(self, rhs: f64) -> f64 {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
fn div_euclid(self, rhs: f64) -> f64 {
let q = (self / rhs).trunc();
if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
}
q
}
}