use std::{
cmp::Ordering,
num::FpCategory,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
};
use num_traits::{Float, Num, NumCast, One, ToPrimitive, Zero};
mod consts {
use super::f128;
pub fn pi() -> f128 {
f128::new(std::f64::consts::PI)
}
pub fn ln_2() -> f128 {
f128::new(std::f64::consts::LN_2)
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
pub struct f128(f64);
impl f128 {
pub fn new<T: ToPrimitive>(f: T) -> Self {
NumCast::from(f).unwrap()
}
}
impl PartialEq for f128 {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl PartialOrd for f128 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl Zero for f128 {
fn zero() -> Self {
Self(0.0)
}
fn set_zero(&mut self) {
self.0 = 0.0
}
fn is_zero(&self) -> bool {
self.0 == 0.0
}
}
impl Neg for f128 {
type Output = Self;
fn neg(self) -> Self::Output {
Self(self.0.neg())
}
}
impl Add for f128 {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl AddAssign for f128 {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs
}
}
impl Sub for f128 {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}
impl SubAssign for f128 {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs
}
}
impl Mul for f128 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0)
}
}
impl MulAssign for f128 {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs
}
}
impl Div for f128 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
Self(self.0 / rhs.0)
}
}
impl DivAssign for f128 {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs
}
}
impl Rem for f128 {
type Output = Self;
fn rem(self, rhs: Self) -> Self::Output {
Self(self.0 % rhs.0)
}
}
impl RemAssign for f128 {
fn rem_assign(&mut self, rhs: Self) {
*self = *self % rhs
}
}
impl One for f128 {
fn one() -> Self {
Self(1.0)
}
fn set_one(&mut self) {
self.0 = 1.0
}
}
impl Num for f128 {
type FromStrRadixErr = ();
fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
unimplemented!()
}
}
impl NumCast for f128 {
fn from<T: ToPrimitive>(n: T) -> Option<Self> {
n.to_f64().map(Self)
}
}
impl ToPrimitive for f128 {
fn to_isize(&self) -> Option<isize> {
self.0.to_isize()
}
fn to_i8(&self) -> Option<i8> {
self.0.to_i8()
}
fn to_i16(&self) -> Option<i16> {
self.0.to_i16()
}
fn to_i32(&self) -> Option<i32> {
self.0.to_i32()
}
fn to_i64(&self) -> Option<i64> {
self.0.to_i64()
}
fn to_i128(&self) -> Option<i128> {
self.0.to_i128()
}
fn to_usize(&self) -> Option<usize> {
self.0.to_usize()
}
fn to_u8(&self) -> Option<u8> {
self.0.to_u8()
}
fn to_u16(&self) -> Option<u16> {
self.0.to_u16()
}
fn to_u32(&self) -> Option<u32> {
self.0.to_u32()
}
fn to_u64(&self) -> Option<u64> {
self.0.to_u64()
}
fn to_u128(&self) -> Option<u128> {
self.0.to_u128()
}
fn to_f32(&self) -> Option<f32> {
Some(self.0 as f32)
}
fn to_f64(&self) -> Option<f64> {
Some(self.0)
}
}
impl Float for f128 {
fn nan() -> Self {
Self(f64::nan())
}
fn infinity() -> Self {
Self(f64::infinity())
}
fn neg_infinity() -> Self {
Self(f64::NEG_INFINITY)
}
fn neg_zero() -> Self {
Self(-0.0)
}
fn min_value() -> Self {
Self(f64::MIN)
}
fn min_positive_value() -> Self {
Self(f64::MIN_POSITIVE)
}
fn epsilon() -> Self {
Self(f64::EPSILON)
}
fn max_value() -> Self {
Self(f64::MAX)
}
fn is_nan(self) -> bool {
self.0.is_nan()
}
fn is_infinite(self) -> bool {
self.0.is_infinite()
}
fn is_finite(self) -> bool {
self.0.is_finite()
}
fn is_normal(self) -> bool {
self.0.is_normal()
}
fn classify(self) -> FpCategory {
self.0.classify()
}
fn floor(self) -> Self {
Self(self.0.floor())
}
fn ceil(self) -> Self {
Self(self.0.ceil())
}
fn round(self) -> Self {
Self(self.0.round())
}
fn trunc(self) -> Self {
Self(self.0.trunc())
}
fn fract(self) -> Self {
Self(self.0.fract())
}
fn abs(self) -> Self {
Self(self.0.abs())
}
fn signum(self) -> Self {
Self(self.0.signum())
}
fn is_sign_positive(self) -> bool {
self.0.is_sign_positive()
}
fn is_sign_negative(self) -> bool {
self.0.is_sign_negative()
}
fn mul_add(self, a: Self, b: Self) -> Self {
Self(self.0.mul_add(a.0, b.0))
}
fn recip(self) -> Self {
Self(self.0.recip())
}
fn powi(self, n: i32) -> Self {
Self(self.0.powi(n))
}
fn powf(self, n: Self) -> Self {
Self(self.0.powf(n.0))
}
fn sqrt(self) -> Self {
Self(self.0.sqrt())
}
fn exp(self) -> Self {
Self(self.0.exp())
}
fn exp2(self) -> Self {
Self(self.0.exp2())
}
fn ln(self) -> Self {
Self(self.0.ln())
}
fn log(self, base: Self) -> Self {
Self(self.0.log(base.0))
}
fn log2(self) -> Self {
Self(self.0.log2())
}
fn log10(self) -> Self {
Self(self.0.log10())
}
fn to_degrees(self) -> Self {
Self(self.0.to_degrees())
}
fn to_radians(self) -> Self {
Self(self.0.to_radians())
}
fn max(self, other: Self) -> Self {
Self(self.0.max(other.0))
}
fn min(self, other: Self) -> Self {
Self(self.0.min(other.0))
}
fn abs_sub(self, other: Self) -> Self {
Self((self.0 - other.0).abs())
}
fn cbrt(self) -> Self {
Self(self.0.cbrt())
}
fn hypot(self, other: Self) -> Self {
Self(self.0.hypot(other.0))
}
fn sin(self) -> Self {
Self(self.0.sin())
}
fn cos(self) -> Self {
Self(self.0.cos())
}
fn tan(self) -> Self {
Self(self.0.tan())
}
fn asin(self) -> Self {
Self(self.0.asin())
}
fn acos(self) -> Self {
Self(self.0.acos())
}
fn atan(self) -> Self {
Self(self.0.atan())
}
fn atan2(self, other: Self) -> Self {
Self(self.0.atan2(other.0))
}
fn sin_cos(self) -> (Self, Self) {
let (r1, r2) = self.0.sin_cos();
(Self(r1), Self(r2))
}
fn exp_m1(self) -> Self {
Self(self.0.exp_m1())
}
fn ln_1p(self) -> Self {
Self(self.0.ln_1p())
}
fn sinh(self) -> Self {
Self(self.0.sinh())
}
fn cosh(self) -> Self {
Self(self.0.cosh())
}
fn tanh(self) -> Self {
Self(self.0.tanh())
}
fn asinh(self) -> Self {
Self(self.0.asinh())
}
fn acosh(self) -> Self {
Self(self.0.acosh())
}
fn atanh(self) -> Self {
Self(self.0.atanh())
}
fn integer_decode(self) -> (u64, i16, i8) {
self.0.integer_decode()
}
}