Skip to content

Instantly share code, notes, and snippets.

@auroranockert
Last active December 12, 2015 05:08
Show Gist options
  • Save auroranockert/4719287 to your computer and use it in GitHub Desktop.
Save auroranockert/4719287 to your computer and use it in GitHub Desktop.
Rust Numeric (Very much first draft, influenza may have had some bad influence)
trait Eq {
fn eq(&self, other: &Self) -> bool;
fn ne(&self, other: &Self) -> bool; // TODO: Default implementation?
}
trait Ord: Eq {
fn lt(&self, other: &Self) -> bool;
fn le(&self, other: &Self) -> bool;
fn ge(&self, other: &Self) -> bool;
fn gt(&self, other: &Self) -> bool;
// TODO: These will be handled using default implementations. But should
// be specialised when required, for example using cmath functions.
fn min(&self, other: &Self) -> Self;
fn max(&self, other: &Self) -> Self;
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
}
/*
* Note that while abs_min / abs_max returns values that may be unordered, they
* are always ordered as reals. This means even complex numbers can implement
* this trait already.
* TODO: Refactor into Abs<Result> so it makes even more sense for complex
* numbers?
*/
trait Abs<Result> {
fn abs(&self) -> Result; // NOTE: Overflows as normal operations, abs(INT_MIN) = INT_MIN.
//NOTE: These methods are in IEEE754-2008, and are actually quite cool
fn abs_min(&self, other: &Self) -> Self;
fn abs_max(&self, other: &Self) -> Self;
}
/*
* Signed, should be provided by all signed real types.
*/
trait Signed: Neg<Self> {
fn sign(&self) -> Self; // NOTE: Since we have copysign, this should be { -1, 0, +1} even for floats?
}
/*
* A quasigroup is a structure resembling a group where the 'division' operation
* is always possible. It is a good enough approximation of what properties the
* trait represents.
*/
trait Additive<RHS,Result>: Add<RHS,Result> Sub<RHS,Result> { }
trait AdditiveQuasigroup: Additive<Self,Self> Zero { }
trait Multiplicative<RHS,Result>: Mul<RHS,Result> Div<RHS,Result> One { }
trait MultiplicativeQuasigroup: Multiplicative<Self,Self> One { }
trait Sqrt {
fn sqrt(&self) -> Self;
}
/*
* Can be trivially implemented for integers, since we don't signal on overflow.
* TODO: Factor into FusedMultiplyAdd<RHS1,RHS2,Result>?
*/
trait FusedMultiplyAdd {
fn fma(&self, a: Self, b: Self) -> Self;
fn fms(&self, a: Self, b: Self) -> Self;
}
trait Num: Eq
AdditiveQuasigroup
MultiplicativeQuasigroup {
fn abs_sub(&self, b: Self) -> Self; // TODO: Is this just abs(a - b)?
}
trait Real: Num Ord Sqrt Abs<Self> { }
/*
* Can really be extended to support most types, but for now we'll restrict
* them to integers.
*/
trait Bitwise: Not<Self>
BitAnd<Self,Self>
BitOr<Self,Self>
BitXor<Self,Self> {
}
/*
* Can really be extended to support most types, but for now we'll restrict
* them to integers.
* NOTE: Shifts are done in the way that makes sense(tm) for the type.
*/
trait Shift<RHS>: Shl<RHS,Self>
Shr<RHS,Self> {
}
/*
* I find these useful, so I'll add them here. We also currently have unexposed
* intrinsics for them, which this would fix.
*/
trait Bitcount<I:Int> {
fn popcount(&self) -> I;
fn clz(&self) -> I;
fn ctz(&self) -> I;
}
/*
* And these are useful for networking etc. Same thing as above, implemented,
* but currently unexposed.
*/
trait ByteSwap {
fn to_big_endian(&self) -> Self;
fn to_little_endian(&self) -> Self;
fn byte_swap(&self) -> Self;
}
/* Additive Identity Element */
trait Zero {
static fn zero() -> Self; // TODO: Factor out to a zero trait?
}
/* Multiplicative Identity Element */
trait One {
static fn one() -> Self; // TODO: Factor out to a one trait?
}
/*
* These are constants that are cool to have if the type provides constants,
* maybe some should be added?
*/
trait RealConstants {
static fn pi() -> Self;
static fn two_pi() -> Self;
static fn frac_pi_2() -> Self;
static fn frac_pi_4() -> Self;
static fn frac_1_pi() -> Self;
static fn frac_2_pi() -> Self;
static fn frac_2_sqrtpi() -> Self;
static fn sqrt2() -> Self;
static fn frac_1_sqrt2() -> Self;
static fn e() -> Self;
static fn log2_e() -> Self;
static fn log10_e() -> Self;
static fn ln_2() -> Self;
static fn ln_10() -> Self;
}
/*
* This means that there is no infinity in the type, should return
* int_max/int_min.
*/
trait Bounded {
static fn min_bound() -> Self;
static fn max_bound() -> Self;
}
/*
* People expect these, but putting them on Real doesn't make sense.
* - Rationals are reals, but exponential functions doesn't make sense.
* - Complex numbers are not reals, but exponential functions make sense.
*/
trait Exponential {
fn exp(&self) -> Self;
fn exp2(&self) -> Self; // TODO: Should have default implementation
fn exp10(&self) -> Self; // TODO: Should have default implementation
fn log(&self) -> Self;
fn log2(&self) -> Self; // TODO: Should have default implementation
fn log10(&self) -> Self; // TODO: Should have default implementation
}
/* Some additional functions recommended by IEEE754-2008 9.2 */
trait ExponentialExpanded: Exponential {
fn expm1(&self) -> Self;
fn exp2m1(&self) -> Self;
fn exp10m1(&self) -> Self;
fn logp1(&self) -> Self;
fn log2p1(&self) -> Self;
fn log10p1(&self) -> Self;
}
/*
* NOTE: An hypothetical complex fp trait
*/
trait Complex<R>: Num
Abs<R>
Sqrt
RealConstants
Trigonometric
TrigonometricExpanded
Hyperbolic
Exponential
ExponentialExpanded
static fn NaN() -> Self; // TODO: There is more than 1 NaN…
// IEEE 754-2008 5.3.3: logBFormat operations
fn scale_b<I:Int>(&self, n: I) -> Self;
fn log_b<I:Int>(&self) -> I;
// IEEE 754-2008 5.7.1: Conformance predicates
static fn is_754_version_1985(&self) -> bool; // TODO: Should always return false for floats?
static fn is_754_version_2008(&self) -> bool; // TODO: Should always return true for floats?
static fn radix(&self) -> uint;
}
/*
* NOTE: A hypothetical fixed-point trait
*/
trait FixedPoint: Real
RealConstants
Trigonometric
TrigonometricExpanded
Hyperbolic
Exponential
ExponentialExpanded { }
/*
* NOTE: A hypothetical NEON-style binary polynomial trait
*/
trait FixedPoint: Num { }
/*
* NOTE: A hypotethical vector trait not including complex numbers.
*/
trait Vector<T:Real>: Real Mul<T,Self> Div<T,Self> { }
/*
* An IEEE754 floating-point number, the radix isn't defined, but I didn't
* include the decimal-related methods.
*/
trait FloatingPoint: Real
FusedMultiplyAdd
RealConstants
Trigonometric
TrigonometricExpanded
Hyperbolic
Exponential
ExponentialExpanded
ConvertToInteger
RoundToIntegral
Mod<Self,Self> { // NOTE: IEEE754 remainder.
static fn NaN() -> Self; // TODO: There is more than 1 NaN…
static fn infinity() -> Self;
static fn neg_infinity() -> Self;
// IEEE 754-2008 5.3.1: General operations
// TODO: Support signalling versions of round_to_integral?
fn next_up(&self) -> Self;
fn next_down(&self) -> Self;
// NOTE: min/max and abs_min/abs_max are defined elsewhere
// IEEE 754-2008 5.3.2: Decimal operations not supported in Rust (yet?)
// IEEE 754-2008 5.3.3: logBFormat operations
fn scale_b<I:Int>(&self, n: I) -> Self;
fn log_b<I:Int>(&self) -> I;
// IEEE 754-2008 5.4.1: Arithmetic operations are defined elsewhere
// TODO: Support signalling versions of convert_to_integer?
// IEEE 754-2008 5.4.2: Conversion operations are defined elsewhere
// IEEE 754-2008 5.4.3: Conversion operations for binary formats should probably be skipped for now
// IEEE 754-2008 5.5.1: Most sign bit operations are defined elsewhere
fn copy_sign(&self, y: Self) -> Self
// IEEE 754-2008 5.5.2: Decimal operations not supported in Rust (yet?)
// IEEE 754-2008 5.6.1: TODO: Should we support signalling comparisons?
fn ordered(&self, other: &Self) -> bool;
fn unordered(&self, other: &Self) -> bool;
fn less_unordered(&self, other: &Self) -> bool;
fn greater_unordered(&self, other: &Self) -> bool;
// IEEE 754-2008 5.7.1: Conformance predicates
static fn is_754_version_1985(&self) -> bool; // TODO: Should always return false for floats?
static fn is_754_version_2008(&self) -> bool; // TODO: Should always return true for floats?
// IEEE 754-2008: 5.7.2 General Operations, some of these might be skipped for now
fn class(&self) -> enum { signalling_NaN,
quiet_NaN,
negative_infinity, positive_infinity,
negative_normal, positive_normal,
negative_subnormal, positive_subnormal,
negative_zero, positive_zero }
fn is_sign_minus(&self) -> bool;
fn is_normal(&self) -> bool;
fn is_finite(&self) -> bool;
fn is_zero(&self) -> bool;
fn is_subnormal(&self) -> bool;
fn is_infinite(&self) -> bool;
fn is_NaN(&self) -> bool;
fn is_signalling(&self) -> bool;
fn is_canonical(&self) -> bool;
fn total_order(&self, b: Self) -> bool;
fn total_order_magnitude(&self, b: Self) -> bool;
static fn radix(&self) -> uint;
// IEEE 754-2008 5.7.3: Decimal still unsupported
// IEEE 754-2008 9.1: Recommended correctly rounded functions
// NOTE: Exponential / Logarithmic functions defined elsewhere
fn hypot(&self, b: Self) -> Self;
// NOTE: rsqrt defined elsewhere
fn compound(&self, n: Self) -> Self;
fn rootn(&self, n: Self) -> Self;
fn pown<I:Int>(&self, n: I) -> Self;
fn pow(&self, n: Self) -> Self;
fn powr(&self, n: Self) -> Self;
// NOTE: Trigonometric functions defined elsewhere
}
/*
* This is a type for both 'normal' and big (u)ints.
* - A 'normal' int is this and bounded, and possibly Signed.
* - A 'big' int is this and possibly Signed.
*/
trait Integer: Real
Shift<Self>
Bitwise
Bitcount
ByteSwap
Mod<Self,Self> {
fn lcm(&self, other: &Self) -> Self;
fn gcd(&self, other: &Self) -> Self;
fn gcd_lcm(&self, other: &Self) -> (Self, Self);
fn div_mod(&self, other: &Self) -> (Self, Self);
fn even(&self) -> bool;
fn odd(&self) -> bool;
}
/*
* The functions here are copied from OpenCL, and are intended to map to lower
* level instructions, and are (possibly) not as accurate as the normal ones.
*/
trait NativeMath {
fn native_cos(&self) -> Self;
fn native_divide(&self, &b: Self) -> Self;
fn native_exp(&self) -> Self;
fn native_exp2(&self) -> Self;
fn native_exp10(&self) -> Self;
fn native_log(&self) -> Self;
fn native_log2(&self) -> Self;
fn native_log10(&self) -> Self;
fn native_powr(&self, &b: Self) -> Self;
fn native_recip(&self) -> Self;
fn native_rsqrt(&self) -> Self;
fn native_sin(&self) -> Self;
fn native_sqrt(&self) -> Self;
fn native_tan(&self) -> Self;
}
trait ConvertToInteger {
fn convert_to_integer_ties_to_even<I:Int>(&self) -> I;
fn convert_to_integer_ties_to_away<I:Int>(&self) -> I;
fn convert_to_integer_ties_toward_zero<I:Int>(&self) -> I;
fn convert_to_integer_ties_toward_positive<I:Int>(&self) -> I;
fn convert_to_integer_ties_toward_negative<I:Int>(&self) -> I;
}
trait RoundToIntegral {
fn round_to_integral_ties_to_even(&self) -> Self;
fn round_to_integral_ties_to_away(&self) -> Self;
fn round_to_integral_ties_toward_zero(&self) -> Self;
fn round_to_integral_ties_toward_positive(&self) -> Self;
fn round_to_integral_ties_toward_negative(&self) -> Self;
fn ceil(&self) -> Self; // NOTE: Just different names…
fn floor(&self) -> Self; // NOTE: Just different names…
fn round(&self) -> Self; // NOTE: Just different names…
fn trunc(&self) -> Self; // NOTE: Just different names…
}
/*
* People expect these, but putting them on Real doesn't make sense.
* - Rationals are reals, but trigonometric functions doesn't make sense.
* - Complex numbers are not reals, but trigonometric functions make sense.
*/
trait Trigonometric {
fn sin(&self) -> Self;
fn cos(&self) -> Self;
fn tan(&self) -> Self;
fn asin(&self) -> Self;
fn acos(&self) -> Self;
fn atan(&self) -> Self;
fn atan2(&self, b: Self) -> Self;
}
/* Some additional functions recommended by IEEE754-2008 9.2 */
trait TrigonometricExpanded: Trigonometric {
fn sin_pi(&self) -> Self;
fn cos_pi(&self) -> Self;
fn atan_pi(&self) -> Self;
fn atan2_pi(&self, b: Self) -> Self;
}
trait Hyperbolic {
fn sinh(&self) -> Self;
fn cosh(&self) -> Self;
fn tanh(&self) -> Self;
fn asinh(&self) -> Self;
fn acosh(&self) -> Self;
fn atanh(&self) -> Self;
}
@kud1ing
Copy link

kud1ing commented Feb 6, 2013

le() and ge() could have default implementations using eq() and gt()/lt() too

@brendanzab
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment