decimal_gda API
decimal_gda implements the General Decimal Arithmetic Specification (GDA,
version 1.70) by M. F. Cowlishaw. Its Decimal is a sign, an arbitrary-length
decimal coefficient and a decimal exponent; its GdaContext carries the
precision, rounding mode, exponent limits, clamping, the extended/subset
switch, the sticky status and the enabled traps; and every GDA operation is a
pure function that returns a GdaOutcome holding the defined result, the next
context and the conditions it raised. The tutorial
shows the package in use; the design page derives
the rules stated here.
The package does not depend on the IEEE 754 package decimal. Besides the GDA
surface it publishes a lower, status-free layer — DecimalContext,
DecimalFlags and the Decimal::*_ctx methods — on which the GDA functions
are built, plus adapters to the Luna-Flow/arithmetic and
Luna-Flow/luna-generic traits.
Throughout, a finite value is written with coefficient and exponent ; its adjusted exponent is , the exponent of its leading digit. For a context with precision , is the smallest exponent a result may have.
The Decimal value
Decimal
Decimal is an immutable GDA number: a finite value, an infinity, a quiet NaN
or a signaling NaN.
pub struct Decimal {
// private fields
} derive(@debug.Debug)
Finite values keep their exponent, so 2.50 and 2.5 are distinct members of
the same cohort: they compare equal numerically and differ in
compare_total, same_quantum and printing. Zero is signed. NaNs carry a sign
and a non-negative integer payload. Every value also stores a precision
attribute (precision()), the precision of the context or constructor that
produced it; GDA operations ignore it and use the context precision instead.
The coefficient is stored as a persistent decimal limb array, so a value can
be shared freely.
Decimal::zero, Decimal::negative_zero, Decimal::one
These return , and , each with exponent 0.
pub fn Decimal::zero(precision? : Int) -> Self
pub fn Decimal::negative_zero(precision? : Int) -> Self
pub fn Decimal::one(precision? : Int) -> Self
precision (default 34, clamped to at least 1) is only the stored precision
attribute.
Decimal::inf, Decimal::nan, Decimal::quiet_nan, Decimal::signaling_nan
These build the special values.
pub fn Decimal::inf(@def.Sign, precision? : Int) -> Self
pub fn Decimal::nan(precision? : Int) -> Self
pub fn Decimal::quiet_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::signaling_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
inf(Negative) is ; any other Sign gives . nan() is a
positive quiet NaN with payload 0. The payload is stored as its absolute
value. A signaling NaN raises InvalidOperation when an arithmetic operation
consumes it and is replaced by the quiet NaN with the same sign and payload.
Decimal::make
make(c, e, p) returns rounded to p significant digits and
with trailing zeros removed.
pub fn Decimal::make(@bigint.BigInt, Int, Int, mode? : @arithmetic.RoundingMode) -> Self
The sign comes from the sign of c. Rounding uses mode (default
ToNearestEven). Because trailing zeros are removed, make(1200, 0, 34) is
1.2E+3; build from a string when the quantum matters. No flags are reported.
Decimal::from_int, Decimal::from_bigint, Decimal::from_double, Decimal::from_float, Decimal::from_bin_float
These convert binary values to decimal, round half to even to precision
digits and remove trailing zeros.
pub fn Decimal::from_int(Int, precision? : Int) -> Self
pub fn Decimal::from_bigint(@bigint.BigInt, precision? : Int) -> Self
pub fn Decimal::from_double(Double, precision? : Int) -> Self
pub fn Decimal::from_float(Float, precision? : Int) -> Self
pub fn Decimal::from_bin_float(@bin_float.BinFloat, precision? : Int) -> Self
precision defaults to 34 (for from_bin_float, to the precision of the
argument). A binary float with is first written exactly
as , so the conversion is exact whenever the result fits
in precision digits; for example from_double(0.1) is the 34-digit
rounding of the binary64 value nearest to . NaNs become the quiet NaN
(sign kept by from_double), infinities keep their sign, zeros keep their
sign (from_bin_float returns ). from_int(100) is 1E+2.
Decimal::to_bin_float
to_bin_float rounds the value to a binary BinFloat with precision
significant bits.
pub fn Decimal::to_bin_float(Self, precision? : Int, mode? : @arithmetic.RoundingMode) -> @bin_float.BinFloat
precision defaults to the stored precision attribute and mode to
ToNearestEven. With TowardNegative and TowardPositive the two results
enclose the decimal value; the elementary functions use exactly this to build
their certified input intervals. Zeros map to , NaNs to the binary NaN.
Decimal::parse, Decimal::from_string
These read a GDA numeric string without a GDA context.
pub fn Decimal::parse(String, precision? : Int) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::from_string(String, precision? : Int) -> Self?
Accepted syntax is the GDA numeric-string grammar: an optional sign, digits
with an optional decimal point, an optional exponent E±n, or
Infinity/Inf/NaN/sNaN (case-insensitive) with an optional decimal NaN
payload. The exponent is kept exactly, so from_string("2.50") has exponent
. A literal with more than precision (default 34) significant digits is
rounded half to even and its trailing zeros are removed. A malformed literal
gives Err(parse_error) or None. Use the package function
parse when the exponent limits, flags, status or traps of a context
must apply.
Decimal::to_string, Decimal::output
These print the value in GDA scientific notation, with lowercase special values.
pub fn Decimal::to_string(Self) -> String
pub fn Decimal::output(Self, &Logger) -> Unit
pub impl Show for Decimal
A finite value with and prints without an exponent
(0.000123, 7.50); otherwise it prints one digit, the remaining digits after
a point, and E± (1.23E+7, 1E-7, 0E+2). Infinities print as
inf/-inf, NaNs as nan, snan, -nan, followed by the payload when it is
not zero. For the GDA spellings Infinity/NaN/sNaN use
Decimal::to_sci_string.
Decimal::to_sci_string, Decimal::to_eng_string
These convert a numeric string under a DecimalContext and print it with
GDA to-scientific-string or to-engineering-string.
pub fn Decimal::to_sci_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_eng_string(String, DecimalContext) -> (String, DecimalFlags)
The string is converted exactly as by
Decimal::from_string_ctx (rounding to the context,
with the conversion flags returned), then formatted. Engineering notation uses
an exponent that is a multiple of three (123E+5 prints as 12.3E+6). Special
values print as Infinity, -Infinity, NaN, sNaN with payload.
Decimal::from_string_ctx
from_string_ctx is the GDA to-number conversion under a status-free
context.
pub fn Decimal::from_string_ctx(String, DecimalContext) -> (Self, DecimalFlags)
The literal is rounded to the context precision, checked against the exponent
range (overflow, subnormal, underflow, clamping) and returned with its flags.
Malformed input returns a quiet NaN with conversion_syntax. In a
non-extended context, infinities and NaNs are themselves a conversion-syntax
error, and zeros lose their sign and exponent.
///|
test "Decimal construction and printing" {
inspect(@decimal_gda.Decimal::from_string("2.50").unwrap(), content="2.50")
inspect(@decimal_gda.Decimal::from_int(100), content="1E+2")
inspect(@decimal_gda.Decimal::make(12345N, -2, 3), content="123")
inspect(@decimal_gda.Decimal::from_double(0.5), content="0.5")
inspect(@decimal_gda.Decimal::signaling_nan(payload=7N), content="snan7")
inspect(@decimal_gda.Decimal::from_string("1.2.3") is None, content="true")
let ctx = @decimal_gda.DecimalContext::new(precision=3)
let (v, flags) = @decimal_gda.Decimal::from_string_ctx("1.2345", ctx)
inspect(v, content="1.23")
inspect(flags.inexact, content="true")
let (sci, _) = @decimal_gda.Decimal::to_sci_string("-sNaN12", ctx)
inspect(sci, content="-sNaN12")
}
Observing a value
Decimal::classify, Decimal::sign, Decimal::precision
These report the class, the numeric sign and the stored precision attribute.
pub fn Decimal::classify(Self) -> @arithmetic.FpClass
pub fn Decimal::sign(Self) -> @def.Sign
pub fn Decimal::precision(Self) -> Int
classify returns Finite, Infinity or NaN. sign returns Zero for
zeros of either sign and for NaNs, and Positive/Negative otherwise; use
is_negative to read the sign bit.
Decimal::coefficient, Decimal::magnitude, Decimal::exponent10, Decimal::quantum
These expose the stored representation .
pub fn Decimal::coefficient(Self) -> @bigint.BigInt
pub fn Decimal::magnitude(Self) -> @bigint.BigInt
pub fn Decimal::exponent10(Self) -> Int
pub fn Decimal::quantum(Self) -> Int
coefficient and magnitude both return (the payload for a NaN, 0
for an infinity). exponent10 and quantum both return (0 for special
values).
Decimal::is_finite, Decimal::is_infinite, Decimal::is_nan, Decimal::is_zero, Decimal::is_negative, Decimal::is_signed, Decimal::is_negative_zero
These are the class and sign predicates.
pub fn Decimal::is_finite(Self) -> Bool
pub fn Decimal::is_infinite(Self) -> Bool
pub fn Decimal::is_nan(Self) -> Bool
pub fn Decimal::is_zero(Self) -> Bool
pub fn Decimal::is_negative(Self) -> Bool
pub fn Decimal::is_signed(Self) -> Bool
pub fn Decimal::is_negative_zero(Self) -> Bool
is_negative and is_signed are the same: they read the sign bit, so they are
true for , and negative NaNs. is_zero is true for finite zeros
of any exponent.
Decimal::is_quiet_nan, Decimal::is_qnan, Decimal::is_signaling_nan, Decimal::is_snan
These distinguish quiet from signaling NaNs; each pair are aliases.
pub fn Decimal::is_quiet_nan(Self) -> Bool
pub fn Decimal::is_qnan(Self) -> Bool
pub fn Decimal::is_signaling_nan(Self) -> Bool
pub fn Decimal::is_snan(Self) -> Bool
Decimal::is_canonical
is_canonical always returns true: every Decimal value is canonical (only
interchange encodings can be non-canonical, see
GdaInterchange::is_canonical).
pub fn Decimal::is_canonical(Self) -> Bool
Decimal::nan_payload, Decimal::get_payload, Decimal::set_payload, Decimal::set_payload_signaling
These read and replace a NaN payload.
pub fn Decimal::nan_payload(Self) -> @bigint.BigInt
pub fn Decimal::get_payload(Self) -> @bigint.BigInt
pub fn Decimal::set_payload(Self, @bigint.BigInt) -> Self
pub fn Decimal::set_payload_signaling(Self, @bigint.BigInt) -> Self
nan_payload and get_payload return the payload of a NaN and 0 for any
other value. set_payload turns a NaN into a quiet NaN with the given payload
and the same sign; set_payload_signaling makes it signaling. Both return
non-NaN values unchanged.
Decimal::is_normal, Decimal::is_subnormal, Decimal::class_name
These classify a value against the exponent range of a DecimalContext.
pub fn Decimal::is_normal(Self, DecimalContext) -> Bool
pub fn Decimal::is_subnormal(Self, DecimalContext) -> Bool
pub fn Decimal::class_name(Self, DecimalContext) -> String
A nonzero finite value is normal when and subnormal when
; zeros, infinities and NaNs are neither. class_name
returns the GDA class string: sNaN, NaN, -Infinity, +Infinity,
-Zero, +Zero, -Subnormal, +Subnormal, -Normal or +Normal. The GDA
forms taking a GdaContext are the package functions
class_name, is_normal, is_subnormal.
Sign, cohort and precision transformations
Decimal::neg, Decimal::abs, Decimal::copy, Decimal::copy_abs, Decimal::copy_negate, Decimal::copy_sign
These change only the sign bit; they never round and never signal, even for a signaling NaN.
pub fn Decimal::neg(Self) -> Self
pub fn Decimal::abs(Self) -> Self
pub fn Decimal::copy(Self) -> Self
pub fn Decimal::copy_abs(Self) -> Self
pub fn Decimal::copy_negate(Self) -> Self
pub fn Decimal::copy_sign(Self, Self) -> Self
neg and copy_negate flip the sign, abs and copy_abs clear it, copy
returns the value, and copy_sign(x, y) gives x the sign bit of y. These
are GDA copy operations; the rounding versions are the package functions
minus, plus, abs.
Decimal::normalized, Decimal::trim, Decimal::with_precision
These move a value within its cohort or round it to a new precision attribute.
pub fn Decimal::normalized(Self) -> Self
pub fn Decimal::trim(Self) -> Self
pub fn Decimal::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self
normalized rounds half to even to the stored precision and removes all
trailing zeros (7.50 becomes 7.5, 1200 becomes 1.2E+3). trim removes
only fractional trailing zeros and never makes the exponent positive (7.50
becomes 7.5, 1200 stays 1200); a zero becomes 0 with exponent 0.
with_precision(p, mode) rounds to p digits with mode, removes trailing
zeros and sets the precision attribute; special values only get the new
attribute. None of them report flags.
Decimal::same_quantum
same_quantum tests whether two values have the same exponent.
pub fn Decimal::same_quantum(Self, Self) -> Bool
It is true for two finite values with equal exponents, for two infinities and for two NaNs, and false otherwise.
The GDA context
GdaContext
GdaContext is the immutable GDA context: arithmetic policy plus sticky status
plus enabled traps.
pub struct GdaContext {
// private fields
}
The policy is precision , a GdaRoundingMode, ,
clamp and extended. The status is a GdaFlags value that operations only
ever enlarge; the traps are a GdaTrapSet. Neither status nor traps influence
the numerical result of an operation: they only decide the next context and
whether the outcome is Completed or Trapped.
GdaContext::new, GdaContext::try_new
These build a context with an empty status.
pub fn GdaContext::new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Self
pub fn GdaContext::try_new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Result[Self, @arithmetic.ArithmeticError]
Defaults: precision=34, rounding=HalfEven, e_min=-999_999_999,
e_max=999_999_999, clamp=false, extended=true, no traps. new aborts
when precision <= 0 or e_min > e_max; try_new returns
Err(domain_error) instead. clamp=true limits exponents to
as the interchange formats do. extended=false selects GDA
subset arithmetic: operands longer than digits are rounded first
(raising LostDigits when that is inexact), special values cannot be parsed,
zeros and some results are normalized, and fma is invalid.
GdaContext::basic, GdaContext::default, GdaContext::decimal32, GdaContext::decimal64, GdaContext::decimal128
These return the standard contexts.
pub fn GdaContext::basic() -> Self
pub fn GdaContext::default() -> Self
pub fn GdaContext::decimal32() -> Self
pub fn GdaContext::decimal64() -> Self
pub fn GdaContext::decimal128() -> Self
| Context | rounding | clamp | extended | traps | |||
|---|---|---|---|---|---|---|---|
basic, default | 9 | HalfUp | no | no | DivisionByZero, InvalidOperation, Overflow, Underflow, Clamped | ||
decimal32 | 7 | HalfEven | yes | yes | none | ||
decimal64 | 16 | HalfEven | yes | yes | none | ||
decimal128 | 34 | HalfEven | yes | yes | none |
basic is the GDA basic default context; default is the same value. The
values are created once and shared.
context, decimal32_context, decimal64_context, decimal128_context
These package functions are shorthands for GdaContext::new (without a trap
argument) and the three interchange presets.
pub fn context(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool) -> GdaContext
pub fn decimal32_context() -> GdaContext
pub fn decimal64_context() -> GdaContext
pub fn decimal128_context() -> GdaContext
GdaContext::precision, GdaContext::rounding, GdaContext::e_min, GdaContext::e_max, GdaContext::clamp, GdaContext::extended, GdaContext::radix
These read the arithmetic policy.
pub fn GdaContext::precision(Self) -> Int
pub fn GdaContext::rounding(Self) -> GdaRoundingMode
pub fn GdaContext::e_min(Self) -> Int
pub fn GdaContext::e_max(Self) -> Int
pub fn GdaContext::clamp(Self) -> Bool
pub fn GdaContext::extended(Self) -> Bool
pub fn GdaContext::radix(Self) -> Int
radix always returns 10.
GdaContext::status, GdaContext::traps
These read the sticky status and the enabled traps.
pub fn GdaContext::status(Self) -> GdaFlags
pub fn GdaContext::traps(Self) -> GdaTrapSet
GdaContext::trap, GdaContext::with_traps, GdaContext::clear_status, GdaContext::reset
These return a new context with changed traps or status; the receiver is not modified.
pub fn GdaContext::trap(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaContext::with_traps(Self, GdaTrapSet) -> Self
pub fn GdaContext::clear_status(Self) -> Self
pub fn GdaContext::reset(Self) -> Self
trap(s) enables (or with enabled=false disables) one trap; with_traps
replaces the whole set. clear_status empties the status and keeps the traps;
reset empties both.
GdaRoundingMode
GdaRoundingMode lists the eight GDA rounding modes.
pub(all) enum GdaRoundingMode {
HalfEven
HalfUp
HalfDown
Down
Ceiling
Floor
Up
ZeroFiveUp
}
pub fn GdaRoundingMode::equal(Self, Self) -> Bool
pub fn GdaRoundingMode::not_equal(Self, Self) -> Bool
When the exact result lies strictly between two representable neighbours,
Down takes the one nearer zero, Up the one farther from zero, Ceiling the
larger, Floor the smaller; HalfEven, HalfUp and HalfDown take the
nearer one and break an exact tie towards an even last digit, away from zero,
or towards zero respectively; ZeroFiveUp rounds towards zero unless that
leaves a last digit of 0 or 5, in which case it rounds away from zero. The
design page gives each mode as
a formula.
Signals, flags and traps
GdaSignal
GdaSignal names the thirteen GDA conditions.
pub(all) enum GdaSignal {
ConversionSyntax
DivisionByZero
DivisionImpossible
DivisionUndefined
InvalidContext
InvalidOperation
Overflow
Underflow
Subnormal
Inexact
Rounded
Clamped
LostDigits
}
pub fn GdaSignal::equal(Self, Self) -> Bool
pub fn GdaSignal::not_equal(Self, Self) -> Bool
The GDA signals are Clamped, DivisionByZero, Inexact,
InvalidOperation, Overflow, Rounded, Subnormal and Underflow.
ConversionSyntax, DivisionImpossible, DivisionUndefined and
InvalidContext are conditions that the specification reports through the
InvalidOperation signal; the package keeps them as separate flags and traps
so you can tell them apart. LostDigits is raised only in subset arithmetic.
GdaFlags
GdaFlags is a set of conditions, used both for the conditions raised by one
operation and for the sticky status of a context.
pub struct GdaFlags {
conversion_syntax : Bool
division_by_zero : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
invalid_operation : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
inexact : Bool
rounded : Bool
clamped : Bool
lost_digits : Bool
} derive(Eq)
pub fn GdaFlags::none() -> Self
pub fn GdaFlags::contains(Self, GdaSignal) -> Bool
pub fn GdaFlags::combine(Self, Self) -> Self
pub fn GdaFlags::equal(Self, Self) -> Bool
pub fn GdaFlags::not_equal(Self, Self) -> Bool
The fields are read-only; build sets with none and combine (field-wise
union). contains(s) reads the field for s, except that
contains(InvalidOperation) is true when any of invalid_operation,
conversion_syntax, division_impossible, division_undefined or
invalid_context is set.
GdaTrapSet
GdaTrapSet is the set of enabled traps.
pub struct GdaTrapSet {
conversion_syntax : Bool
division_by_zero : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
invalid_operation : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
inexact : Bool
rounded : Bool
clamped : Bool
lost_digits : Bool
} derive(Eq)
pub fn GdaTrapSet::none() -> Self
pub fn GdaTrapSet::with_signal(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaTrapSet::contains(Self, GdaSignal) -> Bool
pub fn GdaTrapSet::equal(Self, Self) -> Bool
pub fn GdaTrapSet::not_equal(Self, Self) -> Bool
with_signal(s) enables one trap (or disables it with enabled=false);
contains(s) reads exactly the field for s.
GdaOutcome
GdaOutcome[T] is the result of every GDA operation.
pub(all) enum GdaOutcome[T] {
Completed(T, GdaContext, GdaFlags)
Trapped(GdaSignal, T, GdaContext, GdaFlags)
}
pub fn[T] GdaOutcome::value(Self[T]) -> T
pub fn[T] GdaOutcome::next_context(Self[T]) -> GdaContext
pub fn[T] GdaOutcome::raised(Self[T]) -> GdaFlags
Both variants carry the GDA-defined result, the next context and the
conditions raised by this operation; Trapped also names the trap that fired.
value, next_context and raised read the common fields without matching.
Trap selection
Every GDA function finishes the same way. Let be the conditions the operation raised and the input context.
- If is empty the outcome is
Completed(v, C, none): the very same context comes back. - Otherwise the next context is with status
, where the
invalid_operationflag is also set whenever contains one of the four detailed invalid conditions. - The trapped signal is the first in the order below with
raised.contains(s)andtraps.contains(s): InvalidOperation, DivisionByZero, DivisionUndefined, DivisionImpossible, InvalidContext, ConversionSyntax, Overflow, Underflow, Subnormal, Inexact, Rounded, Clamped, LostDigits. If there is one the outcome isTrapped(s, v, C', R), otherwiseCompleted(v, C', R).
Because contains(InvalidOperation) covers the detailed invalid conditions,
an InvalidOperation trap catches all of them, and it wins over a trap on the
detailed condition itself.
///|
test "GDA context, status and traps" {
let ctx = @decimal_gda.GdaContext::decimal64()
.trap(DivisionUndefined)
.trap(InvalidOperation)
let zero = @decimal_gda.Decimal::zero()
let out = @decimal_gda.divide(zero, zero, ctx) // 0/0
inspect(out.value(), content="nan")
inspect(out.raised().division_undefined, content="true")
inspect(out.raised().contains(InvalidOperation), content="true")
match out {
@decimal_gda.GdaOutcome::Trapped(signal, _, _, _) =>
inspect(signal == InvalidOperation, content="true")
@decimal_gda.GdaOutcome::Completed(_, _, _) => fail("expected a trap")
}
inspect(out.next_context().status().invalid_operation, content="true")
inspect(ctx.status() == @decimal_gda.GdaFlags::none(), content="true")
inspect(ctx.reset().traps() == @decimal_gda.GdaTrapSet::none(), content="true")
}
GDA operations
Every function in this section takes its operands and a GdaContext, rounds
to that context, and returns a GdaOutcome built by the
trap selection rule. A signaling-NaN operand raises
InvalidOperation and yields the corresponding quiet NaN; a quiet NaN operand
propagates without raising anything (the first NaN operand wins). In subset
contexts (extended=false) finite operands longer than the precision are
rounded first. Unless stated otherwise the result is the exact mathematical
result rounded once, with the ideal exponent listed for the operation when
the result is exact.
parse
parse is the GDA to-number conversion of a string.
pub fn parse(String, GdaContext) -> GdaOutcome[Decimal]
The literal keeps its exponent unless it must be rounded to the precision or
clamped to the exponent range. Malformed text gives a quiet NaN with
ConversionSyntax. In subset contexts infinities and NaNs are also a
conversion-syntax error.
apply, plus, minus, abs
These round one operand to the context: plus is , minus is
, abs is , and apply is the plain conversion of a value to the
context.
pub fn apply(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn abs(Decimal, GdaContext) -> GdaOutcome[Decimal]
Ideal exponent: that of the operand. plus, minus and abs return a zero
result as ; apply keeps the sign of a zero and does not round subset
operands first.
add, subtract, multiply, divide, fma
These are the basic arithmetic operations; fma(a, b, c) is
with a single rounding.
pub fn add(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn subtract(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn multiply(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn divide(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn fma(Decimal, Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
Ideal exponents: for add and subtract; for
multiply; for divide (an inexact quotient has a full
-digit coefficient); for fma, the add rule applied to the exact product
and the addend. An exact zero sum is , or when both operands are
negative or the mode is Floor. Special cases: ,
and are invalid; is
with DivisionByZero; is NaN with DivisionUndefined;
is a zero with exponent and Clamped. fma
is invalid in a subset context.
divide_integer, remainder, remainder_near
These divide to an integer quotient.
pub fn divide_integer(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder_near(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
divide_integer returns with exponent 0;
remainder returns (the sign of ); remainder_near returns
where is rounded to the nearest integer, ties to even.
The remainder has ideal exponent . When (or ) needs
more than digits the result is NaN with DivisionImpossible. A zero
divisor gives DivisionByZero (divide_integer of a nonzero number) or
DivisionUndefined (); a zero divisor or an infinite dividend makes
both remainders invalid; a finite dividend with an infinite divisor is its
own remainder.
quantize, rescale
These round a value to a prescribed exponent.
pub fn quantize(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rescale(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
quantize(x, q) returns the value of with exponent , rounded with the
context mode (raising Rounded, and Inexact when digits are lost).
rescale(x, n) does the same with exponent , where must be an integer
value. The result is invalid when the target exponent lies outside
( in subset contexts),
when the result coefficient would need more than digits, or when exactly
one operand is infinite. Two infinities give the infinity. A quantized result
never raises Underflow.
to_integral_exact, to_integral_value
These round to an integer with the context rounding mode.
pub fn to_integral_exact(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn to_integral_value(Decimal, GdaContext) -> GdaOutcome[Decimal]
A value with negative exponent is quantized to exponent 0; to_integral_exact
raises Inexact and Rounded when digits are dropped and
to_integral_value never does. A value with exponent is passed
through apply, so it is rounded to the context precision if it is longer
than digits.11 The GDA reference implementation returns such operands unchanged;
for example, at precision 3 it maps 12345 to 12345, while this package
returns 1.23E+4 with Inexact. The pinned test suite has no such row.
sqrt, exp, ln, log10
These are the correctly rounded square root, exponential, natural logarithm and base-10 logarithm.
pub fn sqrt(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn exp(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn ln(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn log10(Decimal, GdaContext) -> GdaOutcome[Decimal]
They always round half to even, whatever the context rounding mode. Exact
results: sqrt of a perfect square has the ideal exponent ; exp(0) = 1; ln(1) = 0; log10 of a power of ten is the
integer . Every other finite result is inexact with digits. Domain:
the square root and logarithms of a negative number are invalid,
, , and maps to
for all four. exp, ln and log10 raise InvalidContext unless
, and are at most 999,999. If the certified
evaluation cannot decide the rounding within its refinement budget the result
is NaN with InvalidOperation. In a subset context, ln reproduces the
result of the classic reference algorithm, which can exceed the correctly
rounded result by one unit in the last place.
power
power(x, y) is .
pub fn power(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
For an integer the result is computed by binary powering with
working digits (one fewer in subset
contexts) and then rounded with the context mode; an exact power that fits in
digits is returned exactly with exponent . For a non-integer
, must be positive (a negative base is invalid) and the result is
certified to be correctly rounded with the context rounding mode;
is computed as a square root under the context rounding mode. The
same context limits as for exp apply to non-integer exponents. Special
cases follow GDA: (and is invalid), powers of and
take their sign from the parity of an integer exponent, and .
reduce
reduce rounds to the context and removes trailing zeros.
pub fn reduce(Decimal, GdaContext) -> GdaOutcome[Decimal]
A zero becomes with exponent 0 (keeping its sign in extended contexts). In a clamped context the exponent is not raised above .
scaleb, logb
These scale by a power of ten and extract the adjusted exponent.
pub fn scaleb(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logb(Decimal, GdaContext) -> GdaOutcome[Decimal]
scaleb(x, n) returns by adding to the exponent; must
be an integer with exponent 0 and , otherwise the
result is invalid. The result is then checked for overflow, subnormality and
clamping. logb(x) returns as an integer; logb(0) is
with DivisionByZero and logb(±∞) is .
next_plus, next_minus, next_toward
These step to the adjacent representable value.
pub fn next_plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_toward(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
next_plus returns the smallest representable number greater than in the
context and next_minus the largest smaller one; from a zero they step to
, and past the largest finite number they reach
. Neither raises flags for finite results. next_toward(x, y)
steps from towards (returning , with the sign of for zeros, when
they compare equal) and raises Overflow, or Underflow and Subnormal,
together with Inexact and Rounded, when the step leaves the normal range.
logical_and, logical_or, logical_xor, logical_invert
These are digit-wise logical operations on logical operands: non-negative integers with exponent 0 whose digits are all 0 or 1.
pub fn logical_and(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_or(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_xor(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_invert(Decimal, GdaContext) -> GdaOutcome[Decimal]
Each operand is read as exactly digits: shorter operands are padded with
leading zeros and only the low digits of longer ones are used.
logical_invert inverts all digits. Any other operand makes the result
invalid.
shift, rotate
These move the coefficient digits of by places within a window of digits.
pub fn shift(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rotate(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
must be an integer with exponent 0 and , otherwise the result
is invalid. A positive moves digits to the left. shift drops the digits
that leave the window and fills with zeros; rotate moves them round to the
other end. The exponent and sign are unchanged; an infinite is returned
unchanged.
compare, compare_signal, compare_total, compare_total_magnitude
These compare two values.
pub fn compare(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_signal(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_total(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]
pub fn compare_total_magnitude(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]
compare returns the decimal , or by numeric value (,
), or a quiet NaN when an operand is a NaN (raising
InvalidOperation only for a signaling NaN). compare_signal is the same but
raises InvalidOperation for any NaN. compare_total returns , or
in the GDA total order: by sign bit first, then, for positive values,
, finite values by numeric
value and then by exponent (2.50 < 2.5), NaNs by payload; the order is
reversed for negative values. compare_total_magnitude applies the total
order to the absolute values. The total orders never raise flags.
max, min, max_mag, min_mag
These are the GDA max and min operations, on values or on magnitudes.
pub fn max(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn max_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
A single quiet NaN is ignored in favour of the number; two quiet NaNs give
the first; a signaling NaN gives a quiet NaN with InvalidOperation. Values
that compare equal are separated by the total order (so max(2.5, 2.50) is
2.5). The selected operand is then rounded to the context as by plus.
class_name, is_normal, is_subnormal, same_quantum
These classify values under a context; they never raise conditions, so they
always return Completed with the input context.
pub fn class_name(Decimal, GdaContext) -> GdaOutcome[String]
pub fn is_normal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn is_subnormal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn same_quantum(Decimal, Decimal, GdaContext) -> GdaOutcome[Bool]
They wrap Decimal::class_name,
Decimal::is_normal, Decimal::is_subnormal and
Decimal::same_quantum.
///|
test "GDA operation sampler" {
let ctx = @decimal_gda.GdaContext::decimal64()
let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
inspect(@decimal_gda.divide_integer(d("17"), d("5"), ctx).value(), content="3")
inspect(@decimal_gda.remainder(d("-17"), d("5"), ctx).value(), content="-2")
inspect(@decimal_gda.remainder_near(d("17"), d("5"), ctx).value(), content="2")
inspect(@decimal_gda.fma(d("1.5"), d("2"), d("0.25"), ctx).value(), content="3.25")
inspect(@decimal_gda.to_integral_exact(d("2.5"), ctx).value(), content="2")
inspect(@decimal_gda.rescale(d("1.2345"), d("-2"), ctx).value(), content="1.23")
inspect(@decimal_gda.reduce(d("120.00"), ctx).value(), content="1.2E+2")
inspect(@decimal_gda.scaleb(d("1.5"), d("3"), ctx).value(), content="1.5E+3")
inspect(@decimal_gda.logb(d("0.00123"), ctx).value(), content="-3")
inspect(@decimal_gda.next_plus(d("1"), ctx).value(), content="1.000000000000001")
inspect(@decimal_gda.logical_xor(d("1100"), d("1010"), ctx).value(), content="110")
inspect(@decimal_gda.shift(d("12345"), d("2"), ctx).value(), content="1234500")
inspect(@decimal_gda.rotate(d("12345"), d("-1"), @decimal_gda.context(precision=5)).value(), content="51234")
inspect(@decimal_gda.power(d("2"), d("-3"), ctx).value(), content="0.125")
inspect(@decimal_gda.max(d("2.5"), d("2.50"), ctx).value(), content="2.5")
inspect(@decimal_gda.class_name(d("-0"), ctx).value(), content="-Zero")
let wide = @decimal_gda.context() // exponent range ±999,999,999
inspect(@decimal_gda.exp(d("1"), wide).raised().invalid_context, content="true")
}
Ordering and plain arithmetic on values
These methods and operators take no context. They never signal and never trap; use the GDA functions when flags matter.
Decimal::compare, Decimal::compare_checked
compare is a three-way numeric comparison that is total on all values;
compare_checked refuses NaNs.
pub fn Decimal::compare(Self, Self) -> Int
pub fn Decimal::compare_checked(Self, Self) -> Result[Int, @arithmetic.ArithmeticError]
pub impl Compare for Decimal
pub impl @arithmetic.CompareChecked for Decimal
compare orders finite values and infinities numerically with and
places every NaN equal to every other NaN and above every number, so it is a
total preorder and sorting never aborts. compare_checked returns
Err(unordered_comparison) when either operand is a NaN.
Decimal::equal, Decimal::not_equal, Decimal::op_lt, Decimal::op_le, Decimal::op_gt, Decimal::op_ge
These are the Eq and Compare operator methods.
pub fn Decimal::equal(Self, Self) -> Bool
pub fn Decimal::not_equal(Self, Self) -> Bool
pub fn Decimal::op_lt(Self, Self) -> Bool
pub fn Decimal::op_le(Self, Self) -> Bool
pub fn Decimal::op_gt(Self, Self) -> Bool
pub fn Decimal::op_ge(Self, Self) -> Bool
pub impl Eq for Decimal
== is numeric equality on finite values (, ),
sign equality on infinities, and true for any two NaNs. <, <=, >, >=
follow compare.
Decimal::compare_total, Decimal::compare_total_magnitude
These are the GDA total orders as plain methods, returning , or .
pub fn Decimal::compare_total(Self, Self) -> Int
pub fn Decimal::compare_total_magnitude(Self, Self) -> Int
They agree with the package functions
compare_total, compare_total_magnitude
(without subset operand rounding).
Decimal::min, Decimal::max, Decimal::clamp, Decimal::clamp_checked
These select between values without rounding.
pub fn Decimal::min(Self, Self) -> Self
pub fn Decimal::max(Self, Self) -> Self
pub fn Decimal::clamp(Self, min~ : Self, max~ : Self) -> Self
pub fn Decimal::clamp_checked(Self, min~ : Self, max~ : Self) -> Result[Self, @arithmetic.ArithmeticError]
min and max return the other operand when one is a quiet NaN, the first
NaN (quieted) when a signaling NaN is involved or both are NaN, and the
receiver when the two compare equal. clamp returns min or max when the
value lies outside and the value otherwise (a NaN value is
returned unchanged); it aborts when a bound is NaN or min > max, where
clamp_checked returns Err(domain_error).
Decimal::add, Decimal::sub, Decimal::mul, Decimal::div, Decimal::neg
These implement +, -, *, / and unary - without a context.
pub fn Decimal::add(Self, Self) -> Self
pub fn Decimal::sub(Self, Self) -> Self
pub fn Decimal::mul(Self, Self) -> Self
pub fn Decimal::div(Self, Self) -> Self
pub impl Add for Decimal
pub impl Sub for Decimal
pub impl Mul for Decimal
pub impl Div for Decimal
pub impl Neg for Decimal
Let be the larger precision attribute of the operands. +, - and /
round half to even to digits and then remove trailing zeros; * returns
the exact product (it is never rounded) with attribute . Special values
follow IEEE rules without signals: NaN operands give a quiet NaN,
, , and give NaN,
gives a signed infinity and gives . neg is
Decimal::neg.
Decimal::div_checked, Decimal::sqrt
These are checked conveniences that use a default context of the larger operand precision.
pub fn Decimal::div_checked(Self, Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt(Self) -> Result[Self, @arithmetic.ArithmeticError]
div_checked divides with DecimalContext::new(precision=P) and returns
Err(division_by_zero) for a zero divisor and Err(domain_error) for an
invalid division. sqrt takes the square root at the value’s own precision
attribute and returns Err(domain_error) for negative operands.
///|
test "context-free ordering and operators" {
let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
inspect(d("2.50") == d("2.5"), content="true")
inspect(d("2.50").compare_total(d("2.5")), content="-1")
inspect(@decimal_gda.Decimal::nan() == @decimal_gda.Decimal::nan(), content="true")
inspect(d("1").compare(@decimal_gda.Decimal::nan()), content="-1")
inspect(d("1").compare_checked(@decimal_gda.Decimal::nan()) is Err(_), content="true")
inspect(d("1.10") + d("2.20"), content="3.3")
inspect(d("1.10") * d("2.20"), content="2.4200")
inspect(d("1") / d("3"), content="0.3333333333333333333333333333333333")
inspect(d("5").clamp(min=d("0"), max=d("3")), content="3")
}
The status-free context layer
The GDA functions are thin wrappers over the methods below: each converts the
GdaContext policy to a DecimalContext, calls one method, and feeds the
returned DecimalFlags to trap selection. You can call the
layer directly when you want per-operation flags without sticky status, or the
IEEE-style extras it adds (IEEE 754-2019 minimum/maximum, a choice of
tininess detection). The decimal package, not this layer, is
the supported IEEE 754 implementation.
DecimalContext
DecimalContext is a status-free context: precision, two views of the
rounding mode, exponent range, clamp, extended and tininess detection.
pub struct DecimalContext {
// private fields
} derive(Eq)
pub fn DecimalContext::new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Self
pub fn DecimalContext::try_new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Result[Self, @arithmetic.ArithmeticError]
pub fn DecimalContext::exact() -> Self
pub fn DecimalContext::decimal32() -> Self
pub fn DecimalContext::decimal64() -> Self
pub fn DecimalContext::decimal128() -> Self
pub fn DecimalContext::from_arithmetic_context(@arithmetic.ArithmeticContext) -> Self
pub fn DecimalContext::precision(Self) -> Int
pub fn DecimalContext::rounding(Self) -> @arithmetic.RoundingMode
pub fn DecimalContext::decimal_rounding(Self) -> DecimalRoundingMode
pub fn DecimalContext::with_rounding(Self, @arithmetic.RoundingMode) -> Self
pub fn DecimalContext::e_min(Self) -> Int
pub fn DecimalContext::e_max(Self) -> Int
pub fn DecimalContext::clamp(Self) -> Bool
pub fn DecimalContext::extended(Self) -> Bool
pub fn DecimalContext::tininess(Self) -> DecimalTininessDetection
pub fn DecimalContext::with_tininess(Self, DecimalTininessDetection) -> Self
pub fn DecimalContext::equal(Self, Self) -> Bool
pub fn DecimalContext::not_equal(Self, Self) -> Bool
Defaults are those of GdaContext::new with rounding=ToNearestEven and
tininess=BeforeRounding. The rounding actually used is decimal_rounding,
which defaults to the translation of rounding
(DecimalRoundingMode::from_arithmetic); pass decimal_rounding to select
HalfUp, HalfDown or ZeroFiveUp. with_rounding sets both views. new
aborts and try_new returns Err(domain_error) for precision <= 0 or
e_min > e_max. exact() is the unbounded-precision context (precision 0):
results are never rounded. decimal32/64/128 match the GdaContext
presets. from_arithmetic_context copies precision, rounding, the optional
exponent bounds (default ) and clamp. The GDA functions
always use BeforeRounding tininess.
DecimalRoundingMode
DecimalRoundingMode is the same eight-mode set as GdaRoundingMode, for the
status-free layer.
pub(all) enum DecimalRoundingMode {
HalfEven
HalfUp
HalfDown
Down
Ceiling
Floor
Up
ZeroFiveUp
} derive(Eq)
pub fn DecimalRoundingMode::from_arithmetic(@arithmetic.RoundingMode) -> Self
pub fn DecimalRoundingMode::to_arithmetic(Self) -> @arithmetic.RoundingMode?
pub fn DecimalRoundingMode::equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::not_equal(Self, Self) -> Bool
from_arithmetic maps ToNearestEven, TowardZero, TowardPositive,
TowardNegative, AwayFromZero to HalfEven, Down, Ceiling, Floor,
Up; to_arithmetic is its inverse and returns None for HalfUp,
HalfDown and ZeroFiveUp.
DecimalTininessDetection
DecimalTininessDetection chooses when a result counts as tiny for
Underflow and Subnormal.
pub(all) enum DecimalTininessDetection {
BeforeRounding
AfterRounding
} derive(Eq)
pub fn DecimalTininessDetection::equal(Self, Self) -> Bool
pub fn DecimalTininessDetection::not_equal(Self, Self) -> Bool
BeforeRounding tests the adjusted exponent of the exact result against
; AfterRounding tests the result rounded to .
DecimalSignal, DecimalFlags
These are the per-operation condition names and flag set of the status-free layer.
pub(all) enum DecimalSignal {
ConversionSyntax
DivisionByZero
DivisionImpossible
DivisionUndefined
InvalidContext
InvalidOperation
Overflow
Underflow
Subnormal
Inexact
Rounded
Clamped
LostDigits
} derive(Eq)
pub fn DecimalSignal::equal(Self, Self) -> Bool
pub fn DecimalSignal::not_equal(Self, Self) -> Bool
pub struct DecimalFlags {
inexact : Bool
rounded : Bool
lost_digits : Bool
invalid_operation : Bool
division_by_zero : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
clamped : Bool
conversion_syntax : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
} derive(Eq)
pub fn DecimalFlags::new() -> Self
pub fn DecimalFlags::combine(Self, Self) -> Self
pub fn DecimalFlags::contains(Self, DecimalSignal) -> Bool
pub fn DecimalFlags::has_error(Self) -> Bool
pub fn DecimalFlags::equal(Self, Self) -> Bool
pub fn DecimalFlags::not_equal(Self, Self) -> Bool
new is the empty set and combine the union. Unlike GdaFlags,
DecimalFlags::contains(InvalidOperation) reads only the
invalid_operation field (the layer sets it together with
division_undefined and division_impossible, but not with
conversion_syntax or invalid_context). has_error is true when any of
invalid_operation, division_by_zero, division_undefined,
division_impossible or invalid_context is set.
Context methods of Decimal
Each method below is the status-free form of the GDA function of the same
name; it rounds with the given DecimalContext and returns
(result, DecimalFlags).
pub fn Decimal::apply_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::plus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::abs_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::add_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sub_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::mul_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::div_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::fma_ctx(Self, Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::divide_integer(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_near(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::quantize(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rescale(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_exact(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_value(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::reduce_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::scaleb_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logb_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_plus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_minus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_toward(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_and(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_or(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_xor(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_invert(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::shift_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rotate_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_signal_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_total_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::compare_total_magnitude_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::min_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
The results and flags are exactly those the GDA function reports in its
outcome. (The GDA functions parse, add, subtract, multiply and fma
first try a fast path for small exact integer operands; it is taken only when
it produces the same value with no flags.)
Decimal::sqrt_ctx, Decimal::exp_ctx, Decimal::ln_ctx, Decimal::log10_ctx, Decimal::power_ctx
These are the status-free elementary functions.
pub fn Decimal::sqrt_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exp_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::ln_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::power_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
Unlike the GDA functions sqrt, exp, ln and log10, these methods round
with the context’s own rounding mode (the GDA functions pass them a half-even
copy of the context). A certification failure gives NaN with
invalid_operation.
Decimal::try_exp_ctx, Decimal::try_ln_ctx, Decimal::try_log10_ctx, Decimal::try_power_ctx
These are the same functions with certification failures reported as errors.
pub fn Decimal::try_exp_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_ln_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_power_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
When the refinement budget (twelve precision increases) is exhausted without
certifying the rounding, they return Err(certification_failure(...)) with
the operation name, target precision, final working precision and refinement
count. Domain errors are still reported as NaN plus flags inside Ok.
Decimal::normalize_ctx, Decimal::remainder_ctx
These are aliases kept for the IEEE vocabulary.
pub fn Decimal::normalize_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
normalize_ctx is reduce_ctx; remainder_ctx is the IEEE remainder, which
is remainder_near.
Decimal::minimum_ctx, Decimal::maximum_ctx and their number and magnitude variants
These are the IEEE 754-2019 minimum, maximum, minimumNumber,
maximumNumber, minimumMagnitude, maximumMagnitude,
minimumMagnitudeNumber and maximumMagnitudeNumber operations.
pub fn Decimal::minimum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
The plain variants return a quiet NaN when either operand is a NaN; the
number variants return the number when exactly one operand is a NaN. A
signaling NaN raises invalid_operation in both. Equal values are separated by
the total order. The *_mag_ctx names are aliases of the *_magnitude_ctx
ones. These are not GDA operations and have no GdaContext form.
///|
test "status-free layer" {
let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
let ctx = @decimal_gda.DecimalContext::new(precision=5, decimal_rounding=HalfUp)
let (q, flags) = d("2").div_ctx(d("3"), ctx)
inspect(q, content="0.66667")
inspect(flags.inexact, content="true")
inspect(flags.contains(Rounded), content="true")
let floor = @decimal_gda.DecimalContext::new(
precision=3,
rounding=TowardNegative,
e_min=-999_999,
e_max=999_999,
)
inspect(d("1").exp_ctx(floor).0, content="2.71") // context rounding
let nan = @decimal_gda.Decimal::nan()
inspect(d("1").maximum_ctx(nan, ctx).0, content="nan")
inspect(d("1").maximum_number_ctx(nan, ctx).0, content="1")
let (_, zero_div) = d("0").div_ctx(d("0"), ctx)
inspect(zero_div.has_error(), content="true")
}
Interchange encodings
GdaInterchangeFormat
GdaInterchangeFormat names the three IEEE 754 decimal interchange formats.
pub(all) enum GdaInterchangeFormat {
Decimal32
Decimal64
Decimal128
} derive(Eq)
pub fn GdaInterchangeFormat::context(Self) -> DecimalContext
pub fn GdaInterchangeFormat::equal(Self, Self) -> Bool
pub fn GdaInterchangeFormat::not_equal(Self, Self) -> Bool
context returns the matching DecimalContext preset (precision 7, 16 or
34, clamped).
GdaInterchange
GdaInterchange is a decimal32, decimal64 or decimal128 bit pattern in the
densely packed decimal (DPD) encoding.
pub struct GdaInterchange {
// private fields
}
pub fn GdaInterchange::format(Self) -> GdaInterchangeFormat
format returns the format of the pattern.
GdaInterchange::from_decimal, GdaInterchange::to_decimal, GdaInterchange::to_decimal_ctx
These encode and decode values.
pub fn GdaInterchange::from_decimal(Decimal, GdaInterchangeFormat) -> (Self, DecimalFlags)
pub fn GdaInterchange::to_decimal(Self) -> Decimal
pub fn GdaInterchange::to_decimal_ctx(Self) -> (Decimal, DecimalFlags)
from_decimal rounds the value to the format (reporting the rounding,
overflow, underflow and clamping flags) and encodes it. to_decimal decodes
exactly, keeping the exponent; to_decimal_ctx also reports subnormal for
a subnormal value.
GdaInterchange::from_hex, GdaInterchange::to_hex
These convert between a bit pattern and its hexadecimal text.
pub fn GdaInterchange::from_hex(String, GdaInterchangeFormat) -> Self?
pub fn GdaInterchange::to_hex(Self) -> String
The text is # (optional on input) followed by exactly 8, 16 or 32
hexadecimal digits; surrounding spaces are ignored and any other input gives
None. to_hex prints # and uppercase digits.
GdaInterchange::canonical, GdaInterchange::is_canonical
These canonicalize an encoding.
pub fn GdaInterchange::canonical(Self) -> Self
pub fn GdaInterchange::is_canonical(Self) -> Bool
canonical decodes and re-encodes the pattern, which replaces non-canonical
declets and payloads with their canonical form; is_canonical tests whether
that changes the pattern.
GdaInterchange::copy, GdaInterchange::copy_abs, GdaInterchange::copy_negate, GdaInterchange::copy_sign
These operate on the sign bit of the encoding without decoding it.
pub fn GdaInterchange::copy(Self) -> Self
pub fn GdaInterchange::copy_abs(Self) -> Self
pub fn GdaInterchange::copy_negate(Self) -> Self
pub fn GdaInterchange::copy_sign(Self, Self) -> Self
copy_sign aborts when the two patterns have different formats.
Decimal::from_interchange_hex, Decimal::to_interchange_hex
These are the same conversions directly between Decimal and hexadecimal
text.
pub fn Decimal::from_interchange_hex(String, GdaInterchangeFormat) -> Self?
pub fn Decimal::to_interchange_hex(Self, GdaInterchangeFormat) -> (String, DecimalFlags)
///|
test "DPD interchange" {
let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
let (bits, flags) = @decimal_gda.GdaInterchange::from_decimal(d("1.234567890"), Decimal32)
inspect(bits.to_hex(), content="#25F4D2E8")
inspect(bits.to_decimal(), content="1.234568")
inspect(flags.inexact, content="true")
let back = @decimal_gda.Decimal::from_interchange_hex("#A2300000000003D0", Decimal64).unwrap()
inspect(back, content="-7.50")
inspect(bits.copy_negate().to_decimal(), content="-1.234568")
}
Trait implementations
Luna-Flow/arithmetic contextual traits
These adapt the status-free layer to ArithmeticContext.
pub fn Decimal::add_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sub_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::mul_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::div_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::abs_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::exp_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub impl @arithmetic.AddContextual for Decimal
pub impl @arithmetic.SubContextual for Decimal
pub impl @arithmetic.MulContextual for Decimal
pub impl @arithmetic.DivContextual for Decimal
pub impl @arithmetic.AbsContextual for Decimal
pub impl @arithmetic.SqrtContextual for Decimal
pub impl @arithmetic.ExpContextual for Decimal
Each converts the context with DecimalContext::from_arithmetic_context,
calls the _ctx method, and returns Err(division_by_zero) when
division_by_zero is raised, Err(domain_error) for any other error flag,
and otherwise Ok with the value and diagnostics inexact, rounded,
overflow, underflow, subnormal and clamped.
NumericFormatContextual
These describe the number format of an ArithmeticContext.
pub fn Decimal::zero_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::one_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::epsilon_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::min_normal_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::max_finite_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::classify_contextual(Self) -> @arithmetic.FpClass
pub impl @arithmetic.NumericFormatContextual for Decimal
epsilon_contextual is ,
min_normal_contextual is and max_finite_contextual is
.
Checked traits
These return Result instead of flags.
pub fn Decimal::parse_checked(String, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_checked(Self, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_int_checked(Self, Int, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_nat_checked(Self, UInt, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub impl @arithmetic.ParseChecked for Decimal
pub impl @arithmetic.SqrtChecked for Decimal
pub impl @arithmetic.PowIntChecked for Decimal
pub impl @arithmetic.PowNatChecked for Decimal
pub impl @arithmetic.DivChecked for Decimal
parse_checked is Decimal::parse at the context precision. sqrt_checked
returns Err(domain_error) for negative operands. pow_int_checked and
pow_nat_checked call power_ctx with an integer exponent; they return
Err(division_by_zero) for a zero base with a negative exponent,
Err(domain_error) for invalid results, and pow_nat_checked returns
Err(unsupported) for exponents above 999,999,999. DivChecked::div_checked
divides under the given context with the same errors as
Decimal::div_checked.
luna-generic algebra traits
These let generic algebra code use Decimal.
pub fn[S : @luna-generic.Nat] Decimal::from_nat(S) -> Self
pub fn[S : @luna-generic.Integral] Decimal::from_integral(S) -> Self
pub impl @luna-generic.NatHomomorphism for Decimal
pub impl @luna-generic.IntegralHomomorphism for Decimal
pub impl @luna-generic.Zero for Decimal
pub impl @luna-generic.One for Decimal
pub impl @luna-generic.AddMonoid for Decimal
pub impl @luna-generic.MulMonoid for Decimal
pub impl @luna-generic.AddGroup for Decimal
pub impl @luna-generic.Semiring for Decimal
pub impl @luna-generic.Ring for Decimal
from_nat and from_integral convert through BigInt with
Decimal::from_bigint (34 digits, trailing zeros removed), so they are exact
only for integers of at most 34 significant digits. Zero::zero and
One::one are Decimal::zero() and Decimal::one(). The ring structure uses
the context-free operators; because + rounds to the operand precision, the
ring laws hold exactly only while sums stay within that precision.
@def.Floating, Show, Debug
Decimal implements the floating vocabulary of the def package, Show (see
Decimal::to_string) and Debug.
pub impl @def.Floating for Decimal
pub fn Decimal::to_repr(Self) -> @debug.Repr
The Floating methods are classify, sign, precision,
with_precision and normalized, documented above. to_repr is the
structural Debug representation.
///|
test "trait adapters" {
let d = (s : String) => @decimal_gda.Decimal::from_string(s).unwrap()
let actx = @lf_arith.ArithmeticContext::new(4)
let out = d("2").div_contextual(d("3"), actx).unwrap()
inspect(out.value, content="0.6667")
inspect(out.diagnostics.inexact, content="true")
inspect(d("1").div_contextual(d("0"), actx) is Err(_), content="true")
inspect(@decimal_gda.Decimal::epsilon_contextual(actx), content="0.001")
inspect(d("1.5").pow_int_checked(3, actx).unwrap(), content="3.375")
inspect(@decimal_gda.Decimal::from_integral(1200), content="1.2E+3")
}
Complete public interface
This snapshot is the generated pkg.generated.mbti of the package. It is the authority when prose and interface disagree.
// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/decimal_gda"
import {
"Luna-Flow/arithmetic",
"Luna-Flow/floating/bin_float",
"Luna-Flow/floating/def",
"Luna-Flow/luna-generic",
"moonbitlang/core/bigint",
"moonbitlang/core/debug",
}
// Values
pub fn abs(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn add(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn apply(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn class_name(Decimal, GdaContext) -> GdaOutcome[String]
pub fn compare(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_signal(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn compare_total(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]
pub fn compare_total_magnitude(Decimal, Decimal, GdaContext) -> GdaOutcome[Int]
pub fn context(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool) -> GdaContext
pub fn decimal128_context() -> GdaContext
pub fn decimal32_context() -> GdaContext
pub fn decimal64_context() -> GdaContext
pub fn divide(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn divide_integer(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn exp(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn fma(Decimal, Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn is_normal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn is_subnormal(Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn ln(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn log10(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logb(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_and(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_invert(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_or(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn logical_xor(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn max(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn max_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn min_mag(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn multiply(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_minus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn next_toward(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn parse(String, GdaContext) -> GdaOutcome[Decimal]
pub fn plus(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn power(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn quantize(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn reduce(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn remainder_near(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rescale(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn rotate(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn same_quantum(Decimal, Decimal, GdaContext) -> GdaOutcome[Bool]
pub fn scaleb(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn shift(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn sqrt(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn subtract(Decimal, Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn to_integral_exact(Decimal, GdaContext) -> GdaOutcome[Decimal]
pub fn to_integral_value(Decimal, GdaContext) -> GdaOutcome[Decimal]
// Errors
// Types and methods
pub struct Decimal {
// private fields
} derive(@debug.Debug)
pub fn Decimal::abs(Self) -> Self
pub fn Decimal::abs_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::abs_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::add(Self, Self) -> Self
pub fn Decimal::add_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::add_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::apply_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::clamp(Self, min~ : Self, max~ : Self) -> Self
pub fn Decimal::clamp_checked(Self, min~ : Self, max~ : Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::class_name(Self, DecimalContext) -> String
pub fn Decimal::classify(Self) -> @arithmetic.FpClass
pub fn Decimal::classify_contextual(Self) -> @arithmetic.FpClass
pub fn Decimal::coefficient(Self) -> @bigint.BigInt
pub fn Decimal::compare(Self, Self) -> Int
pub fn Decimal::compare_checked(Self, Self) -> Result[Int, @arithmetic.ArithmeticError]
pub fn Decimal::compare_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_signal_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::compare_total(Self, Self) -> Int
pub fn Decimal::compare_total_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::compare_total_magnitude(Self, Self) -> Int
pub fn Decimal::compare_total_magnitude_ctx(Self, Self, DecimalContext) -> (Int, DecimalFlags)
pub fn Decimal::copy(Self) -> Self
pub fn Decimal::copy_abs(Self) -> Self
pub fn Decimal::copy_negate(Self) -> Self
pub fn Decimal::copy_sign(Self, Self) -> Self
pub fn Decimal::div(Self, Self) -> Self
pub fn Decimal::div_checked(Self, Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::div_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::div_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::divide_integer(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::epsilon_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::equal(Self, Self) -> Bool
pub fn Decimal::exp_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::exp_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::exponent10(Self) -> Int
pub fn Decimal::fma_ctx(Self, Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::from_bigint(@bigint.BigInt, precision? : Int) -> Self
pub fn Decimal::from_bin_float(@bin_float.BinFloat, precision? : Int) -> Self
pub fn Decimal::from_double(Double, precision? : Int) -> Self
pub fn Decimal::from_float(Float, precision? : Int) -> Self
pub fn Decimal::from_int(Int, precision? : Int) -> Self
pub fn[S : @luna-generic.Integral] Decimal::from_integral(S) -> Self
pub fn Decimal::from_interchange_hex(String, GdaInterchangeFormat) -> Self?
pub fn[S : @luna-generic.Nat] Decimal::from_nat(S) -> Self
pub fn Decimal::from_string(String, precision? : Int) -> Self?
pub fn Decimal::from_string_ctx(String, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::get_payload(Self) -> @bigint.BigInt
pub fn Decimal::inf(@def.Sign, precision? : Int) -> Self
pub fn Decimal::is_canonical(Self) -> Bool
pub fn Decimal::is_finite(Self) -> Bool
pub fn Decimal::is_infinite(Self) -> Bool
pub fn Decimal::is_nan(Self) -> Bool
pub fn Decimal::is_negative(Self) -> Bool
pub fn Decimal::is_negative_zero(Self) -> Bool
pub fn Decimal::is_normal(Self, DecimalContext) -> Bool
pub fn Decimal::is_qnan(Self) -> Bool
pub fn Decimal::is_quiet_nan(Self) -> Bool
pub fn Decimal::is_signaling_nan(Self) -> Bool
pub fn Decimal::is_signed(Self) -> Bool
pub fn Decimal::is_snan(Self) -> Bool
pub fn Decimal::is_subnormal(Self, DecimalContext) -> Bool
pub fn Decimal::is_zero(Self) -> Bool
pub fn Decimal::ln_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::log10_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logb_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_and(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_invert(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_or(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::logical_xor(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::magnitude(Self) -> @bigint.BigInt
pub fn Decimal::make(@bigint.BigInt, Int, Int, mode? : @arithmetic.RoundingMode) -> Self
pub fn Decimal::max(Self, Self) -> Self
pub fn Decimal::max_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::max_finite_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::max_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::maximum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min(Self, Self) -> Self
pub fn Decimal::min_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::min_normal_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::minimum_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_mag_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minimum_number_magnitude_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::minus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::mul(Self, Self) -> Self
pub fn Decimal::mul_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::mul_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::nan(precision? : Int) -> Self
pub fn Decimal::nan_payload(Self) -> @bigint.BigInt
pub fn Decimal::neg(Self) -> Self
pub fn Decimal::negative_zero(precision? : Int) -> Self
pub fn Decimal::next_minus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_plus(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::next_toward(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::normalize_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::normalized(Self) -> Self
pub fn Decimal::not_equal(Self, Self) -> Bool
pub fn Decimal::one(precision? : Int) -> Self
pub fn Decimal::one_contextual(@arithmetic.ArithmeticContext) -> Self
pub fn Decimal::op_ge(Self, Self) -> Bool
pub fn Decimal::op_gt(Self, Self) -> Bool
pub fn Decimal::op_le(Self, Self) -> Bool
pub fn Decimal::op_lt(Self, Self) -> Bool
pub fn Decimal::output(Self, &Logger) -> Unit
pub fn Decimal::parse(String, precision? : Int) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::parse_checked(String, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::plus_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::pow_int_checked(Self, Int, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::pow_nat_checked(Self, UInt, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::power_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::precision(Self) -> Int
pub fn Decimal::quantize(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::quantum(Self) -> Int
pub fn Decimal::quiet_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::reduce_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::remainder_near(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rescale(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::rotate_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::same_quantum(Self, Self) -> Bool
pub fn Decimal::scaleb_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::set_payload(Self, @bigint.BigInt) -> Self
pub fn Decimal::set_payload_signaling(Self, @bigint.BigInt) -> Self
pub fn Decimal::shift_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sign(Self) -> @def.Sign
pub fn Decimal::signaling_nan(payload? : @bigint.BigInt, negative? : Bool, precision? : Int) -> Self
pub fn Decimal::sqrt(Self) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_checked(Self, @arithmetic.ArithmeticContext) -> Result[Self, @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_contextual(Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sqrt_ctx(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::sub(Self, Self) -> Self
pub fn Decimal::sub_contextual(Self, Self, @arithmetic.ArithmeticContext) -> Result[@arithmetic.ArithmeticOutcome[Self], @arithmetic.ArithmeticError]
pub fn Decimal::sub_ctx(Self, Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_bin_float(Self, precision? : Int, mode? : @arithmetic.RoundingMode) -> @bin_float.BinFloat
pub fn Decimal::to_eng_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_integral_exact(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_integral_value(Self, DecimalContext) -> (Self, DecimalFlags)
pub fn Decimal::to_interchange_hex(Self, GdaInterchangeFormat) -> (String, DecimalFlags)
pub fn Decimal::to_repr(Self) -> @debug.Repr
pub fn Decimal::to_sci_string(String, DecimalContext) -> (String, DecimalFlags)
pub fn Decimal::to_string(Self) -> String
pub fn Decimal::trim(Self) -> Self
pub fn Decimal::try_exp_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_ln_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_log10_ctx(Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::try_power_ctx(Self, Self, DecimalContext) -> Result[(Self, DecimalFlags), @arithmetic.ArithmeticError]
pub fn Decimal::with_precision(Self, Int, @arithmetic.RoundingMode) -> Self
pub fn Decimal::zero(precision? : Int) -> Self
pub fn Decimal::zero_contextual(@arithmetic.ArithmeticContext) -> Self
pub impl @arithmetic.AbsContextual for Decimal
pub impl @arithmetic.AddContextual for Decimal
pub impl @arithmetic.CompareChecked for Decimal
pub impl @arithmetic.DivChecked for Decimal
pub impl @arithmetic.DivContextual for Decimal
pub impl @arithmetic.ExpContextual for Decimal
pub impl @arithmetic.MulContextual for Decimal
pub impl @arithmetic.NumericFormatContextual for Decimal
pub impl @arithmetic.ParseChecked for Decimal
pub impl @arithmetic.PowIntChecked for Decimal
pub impl @arithmetic.PowNatChecked for Decimal
pub impl @arithmetic.SqrtChecked for Decimal
pub impl @arithmetic.SqrtContextual for Decimal
pub impl @arithmetic.SubContextual for Decimal
pub impl @def.Floating for Decimal
pub impl @luna-generic.AddGroup for Decimal
pub impl @luna-generic.AddMonoid for Decimal
pub impl @luna-generic.IntegralHomomorphism for Decimal
pub impl @luna-generic.MulMonoid for Decimal
pub impl @luna-generic.NatHomomorphism for Decimal
pub impl @luna-generic.One for Decimal
pub impl @luna-generic.Ring for Decimal
pub impl @luna-generic.Semiring for Decimal
pub impl @luna-generic.Zero for Decimal
pub impl Add for Decimal
pub impl Compare for Decimal
pub impl Div for Decimal
pub impl Eq for Decimal
pub impl Mul for Decimal
pub impl Neg for Decimal
pub impl Show for Decimal
pub impl Sub for Decimal
pub struct DecimalContext {
// private fields
} derive(Eq)
pub fn DecimalContext::clamp(Self) -> Bool
pub fn DecimalContext::decimal128() -> Self
pub fn DecimalContext::decimal32() -> Self
pub fn DecimalContext::decimal64() -> Self
pub fn DecimalContext::decimal_rounding(Self) -> DecimalRoundingMode
pub fn DecimalContext::e_max(Self) -> Int
pub fn DecimalContext::e_min(Self) -> Int
pub fn DecimalContext::equal(Self, Self) -> Bool
pub fn DecimalContext::exact() -> Self
pub fn DecimalContext::extended(Self) -> Bool
pub fn DecimalContext::from_arithmetic_context(@arithmetic.ArithmeticContext) -> Self
pub fn DecimalContext::new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Self
pub fn DecimalContext::not_equal(Self, Self) -> Bool
pub fn DecimalContext::precision(Self) -> Int
pub fn DecimalContext::rounding(Self) -> @arithmetic.RoundingMode
pub fn DecimalContext::tininess(Self) -> DecimalTininessDetection
pub fn DecimalContext::try_new(precision? : Int, rounding? : @arithmetic.RoundingMode, decimal_rounding? : DecimalRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, tininess? : DecimalTininessDetection) -> Result[Self, @arithmetic.ArithmeticError]
pub fn DecimalContext::with_rounding(Self, @arithmetic.RoundingMode) -> Self
pub fn DecimalContext::with_tininess(Self, DecimalTininessDetection) -> Self
pub struct DecimalFlags {
inexact : Bool
rounded : Bool
lost_digits : Bool
invalid_operation : Bool
division_by_zero : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
clamped : Bool
conversion_syntax : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
} derive(Eq)
pub fn DecimalFlags::combine(Self, Self) -> Self
pub fn DecimalFlags::contains(Self, DecimalSignal) -> Bool
pub fn DecimalFlags::equal(Self, Self) -> Bool
pub fn DecimalFlags::has_error(Self) -> Bool
pub fn DecimalFlags::new() -> Self
pub fn DecimalFlags::not_equal(Self, Self) -> Bool
pub(all) enum DecimalRoundingMode {
HalfEven
HalfUp
HalfDown
Down
Ceiling
Floor
Up
ZeroFiveUp
} derive(Eq)
pub fn DecimalRoundingMode::equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::from_arithmetic(@arithmetic.RoundingMode) -> Self
pub fn DecimalRoundingMode::not_equal(Self, Self) -> Bool
pub fn DecimalRoundingMode::to_arithmetic(Self) -> @arithmetic.RoundingMode?
pub(all) enum DecimalSignal {
ConversionSyntax
DivisionByZero
DivisionImpossible
DivisionUndefined
InvalidContext
InvalidOperation
Overflow
Underflow
Subnormal
Inexact
Rounded
Clamped
LostDigits
} derive(Eq)
pub fn DecimalSignal::equal(Self, Self) -> Bool
pub fn DecimalSignal::not_equal(Self, Self) -> Bool
pub(all) enum DecimalTininessDetection {
BeforeRounding
AfterRounding
} derive(Eq)
pub fn DecimalTininessDetection::equal(Self, Self) -> Bool
pub fn DecimalTininessDetection::not_equal(Self, Self) -> Bool
pub struct GdaContext {
// private fields
}
pub fn GdaContext::basic() -> Self
pub fn GdaContext::clamp(Self) -> Bool
pub fn GdaContext::clear_status(Self) -> Self
pub fn GdaContext::decimal128() -> Self
pub fn GdaContext::decimal32() -> Self
pub fn GdaContext::decimal64() -> Self
pub fn GdaContext::default() -> Self
pub fn GdaContext::e_max(Self) -> Int
pub fn GdaContext::e_min(Self) -> Int
pub fn GdaContext::extended(Self) -> Bool
pub fn GdaContext::new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Self
pub fn GdaContext::precision(Self) -> Int
pub fn GdaContext::radix(Self) -> Int
pub fn GdaContext::reset(Self) -> Self
pub fn GdaContext::rounding(Self) -> GdaRoundingMode
pub fn GdaContext::status(Self) -> GdaFlags
pub fn GdaContext::trap(Self, GdaSignal, enabled? : Bool) -> Self
pub fn GdaContext::traps(Self) -> GdaTrapSet
pub fn GdaContext::try_new(precision? : Int, rounding? : GdaRoundingMode, e_min? : Int, e_max? : Int, clamp? : Bool, extended? : Bool, traps? : GdaTrapSet) -> Result[Self, @arithmetic.ArithmeticError]
pub fn GdaContext::with_traps(Self, GdaTrapSet) -> Self
pub struct GdaFlags {
conversion_syntax : Bool
division_by_zero : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
invalid_operation : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
inexact : Bool
rounded : Bool
clamped : Bool
lost_digits : Bool
} derive(Eq)
pub fn GdaFlags::combine(Self, Self) -> Self
pub fn GdaFlags::contains(Self, GdaSignal) -> Bool
pub fn GdaFlags::equal(Self, Self) -> Bool
pub fn GdaFlags::none() -> Self
pub fn GdaFlags::not_equal(Self, Self) -> Bool
pub struct GdaInterchange {
// private fields
}
pub fn GdaInterchange::canonical(Self) -> Self
pub fn GdaInterchange::copy(Self) -> Self
pub fn GdaInterchange::copy_abs(Self) -> Self
pub fn GdaInterchange::copy_negate(Self) -> Self
pub fn GdaInterchange::copy_sign(Self, Self) -> Self
pub fn GdaInterchange::format(Self) -> GdaInterchangeFormat
pub fn GdaInterchange::from_decimal(Decimal, GdaInterchangeFormat) -> (Self, DecimalFlags)
pub fn GdaInterchange::from_hex(String, GdaInterchangeFormat) -> Self?
pub fn GdaInterchange::is_canonical(Self) -> Bool
pub fn GdaInterchange::to_decimal(Self) -> Decimal
pub fn GdaInterchange::to_decimal_ctx(Self) -> (Decimal, DecimalFlags)
pub fn GdaInterchange::to_hex(Self) -> String
pub(all) enum GdaInterchangeFormat {
Decimal32
Decimal64
Decimal128
} derive(Eq)
pub fn GdaInterchangeFormat::context(Self) -> DecimalContext
pub fn GdaInterchangeFormat::equal(Self, Self) -> Bool
pub fn GdaInterchangeFormat::not_equal(Self, Self) -> Bool
pub(all) enum GdaOutcome[T] {
Completed(T, GdaContext, GdaFlags)
Trapped(GdaSignal, T, GdaContext, GdaFlags)
}
pub fn[T] GdaOutcome::next_context(Self[T]) -> GdaContext
pub fn[T] GdaOutcome::raised(Self[T]) -> GdaFlags
pub fn[T] GdaOutcome::value(Self[T]) -> T
pub(all) enum GdaRoundingMode {
HalfEven
HalfUp
HalfDown
Down
Ceiling
Floor
Up
ZeroFiveUp
} derive(Eq)
pub fn GdaRoundingMode::equal(Self, Self) -> Bool
pub fn GdaRoundingMode::not_equal(Self, Self) -> Bool
pub(all) enum GdaSignal {
ConversionSyntax
DivisionByZero
DivisionImpossible
DivisionUndefined
InvalidContext
InvalidOperation
Overflow
Underflow
Subnormal
Inexact
Rounded
Clamped
LostDigits
} derive(Eq)
pub fn GdaSignal::equal(Self, Self) -> Bool
pub fn GdaSignal::not_equal(Self, Self) -> Bool
pub struct GdaTrapSet {
conversion_syntax : Bool
division_by_zero : Bool
division_impossible : Bool
division_undefined : Bool
invalid_context : Bool
invalid_operation : Bool
overflow : Bool
underflow : Bool
subnormal : Bool
inexact : Bool
rounded : Bool
clamped : Bool
lost_digits : Bool
} derive(Eq)
pub fn GdaTrapSet::contains(Self, GdaSignal) -> Bool
pub fn GdaTrapSet::equal(Self, Self) -> Bool
pub fn GdaTrapSet::none() -> Self
pub fn GdaTrapSet::not_equal(Self, Self) -> Bool
pub fn GdaTrapSet::with_signal(Self, GdaSignal, enabled? : Bool) -> Self
// Type aliases
// Traits
Footnotes
-
The GDA reference implementation returns such operands unchanged; for example, at precision 3 it maps
12345to12345, while this package returns1.23E+4withInexact. The pinned test suite has no such row. ↩