// Copyright 2025 Gabriel Bjørnager Jensen.

mod test;

use crate::{Array, FloatToInt, Uint};
use crate::compat::{
	CloneToUninit,
	ConstParamTy_,
	Freeze,
	Thin,
	ToOwned,
	UseCloned,
};

use core::any::Any;
use core::cmp::Ordering;
use core::convert::Infallible;
use core::fmt::Debug;
use core::hash::Hash;
use core::iter::{Product, Sum};
use core::num::FpCategory;
use core::ops::{
	Add,
	AddAssign,
	Div,
	DivAssign,
	Mul,
	MulAssign,
	Neg,
	Rem,
	RemAssign,
	Sub,
	SubAssign,
};
use core::panic::{RefUnwindSafe, UnwindSafe};

#[cfg(doc)]
use core::f64;

/// A generic, floating-point real.
///
/// This trait abstracts the interfaces defined by [`f16`], [`f32`], [`prim@f64`], and [`f128`] so that these may be used as a single type.
///
/// The following trait(s) are not required due to some floating-point types not implementing them:
/// * [`Display`](core::fmt::Display): Not implement by `f128`
/// * <code>[From](core::convert::From)&lt;f16&gt;</code>: Not implement by `f32`
/// * [`FromStr`](core::str::FromStr): Not implement by `f128`
/// * [`LowerExp`](core::fmt::LowerExp): Not implement by `f128`
#[cfg_attr(feature = "alloc", doc = "* [`ToString`](alloc::string::ToString): Not implemented by `f128`\n")]
/// * [`UpperExp`](core::fmt::UpperExp): Not implement by `f128`
///
/// These trait(s) will be required when standard support arrives.
///
#[cfg_attr(feature = "f128",      doc = "See also [`FloatLeast32`](crate::FloatLeast32) and [`FloatLeast64`](crate::FloatLeast64).\n")]
#[cfg_attr(not(feature = "f128"), doc = "See also [`FloatLeast32`](crate::FloatLeast32).\n")]
#[cfg_attr(feature = "std",       doc = "See also [`StdFloat`](crate::StdFloat).\n")]
///
/// # Safety
///
/// [`Bits`](Self::Bits) must be an unsigned, integral type of the same width as `Self` so that transmutations between the two is always valid.
///
/// Furthermore, all items must behave exactly as their standard counterparts.
pub unsafe trait Float
where
	Self:
		crate::seal::Float
		+ 'static
		+ Any
		+ CloneToUninit
		+ Copy
		+ Debug
		+ Default
		+ FloatToInt<i128>
		+ FloatToInt<i16>
		+ FloatToInt<i32>
		+ FloatToInt<i64>
		+ FloatToInt<i8>
		+ FloatToInt<isize>
		+ FloatToInt<u128>
		+ FloatToInt<u16>
		+ FloatToInt<u32>
		+ FloatToInt<u64>
		+ FloatToInt<u8>
		+ FloatToInt<usize>
		+ Freeze
		+ From<bool>
		//+ From<f16> // Noobs say that we can't handle it.
		+ From<i8>
		+ From<u8>
		+ PartialEq
		+ PartialOrd
		+ Product
		+ RefUnwindSafe
		+ Send
		+ Sum
		+ Sync
		+ Thin
		+ ToOwned
		+ TryFrom<bool, Error = Infallible>
		//+ TryFrom<f16,  Error = Infallible>
		+ TryFrom<i8,   Error = Infallible>
		+ TryFrom<u8,   Error = Infallible>
		+ Unpin
		+ UnwindSafe
		+ UseCloned
		// Arithmetic operators:
		+ Add<Output = Self>
		+ Div<Output = Self>
		+ Mul<Output = Self>
		+ Neg<Output = Self>
		+ Rem<Output = Self>
		+ Sub<Output = Self>
		// Assigning arithmetic operators:
		+ AddAssign
		+ DivAssign
		+ MulAssign
		+ RemAssign
		+ SubAssign,
{
	/// The array type that represents the bytes of this type.
	///
	/// This type is always <code>\[[u8]; [size_of]::&lt;Self&gt;\]</code>.
	type Bytes:
		Array<Scalar = u8>
		+ 'static
		+ Any
		+ CloneToUninit
		+ ConstParamTy_
		+ Copy
		+ Debug
		+ Eq
		+ Freeze
		+ Hash
		+ Ord
		+ PartialEq
		+ PartialEq<[u8]>
		+ PartialOrd
		+ RefUnwindSafe
		+ Send
		+ Sync
		+ ToOwned
		+ Unpin
		+ UnwindSafe;

	/// The scalar type that represents the bits of this type.
	type Bits: Uint<Bytes = Self::Bytes>;

	/// See <code>[prim@f64]::[RADIX](f64::RADIX)</code>.
	const RADIX:           u32;

	/// See <code>[prim@f64]::[MANTISSA_DIGITS](f64::MANTISSA_DIGITS)</code>.
	const MANTISSA_DIGITS: u32;

	/// See <code>[prim@f64]::[DIGITS](f64::DIGITS)</code>.
	const DIGITS:          u32;

	/// See <code>[prim@f64]::[EPSILON](f64::EPSILON)</code>.
	const EPSILON:         Self;

	/// See <code>[prim@f64]::[MIN](f64::MIN)</code>.
	const MIN:             Self;

	/// See <code>[prim@f64]::[MIN_POSITIVE](f64::MIN_POSITIVE)</code>.
	const MIN_POSITIVE:    Self;

	/// See <code>[prim@f64]::[MAX](f64::MAX)</code>.
	const MAX:             Self;

	/// See <code>[prim@f64]::[INFINITY](f64::INFINITY)</code>.
	const INFINITY:        Self;

	/// See <code>[prim@f64]::[NEG_INFINITY](f64::NEG_INFINITY)</code>.
	const NEG_INFINITY:    Self;

	/// See <code>[prim@f64]::[NAN](f64::NAN)</code>.
	const NAN:             Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[E](f64::consts::E)</code>.
	const E:               Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[PI](f64::consts::PI)</code>.
	const PI:              Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[TAU](f64::consts::TAU)</code>.
	const TAU:             Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LOG2_10](f64::consts::LOG2_10)</code>.
	const LOG2_10:         Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LOG2_E](f64::consts::LOG2_E)</code>.
	const LOG2_E:          Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LN_2](f64::consts::LN_2)</code>.
	const LN_2:            Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LN_10](f64::consts::LN_10)</code>.
	const LN_10:           Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LOG10_2](f64::consts::LOG10_2)</code>.
	const LOG10_2:         Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[LOG10_E](f64::consts::LOG10_E)</code>.
	const LOG10_E:         Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[SQRT_2](f64::consts::SQRT_2)</code>.
	const SQRT_2:          Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_1_PI](f64::consts::FRAC_1_PI)</code>.
	const FRAC_1_PI:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_1_SQRT_2](f64::consts::FRAC_1_SQRT_2)</code>.
	const FRAC_1_SQRT_2:   Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_2_PI](f64::consts::FRAC_2_PI)</code>.
	const FRAC_2_PI:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_2_SQRT_PI](f64::consts::FRAC_2_SQRT_PI)</code>.
	const FRAC_2_SQRT_PI:  Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_PI_2](f64::consts::FRAC_PI_2)</code>.
	const FRAC_PI_2:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_PI_3](f64::consts::FRAC_PI_3)</code>.
	const FRAC_PI_3:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_PI_4](f64::consts::FRAC_PI_4)</code>.
	const FRAC_PI_4:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_PI_6](f64::consts::FRAC_PI_6)</code>.
	const FRAC_PI_6:       Self;

	/// See <code>[mod@f64]::[consts](f64::consts)::[FRAC_PI_8](f64::consts::FRAC_PI_8)</code>.
	const FRAC_PI_8:       Self;

	#[cfg_attr(feature = "f16",                                  doc = "Equivalent to <code>Self::[from_f16](Self::from_f16)(0.0)</code>.")]
	#[cfg_attr(all(not(feature = "f16"), feature = "f128"),      doc = "Equivalent to <code>Self::[from_f128_lossy](Self::from_f128_lossy)(0.0)</code>.")]
	#[cfg_attr(all(not(feature = "f16"), not(feature = "f128")), doc = "Equivalent to <code>Self::[from_f64_lossy](Self::from_f64_lossy)(0.0)</code>.")]
	///
	/// # Examples
	///
	/// ```rust
	/// use multitype::Float;
	///
	/// let v0 = f32::ZERO;
	/// let v1 = 0.0f32;
	///
	/// assert_eq!(v0, v1);
	/// ```
	const ZERO: Self;

	#[cfg_attr(feature = "f16",                                  doc = "Equivalent to <code>Self::[from_f16](Self::from_f16)(1.0)</code>.")]
	#[cfg_attr(all(not(feature = "f16"), feature = "f128"),      doc = "Equivalent to <code>Self::[from_f128_lossy](Self::from_f128_lossy)(1.0)</code>.")]
	#[cfg_attr(all(not(feature = "f16"), not(feature = "f128")), doc = "Equivalent to <code>Self::[from_f64_lossy](Self::from_f64_lossy)(1.0)</code>.")]
	///
	/// # Examples
	///
	/// ```rust
	/// use multitype::Float;
	///
	/// let v0 = f32::ONE;
	/// let v1 = 1.0f32;
	///
	/// assert_eq!(v0, v1);
	/// ```
	const ONE: Self;

	/// Losslessly constructs a new, floating-point real from an [`f16`] value.
	#[cfg(feature = "f16")]
	#[cfg_attr(feature = "unstable-docs", doc(cfg(feature = "f16")))]
	#[must_use]
	fn from_f16(value: f16) -> Self;

	/// Equivalent to `value as Self`.
	///
	#[cfg_attr(feature = "f128", doc = "Note that when [`f128`] stabilises (see [`#116909`](https://github.com/rust-lang/rust/issues/116909/)), this constructor may be removed in favour of [`from_f128_lossy`](Self::from_f128_lossy).\n")]
	///
	/// # Examples
	///
	/// ```rust
	/// use multitype::Float;
	///
	/// let v0 = 0.062_500f64 as f32;
	/// let v1 = f32::from_f64_lossy(0.062_500);
	///
	/// assert_eq!(v0.to_bits(), v1.to_bits());
	/// ```
	#[must_use]
	fn from_f64_lossy(value: f64) -> Self;

	/// Equivalent to `value as Self`.
	///
	/// # Examples
	///
	/// ```rust
	/// # #![feature(f128)]
	///
	/// use multitype::Float;
	///
	/// let v0 = 0.062_500f128 as f32;
	/// let v1 = f32::from_f128_lossy(0.062_500);
	///
	/// assert_eq!(v0.to_bits(), v1.to_bits());
	/// ```
	#[cfg(feature = "f128")]
	#[cfg_attr(feature = "unstable-docs", doc(cfg(feature = "f128")))]
	#[must_use]
	fn from_f128_lossy(value: f128) -> Self;

	/// See <code>[prim@f64]::[from_ne_bytes](f64::from_ne_bytes)</code>.
	#[must_use]
	fn from_ne_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[prim@f64]::[from_le_bytes](f64::from_le_bytes)</code>.
	#[must_use]
	fn from_le_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[prim@f64]::[from_be_bytes](f64::from_be_bytes)</code>.
	#[must_use]
	fn from_be_bytes(bytes: Self::Bytes) -> Self;

	/// See <code>[prim@f64]::[from_bits](f64::from_bits)</code>.
	#[must_use]
	fn from_bits(bits: Self::Bits) -> Self;

	/// See <code>[prim@f64]::[abs](f64::abs)</code>.
	#[must_use]
	fn abs(self) -> Self;

	/// See <code>[prim@f64]::[recip](f64::recip)</code>.
	#[must_use]
	fn recip(self) -> Self;

	/// See <code>[prim@f64]::[midpoint](f64::midpoint)</code>.
	#[must_use]
	fn midpoint(self, rhs: Self) -> Self;

	/// See <code>[prim@f64]::[to_radians](f64::to_radians)</code>.
	#[must_use]
	fn to_radians(self) -> Self;

	/// See <code>[prim@f64]::[to_degrees](f64::to_degrees)</code>.
	#[must_use]
	fn to_degrees(self) -> Self;

	/// See <code>[prim@f64]::[next_down](f64::next_down)</code>.
	#[must_use]
	fn next_down(self) -> Self;

	/// See <code>[prim@f64]::[next_up](f64::next_up)</code>.
	#[must_use]
	fn next_up(self) -> Self;

	/// See <code>[prim@f64]::[signum](f64::signum)</code>.
	#[must_use]
	fn signum(self) -> Self;

	/// See <code>[prim@f64]::[copysign](f64::copysign)</code>.
	#[must_use]
	fn copysign(self, sign: Self) -> Self;

	/// See <code>[prim@f64]::[classify](f64::classify)</code>.
	#[must_use]
	fn classify(self) -> FpCategory;

	/// See <code>[prim@f64]::[is_nan](f64::is_nan)</code>.
	#[must_use]
	fn is_nan(self) -> bool;

	/// See <code>[prim@f64]::[is_infinite](f64::is_infinite)</code>.
	#[must_use]
	fn is_infinite(self) -> bool;

	/// See <code>[prim@f64]::[is_finite](f64::is_finite)</code>.
	#[must_use]
	fn is_finite(self) -> bool;

	/// See <code>[prim@f64]::[is_normal](f64::is_normal)</code>.
	#[must_use]
	fn is_normal(self) -> bool;

	/// See <code>[prim@f64]::[is_subnormal](f64::is_subnormal)</code>.
	#[must_use]
	fn is_subnormal(self) -> bool;

	/// See <code>[prim@f64]::[is_sign_negative](f64::is_sign_negative)</code>.
	#[must_use]
	fn is_sign_negative(self) -> bool;

	/// See <code>[prim@f64]::[is_sign_positive](f64::is_sign_positive)</code>.
	#[must_use]
	fn is_sign_positive(self) -> bool;

	/// See <code>[prim@f64]::[clamp](f64::clamp)</code>.
	#[must_use]
	fn clamp(self, min: Self, max: Self) -> Self;

	/// See <code>[prim@f64]::[min](f64::min)</code>.
	#[must_use]
	fn min(self, rhs: Self) -> Self;

	/// See <code>[prim@f64]::[max](f64::max)</code>.
	#[must_use]
	fn max(self, rhs: Self) -> Self;

	/// See <code>[prim@f64]::[total_cmp](f64::total_cmp)</code>.
	#[must_use]
	fn total_cmp(&self, rhs: &Self) -> Ordering;

	/// See <code>[prim@f64]::[to_int_unchecked](f64::to_int_unchecked)</code>.
	///
	/// Our `multitype::FloatToInt<T>` trait can be expected to be as equivalent to <code>[core::convert::FloatToInt]&lt;T&gt;</code> as possible.
	#[expect(clippy::missing_safety_doc)]
	#[must_use]
	unsafe fn to_int_unchecked<T>(self) -> T
	where
		Self: FloatToInt<T>;

	/// See <code>[prim@f64]::[to_bits](f64::to_bits)</code>.
	#[must_use]
	fn to_bits(self) -> Self::Bits;

	/// See <code>[prim@f64]::[to_ne_bytes](f64::to_ne_bytes)</code>.
	#[must_use]
	fn to_ne_bytes(self) -> Self::Bytes;

	/// See <code>[prim@f64]::[to_le_bytes](f64::to_le_bytes)</code>.
	#[must_use]
	fn to_le_bytes(self) -> Self::Bytes;

	/// See <code>[prim@f64]::[to_be_bytes](f64::to_be_bytes)</code>.
	#[must_use]
	fn to_be_bytes(self) -> Self::Bytes;
}

macro_rules! impl_float {
	{
		$($Ty:ty {
			Bytes = $Bytes:ty,
			Bits  = $Bits:ty,

			consts = $consts:ident$(,)?
		} $(= $feature:literal)?),*$(,)?
	} => {$(
		$(
			#[cfg(feature = $feature)]
		)*
		impl ::multitype::seal::Float for $Ty {}

		$(
			#[cfg(feature = $feature)]
			#[cfg_attr(feature = "unstable-docs", doc(cfg(feature = $feature)))]
		)?
		unsafe impl ::multitype::Float for $Ty {
			type Bytes = $Bytes;

			type Bits = $Bits;

			const RADIX:           ::core::primitive::u32 = Self::RADIX;

			const MANTISSA_DIGITS: ::core::primitive::u32 = Self::MANTISSA_DIGITS;
			const DIGITS:          ::core::primitive::u32 = Self::DIGITS;

			const EPSILON:         Self = Self::EPSILON;

			const MIN:             Self = Self::MIN;
			const MIN_POSITIVE:    Self = Self::MIN_POSITIVE;
			const MAX:             Self = Self::MAX;

			const ZERO:            Self = 0.0;
			const ONE:             Self = 1.0;

			const INFINITY:        Self = Self::INFINITY;
			const NEG_INFINITY:    Self = Self::NEG_INFINITY;

			const NAN:             Self = Self::NAN;

			const E:               Self = ::core::$consts::consts::E;
			const PI:              Self = ::core::$consts::consts::PI;
			const TAU:             Self = ::core::$consts::consts::TAU;

			const LOG2_10:         Self = ::core::$consts::consts::LOG2_10;
			const LOG2_E:          Self = ::core::$consts::consts::LOG2_E;
			const LN_2:            Self = ::core::$consts::consts::LN_2;
			const LN_10:           Self = ::core::$consts::consts::LN_10;
			const LOG10_2:         Self = ::core::$consts::consts::LOG10_2;
			const LOG10_E:         Self = ::core::$consts::consts::LOG10_E;

			const SQRT_2:          Self = ::core::$consts::consts::SQRT_2;

			const FRAC_1_PI:       Self = ::core::$consts::consts::FRAC_1_PI;
			const FRAC_1_SQRT_2:   Self = ::core::$consts::consts::FRAC_1_SQRT_2;
			const FRAC_2_PI:       Self = ::core::$consts::consts::FRAC_2_PI;
			const FRAC_2_SQRT_PI:  Self = ::core::$consts::consts::FRAC_2_SQRT_PI;
			const FRAC_PI_2:       Self = ::core::$consts::consts::FRAC_PI_2;
			const FRAC_PI_3:       Self = ::core::$consts::consts::FRAC_PI_3;
			const FRAC_PI_4:       Self = ::core::$consts::consts::FRAC_PI_4;
			const FRAC_PI_6:       Self = ::core::$consts::consts::FRAC_PI_6;
			const FRAC_PI_8:       Self = ::core::$consts::consts::FRAC_PI_8;

			#[cfg(feature = "f16")]
			#[cfg_attr(feature = "unstable-docs", doc(cfg(feature = "f16")))]
			#[inline(always)]
			fn from_f16(value: f16) -> Self {
				value as Self
			}

			#[inline(always)]
			fn from_f64_lossy(value: f64) -> Self {
				value as Self
			}

			#[cfg(feature = "f128")]
			#[cfg_attr(feature = "unstable-docs", doc(cfg(feature = "f128")))]
			#[inline(always)]
			fn from_f128_lossy(value: f128) -> Self {
				value as Self
			}

			#[inline(always)]
			#[track_caller]
			fn from_ne_bytes(bytes: Self::Bytes) -> Self {
				Self::from_ne_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_le_bytes(bytes: Self::Bytes) -> Self {
				Self::from_le_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_be_bytes(bytes: Self::Bytes) -> Self {
				Self::from_be_bytes(bytes)
			}

			#[inline(always)]
			#[track_caller]
			fn from_bits(bits: Self::Bits) -> Self {
				Self::from_bits(bits)
			}

			#[inline(always)]
			#[track_caller]
			fn abs(self) -> Self {
				self.abs()
			}

			#[inline(always)]
			#[track_caller]
			fn recip(self) -> Self {
				self.recip()
			}

			#[inline(always)]
			#[track_caller]
			fn midpoint(self, rhs: Self) -> Self {
				self.midpoint(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn to_radians(self) -> Self {
				self.to_radians()
			}

			#[inline(always)]
			#[track_caller]
			fn to_degrees(self) -> Self {
				self.to_radians()
			}

			// BACKPORT(1.86)
			#[inline]
			fn next_down(self) -> Self {
				if self.is_nan() || (self.is_infinite() && self.is_sign_negative()) {
				    return self;
				}

				if self.abs().to_bits() == 0 {
					return Self::from_bits(1).copysign(-1.0);
				}

				let bits = if self.is_sign_positive() {
					self.to_bits() - 1
				} else {
					self.to_bits() + 1
				};

				Self::from_bits(bits)
			}

			// BACKPORT(1.86)
			#[inline]
			fn next_up(self) -> Self {
				if self.is_nan() || (self.is_infinite() && self.is_sign_positive()) {
				    return self;
				}

				if self.abs().to_bits() == 0 {
					return Self::from_bits(1).copysign(-1.0);
				}

				let bits = if self.is_sign_positive() {
					self.to_bits() + 1
				} else {
					self.to_bits() - 1
				};

				Self::from_bits(bits)
			}

			#[inline(always)]
			#[track_caller]
			fn signum(self) -> Self {
				self.signum()
			}

			#[inline(always)]
			#[track_caller]
			fn copysign(self, sign: Self) -> Self {
				self.copysign(sign)
			}

			#[inline(always)]
			#[track_caller]
			fn classify(self) -> ::core::num::FpCategory {
				self.classify()
			}

			#[inline(always)]
			#[track_caller]
			fn is_nan(self) -> bool {
				self.is_nan()
			}

			#[inline(always)]
			#[track_caller]
			fn is_infinite(self) -> bool {
				self.is_infinite()
			}

			#[inline(always)]
			#[track_caller]
			fn is_finite(self) -> bool {
				self.is_finite()
			}

			#[inline(always)]
			#[track_caller]
			fn is_normal(self) -> bool {
				self.is_normal()
			}

			#[inline(always)]
			#[track_caller]
			fn is_subnormal(self) -> bool {
				self.is_subnormal()
			}

			#[inline(always)]
			#[track_caller]
			fn is_sign_negative(self) -> bool {
				self.is_sign_negative()
			}

			#[inline(always)]
			#[track_caller]
			fn is_sign_positive(self) -> bool {
				self.is_sign_positive()
			}

			#[inline(always)]
			#[track_caller]
			fn clamp(self, min: Self, max: Self) -> Self {
				self.clamp(min, max)
			}

			#[inline(always)]
			#[track_caller]
			fn min(self, rhs: Self) -> Self {
				self.min(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn max(self, rhs: Self) -> Self {
				self.max(rhs)
			}

			#[inline(always)]
			#[track_caller]
			fn total_cmp(&self, rhs: &Self) -> ::core::cmp::Ordering {
				self.total_cmp(rhs)
			}

			#[inline(always)]
			#[track_caller]
			unsafe fn to_int_unchecked<T>(self) -> T
			where
				Self: ::multitype::FloatToInt<T>,
			{
				unsafe { <Self as ::multitype::FloatToInt<T>>::to_int_unchecked(self) }
			}

			#[inline(always)]
			#[track_caller]
			fn to_ne_bytes(self) -> Self::Bytes {
				self.to_ne_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn to_le_bytes(self) -> Self::Bytes {
				self.to_le_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn to_be_bytes(self) -> Self::Bytes {
				self.to_be_bytes()
			}

			#[inline(always)]
			#[track_caller]
			fn to_bits(self) -> Self::Bits {
				self.to_bits()
			}
		}
	)*};
}

impl_float! {
	f16  { Bytes = [u8; 02], Bits = u16,  consts = f16  } = "f16",
	f32  { Bytes = [u8; 04], Bits = u32,  consts = f32  },
	f64  { Bytes = [u8; 08], Bits = u64,  consts = f64  },
	f128 { Bytes = [u8; 16], Bits = u128, consts = f128 } = "f128",
}
