///|
pub impl AddContextual for Double with fn add_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left + right))
}
///|
pub impl SubContextual for Double with fn sub_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left - right))
}
///|
pub impl MulContextual for Double with fn mul_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left * right))
}
///|
pub impl DivContextual for Double with fn div_contextual(left, right, context) {
DivChecked::div_checked(left, right, context).map(ArithmeticOutcome::exact)
}
///|
pub impl AbsContextual for Double with fn abs_contextual(value, _context) {
Ok(ArithmeticOutcome::exact(value.abs()))
}
///|
pub impl SqrtContextual for Double with fn sqrt_contextual(value, context) {
SqrtChecked::sqrt_checked(value, context).map(ArithmeticOutcome::exact)
}
///|
pub impl ExpContextual for Double with fn exp_contextual(value, _context) {
Ok(ArithmeticOutcome::exact(Exponential::exp(value)))
}
///|
pub impl IntegralContextual for Double with fn from_int_contextual(
value,
_context,
) {
Ok(ArithmeticOutcome::exact(Double::from_int(value)))
}
///|
fn double_next_plus(value : Double) -> Double {
if Double::is_nan(value) || Double::is_pos_inf(value) {
return value
}
if value == 0.0 {
return 1UL.reinterpret_as_double()
}
let bits = value.reinterpret_as_uint64()
if value > 0.0 {
(bits + 1UL).reinterpret_as_double()
} else {
(bits - 1UL).reinterpret_as_double()
}
}
///|
fn double_next_minus(value : Double) -> Double {
if Double::is_nan(value) || Double::is_neg_inf(value) {
return value
}
if value == 0.0 {
return 0x8000_0000_0000_0001UL.reinterpret_as_double()
}
let bits = value.reinterpret_as_uint64()
if value > 0.0 {
(bits - 1UL).reinterpret_as_double()
} else {
(bits + 1UL).reinterpret_as_double()
}
}
///|
pub impl AdjacentContextual for Double with fn next_plus_contextual(
value,
_context,
) {
Ok(ArithmeticOutcome::exact(double_next_plus(value)))
}
///|
pub impl AdjacentContextual for Double with fn next_minus_contextual(
value,
_context,
) {
Ok(ArithmeticOutcome::exact(double_next_minus(value)))
}
///|
pub impl AdjacentContextual for Double with fn next_toward_contextual(
value,
target,
_context,
) {
let result = if Double::is_nan(value) {
value
} else if Double::is_nan(target) || value == target {
target
} else if value < target {
double_next_plus(value)
} else {
double_next_minus(value)
}
Ok(ArithmeticOutcome::exact(result))
}
///|
pub impl NumericFormatContextual for Double with fn zero_contextual(_context) {
0.0
}
///|
pub impl NumericFormatContextual for Double with fn one_contextual(_context) {
1.0
}
///|
pub impl NumericFormatContextual for Double with fn epsilon_contextual(_context) {
2.220446049250313e-16
}
///|
pub impl NumericFormatContextual for Double with fn min_normal_contextual(
_context,
) {
2.2250738585072014e-308
}
///|
pub impl NumericFormatContextual for Double with fn max_finite_contextual(
_context,
) {
1.7976931348623157e308
}
///|
pub impl NumericFormatContextual for Double with fn classify_contextual(value) {
if Double::is_nan(value) {
FpClass::NaN
} else if Double::is_inf(value) {
FpClass::Infinity
} else {
FpClass::Finite
}
}
///|
pub impl AddContextual for Float with fn add_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left + right))
}
///|
pub impl SubContextual for Float with fn sub_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left - right))
}
///|
pub impl MulContextual for Float with fn mul_contextual(left, right, _context) {
Ok(ArithmeticOutcome::exact(left * right))
}
///|
pub impl DivContextual for Float with fn div_contextual(left, right, context) {
DivChecked::div_checked(left, right, context).map(ArithmeticOutcome::exact)
}
///|
pub impl AbsContextual for Float with fn abs_contextual(value, _context) {
Ok(ArithmeticOutcome::exact(value.abs()))
}
///|
pub impl SqrtContextual for Float with fn sqrt_contextual(value, context) {
SqrtChecked::sqrt_checked(value, context).map(ArithmeticOutcome::exact)
}
///|
pub impl ExpContextual for Float with fn exp_contextual(value, _context) {
Ok(ArithmeticOutcome::exact(Exponential::exp(value)))
}
///|
pub impl IntegralContextual for Float with fn from_int_contextual(
value,
_context,
) {
let converted = Float::from_int(value)
let exact = converted.to_double() == Double::from_int(value)
let diagnostics = if exact {
ArithmeticDiagnostics::empty()
} else {
ArithmeticDiagnostics::new(inexact=true, rounded=true)
}
Ok(ArithmeticOutcome::with_diagnostics(converted, diagnostics))
}
///|
fn float_next_plus(value : Float) -> Float {
if Float::is_nan(value) || Float::is_pos_inf(value) {
return value
}
if value == 0.0F {
return Float::reinterpret_from_uint(1U)
}
let bits = value.reinterpret_as_uint()
if value > 0.0F {
Float::reinterpret_from_uint(bits + 1U)
} else {
Float::reinterpret_from_uint(bits - 1U)
}
}
///|
fn float_next_minus(value : Float) -> Float {
if Float::is_nan(value) || Float::is_neg_inf(value) {
return value
}
if value == 0.0F {
return Float::reinterpret_from_uint(0x8000_0001U)
}
let bits = value.reinterpret_as_uint()
if value > 0.0F {
Float::reinterpret_from_uint(bits - 1U)
} else {
Float::reinterpret_from_uint(bits + 1U)
}
}
///|
pub impl AdjacentContextual for Float with fn next_plus_contextual(
value,
_context,
) {
Ok(ArithmeticOutcome::exact(float_next_plus(value)))
}
///|
pub impl AdjacentContextual for Float with fn next_minus_contextual(
value,
_context,
) {
Ok(ArithmeticOutcome::exact(float_next_minus(value)))
}
///|
pub impl AdjacentContextual for Float with fn next_toward_contextual(
value,
target,
_context,
) {
let result = if Float::is_nan(value) {
value
} else if Float::is_nan(target) || value == target {
target
} else if value < target {
float_next_plus(value)
} else {
float_next_minus(value)
}
Ok(ArithmeticOutcome::exact(result))
}
///|
pub impl NumericFormatContextual for Float with fn zero_contextual(_context) {
0.0F
}
///|
pub impl NumericFormatContextual for Float with fn one_contextual(_context) {
1.0F
}
///|
pub impl NumericFormatContextual for Float with fn epsilon_contextual(_context) {
1.1920929e-7F
}
///|
pub impl NumericFormatContextual for Float with fn min_normal_contextual(
_context,
) {
1.1754944e-38F
}
///|
pub impl NumericFormatContextual for Float with fn max_finite_contextual(
_context,
) {
3.4028235e38F
}
///|
pub impl NumericFormatContextual for Float with fn classify_contextual(value) {
if Float::is_nan(value) {
FpClass::NaN
} else if Float::is_inf(value) {
FpClass::Infinity
} else {
FpClass::Finite
}
}