/*---------------------------------------------------------------------------
  Copyright 2012-2021, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

// Arbitrary precision decimal numbers.
//
// Decimals have arbitrary precision and range and
// do exact decimal arithmetic and are well suited for
// financial calculations for example.
module std/num/decimalstd/num/decimal

import std/text/parsestd/text/parse
import std/num/float64std/num/float64

// Type of a decimal number. Decimals have arbitrary precision and range and
// do exact decimal arithmetic and are well suited for financial calculations for
// example.
abstract value struct decimalstd/num/decimal/decimal: V
  numstd/num/decimal/decimal/num: (decimal : decimal) -> int : intstd/core/types/int: V
  expstd/num/decimal/decimal/exp: (decimal : decimal) -> int : intstd/core/types/int: V


// The decimal zero.
pub val zerostd/num/decimal/zero: decimal : decimalstd/num/decimal/decimal: V = Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
,0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
) // round exponents to specific intervals (7) to avoid too much rescaling fun round-expstd/num/decimal/round-exp: (exp : int) -> int( expexp: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V if expexp: int.is-zerostd/core/int/is-zero: (x : int) -> bool then 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
else 7literal: int
dec = 7
hex8 = 0x07
bit8 = 0b00000111
*std/core/int/(*): (int, int) -> int(expexp: int /std/core/int/(/): (x : int, y : int) -> int 7literal: int
dec = 7
hex8 = 0x07
bit8 = 0b00000111
) // Create a decimal from an integer `i` with an optional // exponent `exp` (=`0`) such that the result equals `i`×10^`exp`^. pub fun int/decimalstd/num/decimal/int/decimal: (i : int, exp : ? int) -> decimal( ii: int : intstd/core/types/int: V, expexp: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)result: -> total decimal : decimalstd/num/decimal/decimal: V decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal(ii: int,expexp: int
) // Create a decimal from an integer `i` with an optional // exponent `exp` (=`0`) such that the result equals `i`×10^`exp`^. fun decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal( ii: int : intstd/core/types/int: V, expexp: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)result: -> total decimal : decimalstd/num/decimal/decimal: V // use exponents only at specific intervals to avoid too much re-scaling val xx: int = round-expstd/num/decimal/round-exp: (exp : int) -> int(expexp: int) // always x <= exp val diffdiff: int = expexp: int -std/core/int/(-): (x : int, y : int) -> int xx: int // trace("decimal-exp: " + i.show + "e" + exp.show + ", diff: " + diff.show + ", x: " + x.show) if diffdiff: int.is-zerostd/core/int/is-zero: (x : int) -> bool then Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(ii: int,expexp: int) else Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(ii: int.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(diffdiff: int.absstd/core/int/abs: (i : int) -> int),xx: int
) /* Create a decimal from a `:float64` with a specified maximal precision (=`-1`). Use a negative maximal precision to create a decimal that precisely represents the `:float64`. Note: creating a `:decimal` from a `:float64` may lose precision and give surprising results as many decimal fractions cannot be represented precisely by a `:float64`. Also, `decimal(i,exp)` is more efficient and better when when exact representations are required. For example: ``` > decimal(1.1) 1.100000000000000088817841970012523233890533447265625 > decimal(1.1,17) 1.10000000000000008 > decimal(11,-1) 1.1 ``` . */ pub fun float64/decimalstd/num/decimal/float64/decimal: (d : float64, max-prec : ? int) -> decimal( dd: float64 : float64std/core/types/float64: V, max-precmax-prec: ? int : intstd/core/types/int: V = -1literal: int
dec = -1
hex8 = 0xFF
bit8 = 0b11111111
)result: -> total decimal : decimalstd/num/decimal/decimal: V val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)manman: int,expexp: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = dd: float64.decodestd/num/float64/decode: (d : float64) -> (int, int) if expexp: int >=std/core/int/(>=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then (manman: int *std/core/int/(*): (int, int) -> int (2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
^std/core/int/(^): (i : int, exp : int) -> intexpexp: int)).decimalstd/num/decimal/int/decimal: (i : int, exp : ? int) -> decimal else val precprec: int = if max-precmax-prec: int <std/core/int/(<): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then ~std/core/int/(~): (i : int) -> intexpexp: int else minstd/core/int/min: (i : int, j : int) -> int(max-precmax-prec: int,~std/core/int/(~): (i : int) -> intexpexp: int) divstd/num/decimal/div: (x : decimal, y : decimal, min-prec : ? int) -> decimal( manman: int.decimalstd/num/decimal/int/decimal: (i : int, exp : ? int) -> decimal, powstd/num/decimal/pow: (x : decimal, n : int) -> decimal(2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
.decimalstd/num/decimal/int/decimal: (i : int, exp : ? int) -> decimal, ~std/core/int/(~): (i : int) -> intexpexp: int), precprec: int
) /* // Parse a `:decimal` number. pub fun parse-decimalx( s : string ) : maybe<decimal> match s.trim.find(rx-decimal) Nothing -> Nothing Just(cap) -> val sign = cap.groups[1] val whole = cap.groups[2] val frac = cap.groups[3] val exp = ~frac.count + cap.groups[4].parse-int.default(0) val f = decimal-exp( (whole + frac).parse-int.default(0), exp ) if sign=="-" then Just(~f) else Just(f) val rx-decimal = regex(r"^([\-\+]?)(\d+)(?:\.(\d*))?(?:[eE]([\-\+]?\d+))?$") */ // Parse a `:decimal` number. pub fun parse-decimalstd/num/decimal/parse-decimal: (s : string) -> maybe<decimal>( ss: string : stringstd/core/types/string: V )result: -> total maybe<decimal> : maybestd/core/types/maybe: V -> V<decimalstd/num/decimal/decimal: V> ss: string.trimstd/core/string/trim: (s : string) -> string.slicestd/core/sslice/slice: (s : string) -> sslice.parse-eofstd/text/parse/parse-eof: (input : sslice, p : () -> parse decimal) -> parse-error<decimal>(pdecimalstd/num/decimal/pdecimal: () -> parse decimal).maybestd/text/parse/maybe: (perr : parse-error<decimal>) -> maybe<decimal> fun pdecimalstd/num/decimal/pdecimal: () -> parse decimal()result: -> parse decimal : parsestd/text/parse/parse: (E, V) -> V decimalstd/num/decimal/decimal: V val negneg: bool = signstd/text/parse/sign: () -> parse bool() val wholewhole: string = digitsstd/text/parse/digits: () -> parse string() val fracfrac: string = optionalstd/text/parse/optional: (default : string, p : parser<total,string>) -> parse string(""literal: string
count= 0
, { charstd/text/parse/char: (c : char) -> parse char('.'literal: char
unicode= u002E
); digitsstd/text/parse/digits: () -> parse string() }) val expexp: int = optionalstd/text/parse/optional: (default : int, p : parser<total,int>) -> parse int(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, { one-ofstd/text/parse/one-of: (chars : string) -> parse char("eE"literal: string
count= 2
); pintstd/text/parse/pint: () -> parse int() }) // trace("frac:" + frac) val ii: decimal = decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> parse decimal( (wholewhole: string ++std/core/types/(++): (x : string, y : string) -> parse string fracfrac: string).parse-intstd/core/int/parse-int: (s : string, hex : ? bool) -> parse maybe<int>.defaultstd/core/maybe/default: (m : maybe<int>, nothing : int) -> parse int(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
), expexp: int -std/core/int/(-): (x : int, y : int) -> parse int fracfrac: string.countstd/core/string/count: (s : string) -> parse int ) if negneg: bool then ~std/num/decimal/(~): (x : decimal) -> parse decimalii: decimal else
ii: decimal // Ensure a decimal `x` has an exponent such that `x.exp <= e`. fun expandstd/num/decimal/expand: (x : decimal, e : int) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, ee: int : intstd/core/types/int: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int <=std/core/int/(<=): (x : int, y : int) -> bool ee: int then xx: decimal else //trace("expand: " ++ x.show ++ " to exp " ++ p.show) decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal( xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int( xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int -std/core/int/(-): (x : int, y : int) -> int ee: int ), ee: int ) // Choose an exponent that minimizes memory usage. pub fun reducestd/num/decimal/reduce: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V val pp: int = xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-exp10std/core/int/is-exp10: (i : int) -> int if !std/core/types/bool/(!): (b : bool) -> boolpp: int.is-posstd/core/int/is-pos: (i : int) -> bool returnreturn: decimal xx: decimal val exppexpp: int= xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int +std/core/int/(+): (x : int, y : int) -> int pp: int // trace("reduce: x:" ++ x.showx ++ ", p:" ++ p.show ++ ", expp:" ++ expp.show) if round-expstd/num/decimal/round-exp: (exp : int) -> int(exppexpp: int)==std/core/int/(==): (x : int, y : int) -> boolxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int then xx: decimal else decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal(xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.cdiv-exp10std/core/int/cdiv-exp10: (i : int, n : int) -> int(pp: int), exppexpp: int) // Add two decimals. pub fun (+)std/num/decimal/(+): (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V val ee: int = minstd/core/int/min: (i : int, j : int) -> int(xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int,yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) // trace("add: " ++ x.show-raw ++ " + " ++ y.show-raw ++ ", using exp: " ++ e.show ) val xxxx: decimal = xx: decimal.expandstd/num/decimal/expand: (x : decimal, e : int) -> decimal(ee: int) val yyyy: decimal = yy: decimal.expandstd/num/decimal/expand: (x : decimal, e : int) -> decimal(ee: int) // trace("expanded add: " ++ xx.show-raw ++ " + " ++ yy.show-raw) Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(xxxx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int +std/core/int/(+): (x : int, y : int) -> int yyyy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int, ee: int) // Negate a decimal. pub fun (~)std/num/decimal/(~): (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(~std/core/int/(~): (i : int) -> intxx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int, xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) // Subtract two decimals. pub fun (-)std/num/decimal/(-): (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V xx: decimal +std/num/decimal/(+): (x : decimal, y : decimal) -> decimal (~std/num/decimal/(~): (x : decimal) -> decimalyy: decimal) // Increment a decimal pub fun incstd/num/decimal/inc: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.incstd/core/int/inc: (i : int) -> int, xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) // Decrement a decimal pub fun decstd/num/decimal/dec: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.decstd/core/int/dec: (i : int) -> int, xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) // Is this an even decimal? pub fun is-evenstd/num/decimal/is-even: (x : decimal) -> bool(xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total bool : boolstd/core/types/bool: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-evenstd/core/int/is-even: (i : int) -> bool // Is this an odd decimal? pub fun is-oddstd/num/decimal/is-odd: (x : decimal) -> bool( xx: decimal :decimalstd/num/decimal/decimal: V )result: -> total bool : boolstd/core/types/bool: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-oddstd/core/int/is-odd: (i : int) -> bool // Is this decimal zero? pub fun is-zerostd/num/decimal/is-zero: (x : decimal) -> bool( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total bool : boolstd/core/types/bool: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-zerostd/core/int/is-zero: (x : int) -> bool // Is the decimal positive? pub fun is-posstd/num/decimal/is-pos: (x : decimal) -> bool( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total bool : boolstd/core/types/bool: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-posstd/core/int/is-pos: (i : int) -> bool // Is the decimal negative? pub fun is-negstd/num/decimal/is-neg: (x : decimal) -> bool( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total bool : boolstd/core/types/bool: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.is-negstd/core/int/is-neg: (i : int) -> bool // Multiply two decimals with full precision. pub fun (*)std/num/decimal/(*): (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V val zz: decimal = decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal(xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int *std/core/int/(*): (int, int) -> int yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int, xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int +std/core/int/(+): (x : int, y : int) -> int yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) if zz: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.is-negstd/core/int/is-neg: (i : int) -> bool then zz: decimal.reducestd/num/decimal/reduce: (x : decimal) -> decimal else zz: decimal // Decimal to the power of `n` pub fun powstd/num/decimal/pow: (x : decimal, n : int) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, nn: int : intstd/core/types/int: V )result: -> total decimal : decimalstd/num/decimal/decimal: V val mm: int = nn: int.absstd/core/int/abs: (i : int) -> int val yy: decimal = decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal(xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int ^std/core/int/(^): (i : int, exp : int) -> int mm: int, xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int *std/core/int/(*): (int, int) -> int mm: int ) if nn: int.is-negstd/core/int/is-neg: (i : int) -> bool then divstd/num/decimal/div: (x : decimal, y : decimal, min-prec : ? int) -> decimal( 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
.decimalstd/num/decimal/int/decimal: (i : int, exp : ? int) -> decimal, yy: decimal, 3literal: int
dec = 3
hex8 = 0x03
bit8 = 0b00000011
+std/core/int/(+): (x : int, y : int) -> int mm: int) else
yy: decimal // Rounding modes. pub type roundstd/num/decimal/round: V // Round to neareast integer, round to the even number in case of a tie con Half-evenstd/num/decimal/Half-even: round // Round to nearest integer, round towards infinity in case of a tie con Half-ceilingstd/num/decimal/Half-ceiling: round // Round to nearest integer, round towards negative infinity in case of a tie con Half-floorstd/num/decimal/Half-floor: round // Round to nearest integer, round towards zero in case of a tie con Half-truncatestd/num/decimal/Half-truncate: round // Round to nearest integer, round away from zero in case of a tie con Half-away-from-zerostd/num/decimal/Half-away-from-zero: round // Round to the minimum integer that is larger or equal con Ceilingstd/num/decimal/Ceiling: round // Round to the maximum integer that is lower or equal con Floorstd/num/decimal/Floor: round // Round to the nearest integer towards zero (i.e. _truncate_) con Truncatestd/num/decimal/Truncate: round // Round to the nearest integer away from zero, i.e. toward negative infinity for negative numbers, and positive infinity for positive numbers. con Away-from-zerostd/num/decimal/Away-from-zero: round // Round a `:decimal` number to an integer an optional rounding mode `rnd` (=`Half-even`). pub fun intstd/num/decimal/int: (x : decimal, rnd : ? round) -> int( xx: decimal : decimalstd/num/decimal/decimal: V, rndrnd: ? round : roundstd/num/decimal/round: V = Half-evenstd/num/decimal/Half-even: round)result: -> total int : intstd/core/types/int: V val yy: decimal = xx: decimal.roundstd/num/decimal/round: (x : decimal, rnd : ? round) -> decimal(rndrnd: round) // y.exp >= 0 if yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.is-posstd/core/int/is-pos: (i : int) -> bool then yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) else yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int // Round a `:decimal` number to a whole number with an optional rounding mode (=`Half-even`). pub fun roundstd/num/decimal/round: (x : decimal, rnd : ? round) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, rndrnd: ? round : roundstd/num/decimal/round: V = Half-evenstd/num/decimal/Half-even: round )result: -> total decimal : decimalstd/num/decimal/decimal: V xx: decimal.round-to-precstd/num/decimal/round-to-prec: (x : decimal, prec : ? int, rnd : ? round) -> decimal(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
,rndrnd: round
) // Round the decimal-point number `x` to // to a specified number of digits behind the dot `prec` (=`0`) with an optional // rounding mode `rnd` (=`Half-even`). The precision can be negative.\ // `decimal(1,485).round-to-prec(2).show == "1.48"` \ // `decimal(112,49).round-to-prec(-1).show == "110"` pub fun round-to-precstd/num/decimal/round-to-prec: (x : decimal, prec : ? int, rnd : ? round) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, precprec: ? int : intstd/core/types/int: V = 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
, rndrnd: ? round : roundstd/num/decimal/round: V = Half-evenstd/num/decimal/Half-even: round )result: -> total decimal : totalstd/core/types/total: E decimalstd/num/decimal/decimal: V if xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int >=std/core/int/(>=): (x : int, y : int) -> bool ~std/core/int/(~): (i : int) -> intprecprec: int returnreturn: decimal xx: decimal val cxcx: decimal = xx: decimal.reducestd/num/decimal/reduce: (x : decimal) -> decimal val pp: int = ~std/core/int/(~): (i : int) -> intcxcx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int -std/core/int/(-): (x : int, y : int) -> int precprec: int if !std/core/types/bool/(!): (b : bool) -> boolpp: int.is-posstd/core/int/is-pos: (i : int) -> bool returnreturn: decimal cxcx: decimal // already less than prec precision val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)qq: int,rr: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = cxcx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.divmod-exp10std/core/int/divmod-exp10: (i : int, n : int) -> (int, int)(pp: int) fun round-halfround-half: (keep-on-eq : bool) -> int( keep-on-eqkeep-on-eq: bool : boolstd/core/types/bool: V )result: -> total int val halfhalf: int = pp: int.exp10std/core/int/exp10: (exp : int) -> int /std/core/int/(/): (x : int, y : int) -> int 2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
match cmpstd/core/int/cmp: (x : int, y : int) -> order(rr: int,halfhalf: int) Eqstd/core/types/Eq: order -> if keep-on-eqkeep-on-eq: bool then qq: int else qq: int.incstd/core/int/inc: (i : int) -> int Gtstd/core/types/Gt: order -> qq: int.incstd/core/int/inc: (i : int) -> int Ltstd/core/types/Lt: order ->
qq: int val q1q1: int = if rr: int.is-zerostd/core/int/is-zero: (x : int) -> bool then qq: int else match rndrnd: round Half-evenstd/num/decimal/Half-even: round -> round-halfround-half: (keep-on-eq : bool) -> int(qq: int.is-evenstd/core/int/is-even: (i : int) -> bool) Half-floorstd/num/decimal/Half-floor: round -> round-halfround-half: (keep-on-eq : bool) -> int(Truestd/core/types/True: bool) Half-ceilingstd/num/decimal/Half-ceiling: round -> round-halfround-half: (keep-on-eq : bool) -> int(Falsestd/core/types/False: bool) Half-truncatestd/num/decimal/Half-truncate: round -> round-halfround-half: (keep-on-eq : bool) -> int(qq: int.is-posstd/core/int/is-pos: (i : int) -> bool) Half-away-from-zerostd/num/decimal/Half-away-from-zero: round -> round-halfround-half: (keep-on-eq : bool) -> int(qq: int.is-negstd/core/int/is-neg: (i : int) -> bool) Floorstd/num/decimal/Floor: round -> qq: int Ceilingstd/num/decimal/Ceiling: round -> qq: int.incstd/core/int/inc: (i : int) -> int Truncatestd/num/decimal/Truncate: round -> if !std/core/types/bool/(!): (b : bool) -> boolqq: int.is-negstd/core/int/is-neg: (i : int) -> bool then qq: int else qq: int.incstd/core/int/inc: (i : int) -> int Away-from-zerostd/num/decimal/Away-from-zero: round -> if !std/core/types/bool/(!): (b : bool) -> boolqq: int.is-posstd/core/int/is-pos: (i : int) -> bool then qq: int else qq: int.incstd/core/int/inc: (i : int) -> int //trace("round: " + x.showx + ", q: " + q.show + ", r: " + r.show + ", q1: " + q1.show + "e-" + prec.show ) decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal(q1q1: int,~std/core/int/(~): (i : int) -> intprecprec: int
) // Optimize: Use float64 division when within precision bounds. val maxexpstd/num/decimal/maxexp: int : intstd/core/types/int: V = 308literal: int
dec = 308
hex16= 0x0134
bit16= 0b0000000100110100
val maxpdstd/num/decimal/maxpd: float64 : float64std/core/types/float64: V = 1.0e15literal: float64
hex64= 0x1.c6bf52634p49
val maxprecisestd/num/decimal/maxprecise: int : intstd/core/types/int: V = intstd/num/float64/int: (f : float64) -> int(maxpdstd/num/decimal/maxpd: float64) val minprecisestd/num/decimal/minprecise: int : intstd/core/types/int: V = ~std/core/int/(~): (i : int) -> intmaxprecisestd/num/decimal/maxprecise: int fun is-precisestd/num/decimal/is-precise: (i : int) -> bool(ii: int : intstd/core/types/int: V )result: -> total bool : boolstd/core/types/bool: V (ii: int >std/core/int/(>): (x : int, y : int) -> bool minprecisestd/num/decimal/minprecise: int &&std/core/types/(&&): (x : bool, y : bool) -> bool ii: int <std/core/int/(<): (x : int, y : int) -> bool maxprecisestd/num/decimal/maxprecise: int) /* Divide two decimals with a given extra precision `min-prec` (=`15`). The `min-prec` is the number of extra digits used to calculate inexact divisions. Note: the division uses up to `min-prec` precision using `Floor` rounding for the last digit if the result is inexact. To round differently, you can for example divide with larger precision and use `round-to-prec`. ``` > div( decimal(2), decimal(3), 0 ) 0 > div( decimal(2), decimal(3), 1 ) 0.6 > div( decimal(2), decimal(3) ) // default precision is 15 0.6666666666666666 > div( decimal(2), decimal(3) ).round-to-prec(6) 0.666667 ``` . */ pub fun divstd/num/decimal/div: (x : decimal, y : decimal, min-prec : ? int) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V, min-precmin-prec: ? int : intstd/core/types/int: V = 15literal: int
dec = 15
hex8 = 0x0F
bit8 = 0b00001111
)result: -> total decimal : decimalstd/num/decimal/decimal: V if xx: decimal.is-zerostd/num/decimal/is-zero: (x : decimal) -> bool ||std/core/types/(||): (x : bool, y : bool) -> bool yy: decimal.is-zerostd/num/decimal/is-zero: (x : decimal) -> bool then returnreturn: decimal Decimalstd/num/decimal/Decimal: (num : int, exp : int) -> decimal(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
,0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)std/core/types/Unit: () val ee: int = xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int -std/core/int/(-): (x : int, y : int) -> int yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int /* // use float64 division if within precision bounds.. if min-prec <= 15 && e.abs <= 15 && x.num.is-precise && y.num.is-precise val r = x.num.float64 / y.num.float64 if e.is-zero then decimal(r) else decimal(r * exp10(e.float64)) else */ // otherwise use long integer division val xdigitsxdigits: int = xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.count-digitsstd/core/int/count-digits: (i : int) -> int val ydigitsydigits: int = yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.count-digitsstd/core/int/count-digits: (i : int) -> int val extraextra: int = maxstd/core/int/max: (i : int, j : int) -> int(0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
,ydigitsydigits: int -std/core/int/(-): (x : int, y : int) -> int xdigitsxdigits: int) +std/core/int/(+): (x : int, y : int) -> int min-precmin-prec: int if extraextra: int >std/core/int/(>): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal( xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(extraextra: int) /std/core/int/(/): (x : int, y : int) -> int yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int, ee: int -std/core/int/(-): (x : int, y : int) -> int extraextra: int ).reducestd/num/decimal/reduce: (x : decimal) -> decimal else decimal-expstd/num/decimal/decimal-exp: (i : int, exp : ? int) -> decimal( xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int /std/core/int/(/): (x : int, y : int) -> int yy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int, ee: int -std/core/int/(-): (x : int, y : int) -> int extraextra: int ).reducestd/num/decimal/reduce: (x : decimal) -> decimal
// Divide two decimals using 15 digits of extra precision. pub fun (/)std/num/decimal/(/): (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V divstd/num/decimal/div: (x : decimal, y : decimal, min-prec : ? int) -> decimal(xx: decimal,yy: decimal) // Compare decimals. pub fun cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total order : orderstd/core/types/order: V // todo: optimize further to avoid allocations. val ee: int = minstd/core/int/min: (i : int, j : int) -> int(xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int,yy: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) val xxxx: decimal = xx: decimal.expandstd/num/decimal/expand: (x : decimal, e : int) -> decimal(ee: int) val yyyy: decimal = yy: decimal.expandstd/num/decimal/expand: (x : decimal, e : int) -> decimal(ee: int) cmpstd/core/int/cmp: (x : int, y : int) -> order(xxxx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int,yyyy: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int) pub fun (>)std/num/decimal/(>): (x : decimal, y : decimal) -> bool (xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) ==std/core/order/(==): (x : order, y : order) -> bool Gtstd/core/types/Gt: order } pub fun (>=)std/num/decimal/(>=): (x : decimal, y : decimal) -> bool(xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) !=std/core/order/(!=): (x : order, y : order) -> bool Ltstd/core/types/Lt: order } pub fun (==)std/num/decimal/(==): (x : decimal, y : decimal) -> bool(xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) ==std/core/order/(==): (x : order, y : order) -> bool Eqstd/core/types/Eq: order } pub fun (!=)std/num/decimal/(!=): (x : decimal, y : decimal) -> bool(xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) !=std/core/order/(!=): (x : order, y : order) -> bool Eqstd/core/types/Eq: order } pub fun (<)std/num/decimal/(<): (x : decimal, y : decimal) -> bool (xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) ==std/core/order/(==): (x : order, y : order) -> bool Ltstd/core/types/Lt: order } pub fun (<=)std/num/decimal/(<=): (x : decimal, y : decimal) -> bool(xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V)result: -> total bool : boolstd/core/types/bool: V { cmpstd/num/decimal/cmp: (x : decimal, y : decimal) -> order(xx: decimal,yy: decimal) !=std/core/order/(!=): (x : order, y : order) -> bool Gtstd/core/types/Gt: order } // The sign of a decimal number. pub fun signstd/num/decimal/sign: (x : decimal) -> order( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total order : orderstd/core/types/order: V xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.signstd/core/int/sign: (i : int) -> order // The minimum of `x` and `y`. pub fun minstd/num/decimal/min: (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if xx: decimal <=std/num/decimal/(<=): (x : decimal, y : decimal) -> bool yy: decimal then xx: decimal else yy: decimal // The maximum of `x` and `y` pub fun maxstd/num/decimal/max: (x : decimal, y : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V, yy: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if xx: decimal >=std/num/decimal/(>=): (x : decimal, y : decimal) -> bool yy: decimal then xx: decimal else yy: decimal // Take the sum of a list of decimal numbers (0 for the empty list). pub fun sumstd/num/decimal/sum: (ds : list<decimal>) -> decimal( dsds: list<decimal> : liststd/core/types/list: V -> V<decimalstd/num/decimal/decimal: V> )result: -> total decimal : decimalstd/num/decimal/decimal: V dsds: list<decimal>.foldrstd/core/list/foldr: (xs : list<decimal>, z : decimal, f : (decimal, decimal) -> decimal) -> decimal(zerostd/num/decimal/zero: decimal,(+)std/num/decimal/(+): (x : decimal, y : decimal) -> decimal) // The absolute value of a decimal pub fun absstd/num/decimal/abs: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if xx: decimal.is-negstd/num/decimal/is-neg: (x : decimal) -> bool then ~std/num/decimal/(~): (x : decimal) -> decimalxx: decimal else xx: decimal // Round a `:decimal` using to the largest integer that is not larger than `x`. pub fun floorstd/num/decimal/floor: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V xx: decimal.roundstd/num/decimal/round: (x : decimal, rnd : ? round) -> decimal(Floorstd/num/decimal/Floor: round) // Round a `:decimal` to the smallest integer that is not less than `x`. pub fun ceilingstd/num/decimal/ceiling: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V xx: decimal.roundstd/num/decimal/round: (x : decimal, rnd : ? round) -> decimal(Ceilingstd/num/decimal/Ceiling: round) // Truncate a `:decimal` to an integer by rounding towards zero. pub fun truncatestd/num/decimal/truncate: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V xx: decimal.roundstd/num/decimal/round: (x : decimal, rnd : ? round) -> decimal(Truncatestd/num/decimal/Truncate: round) // Convert a decimal to a `:float64`. This may lose precision. pub fun float64std/num/decimal/float64: (x : decimal) -> float64( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total float64 : float64std/core/types/float64: V // todo: handle decimals with many digits better if !std/core/types/bool/(!): (b : bool) -> boolxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.is-negstd/core/int/is-neg: (i : int) -> bool then xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.float64std/num/float64/float64: (i : int) -> float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 powstd/num/float64/pow: (d : float64, p : float64) -> float64(10.0literal: float64
hex64= 0x1.4p3
,xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.float64std/num/float64/float64: (i : int) -> float64) else val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)qq: int,rr: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.divmod-exp10std/core/int/divmod-exp10: (i : int, n : int) -> (int, int)(~std/core/int/(~): (i : int) -> intxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) qq: int.float64std/num/float64/float64: (i : int) -> float64 +std/num/float64/(+): (x : float64, y : float64) -> float64 rr: int.float64std/num/float64/float64: (i : int) -> float64 *std/num/float64/(*): (x : float64, y : float64) -> float64 exp10std/num/float64/exp10: (p : float64) -> float64(xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.float64std/num/float64/float64: (i : int) -> float64
) // Return the 'truncated' fraction, always in the range (`-1.0`,`1.0`). // `x.truncate + x.fraction == x` pub fun fractionstd/num/decimal/fraction: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if !std/core/types/bool/(!): (b : bool) -> boolxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.is-negstd/core/int/is-neg: (i : int) -> bool then zerostd/num/decimal/zero: decimal else (xx: decimal -std/num/decimal/(-): (x : decimal, y : decimal) -> decimal xx: decimal.truncatestd/num/decimal/truncate: (x : decimal) -> decimal) // Return the 'floored' fraction, always in the range [`0`,`1.0`). // `x.floor + x.ffraction == x` pub fun ffractionstd/num/decimal/ffraction: (x : decimal) -> decimal( xx: decimal : decimalstd/num/decimal/decimal: V )result: -> total decimal : decimalstd/num/decimal/decimal: V if !std/core/types/bool/(!): (b : bool) -> boolxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.is-negstd/core/int/is-neg: (i : int) -> bool then zerostd/num/decimal/zero: decimal else (xx: decimal -std/num/decimal/(-): (x : decimal, y : decimal) -> decimal xx: decimal.floorstd/num/decimal/floor: (x : decimal) -> decimal) /* -------------------------------------------------------------------------------------- Show -------------------------------------------------------------------------------------- */ // Show a decimal `d` using its internal representation. pub fun show-rawstd/num/decimal/show-raw: (d : decimal) -> string(dd: decimal : decimalstd/num/decimal/decimal: V)result: -> total string dd: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.showstd/core/int/show: (i : int) -> string ++std/core/types/(++): (x : string, y : string) -> string "e"literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string dd: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int.showstd/core/int/show: (i : int) -> string
// Show a decimal `d` with a given precision `prec` (=`-1000`). // The precision specifies the number of digits after the dot (in either scientific of fixed-point notation). // If the precision is negative, _at most_ `prec` digits are displayed, while for a positive // precision, exactly `prec` digits behind the dot are displayed. // This uses `show-fixed` when the exponent of `d` in scientific notation is larger than -5 // and smaller than the precision (or 15 in case of a negative precision), otherwise it uses `show-exp`. pub fun showstd/num/decimal/show: (d : decimal, prec : ? int) -> string( dd: decimal : decimalstd/num/decimal/decimal: V, precprec: ? int : intstd/core/types/int: V = -1000literal: int
dec = -1000
hex16= 0xFC18
bit16= 0b1111110000011000
)result: -> total string : stringstd/core/types/string: V val expexp: int = dd: decimal.exponentstd/num/decimal/exponent: (d : decimal) -> int if expexp: int >std/core/int/(>): (x : int, y : int) -> bool -5literal: int
dec = -5
hex8 = 0xFB
bit8 = 0b11111011
&&std/core/types/(&&): (x : bool, y : bool) -> bool expexp: int <std/core/int/(<): (x : int, y : int) -> bool (if precprec: int.is-negstd/core/int/is-neg: (i : int) -> bool then 15literal: int
dec = 15
hex8 = 0x0F
bit8 = 0b00001111
else precprec: int) then show-fixedstd/num/decimal/show-fixed: (d : decimal, prec : ? int) -> string( dd: decimal, precprec: int ) else show-expstd/num/decimal/show-exp: (d : decimal, prec : ? int) -> string( dd: decimal, precprec: int
) // The exponent of a decimal if displayed in scientific notation.\ // `11.2e-1.decimal.exponent == 0` pub fun exponentstd/num/decimal/exponent: (d : decimal) -> int( dd: decimal : decimalstd/num/decimal/decimal: V )result: -> total int : intstd/core/types/int: V dd: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.count-digitsstd/core/int/count-digits: (i : int) -> int +std/core/int/(+): (x : int, y : int) -> int dd: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int -std/core/int/(-): (x : int, y : int) -> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
/* Show a decimal `d` with a given precision `prec` (=`-1000`) in fixed-point notation. The precision specifies the number of digits after the dot. If the precision is negative, _at most_ `prec` digits after the dot are displayed, while for a positive precision, exactly `prec` digits are used. ``` > decimal(1,-1).show-fixed "0.1" > 0.1.decimal.show-fixed "0.1000000000000000055511151231257827021181583404541015625" > 0.1.decimal.show-fixed(20) "0.1000000000000000555" > 0.1.decimal.show-fixed(-20) "0.1000000000000000555" > decimal(1,-1).show-fixed(20) "0.1000000000000000000" ``` . */ pub fun show-fixedstd/num/decimal/show-fixed: (d : decimal, prec : ? int) -> string( dd: decimal : decimalstd/num/decimal/decimal: V, precprec: ? int : intstd/core/types/int: V = -1000literal: int
dec = -1000
hex16= 0xFC18
bit16= 0b1111110000011000
)result: -> total string : stringstd/core/types/string: V val xx: decimal = dd: decimal.round-to-precstd/num/decimal/round-to-prec: (x : decimal, prec : ? int, rnd : ? round) -> decimal(precprec: int.absstd/core/int/abs: (i : int) -> int) if xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int >=std/core/int/(>=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then val fracfrac: string = if precprec: int<=std/core/int/(<=): (x : int, y : int) -> bool0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then ""literal: string
count= 0
else "."literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string repeatstd/core/string/repeat: (s : string, n : int) -> string("0"literal: string
count= 1
,precprec: int) xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.showstd/core/int/show: (i : int) -> string ++std/core/types/(++): (x : string, y : string) -> string repeatstd/core/string/repeat: (s : string, n : int) -> string("0"literal: string
count= 1
,xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int) ++std/core/types/(++): (x : string, y : string) -> string fracfrac: string else val digitsdigits: int = ~std/core/int/(~): (i : int) -> intxx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int val signsign: string = if xx: decimal.is-negstd/num/decimal/is-neg: (x : decimal) -> bool then "-"literal: string
count= 1
else ""literal: string
count= 0
val ii: int = xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.absstd/core/int/abs: (i : int) -> int val manman: int = cdiv-exp10std/core/int/cdiv-exp10: (i : int, n : int) -> int(ii: int,digitsdigits: int) val fracfrac: int = ii: int -std/core/int/(-): (x : int, y : int) -> int mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(manman: int,digitsdigits: int) signsign: string ++std/core/types/(++): (x : string, y : string) -> string manman: int.showstd/core/int/show: (i : int) -> string ++std/core/types/(++): (x : string, y : string) -> string fracfrac: int.showstd/core/int/show: (i : int) -> string.pad-leftstd/core/string/pad-left: (s : string, width : int, fill : ? char) -> string(digitsdigits: int,'0'literal: char
unicode= u0030
).show-fracstd/num/decimal/show-frac: (frac : string, prec : int) -> string(precprec: int
) /* Show a decimal `d` with a given precision `prec` (=`-1000`) in scientific notation. The precision specifies the number of digits after the dot, i.e. the number of significant digits is `prec+1`. If the precision is negative, _at most_ `prec` digits are displayed, and if it is positive exactly `prec` digits are used. ``` > decimal(1,-1).show-exp "1e-1" > 1.1.decimal.show-exp "1.100000000000000088817841970012523233890533447265625" > 1.1.decimal.show-exp(-20) "1.10000000000000008882" > 0.125.decimal.show-exp(-20) "1.25e-1" > 0.125.decimal.show-exp(20) "1.25000000000000000000e-1" ``` . */ pub fun show-expstd/num/decimal/show-exp: (d : decimal, prec : ? int) -> string( dd: decimal : decimalstd/num/decimal/decimal: V, precprec: ? int : intstd/core/types/int: V = -1000literal: int
dec = -1000
hex16= 0xFC18
bit16= 0b1111110000011000
)result: -> total string : stringstd/core/types/string: V val xx: decimal = dd: decimal.round-to-precstd/num/decimal/round-to-prec: (x : decimal, prec : ? int, rnd : ? round) -> decimal(precprec: int.absstd/core/int/abs: (i : int) -> int -std/core/int/(-): (x : int, y : int) -> int dd: decimal.exponentstd/num/decimal/exponent: (d : decimal) -> int) val ss: string = xx: decimal.numstd/num/decimal/decimal/num: (decimal : decimal) -> int.absstd/core/int/abs: (i : int) -> int.showstd/core/int/show: (i : int) -> string val digitsdigits: int = ss: string.countstd/core/string/count: (s : string) -> int val expexp: int = xx: decimal.expstd/num/decimal/decimal/exp: (decimal : decimal) -> int +std/core/int/(+): (x : int, y : int) -> int digitsdigits: int -std/core/int/(-): (x : int, y : int) -> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
val signsign: string = if xx: decimal.is-negstd/num/decimal/is-neg: (x : decimal) -> bool then "-"literal: string
count= 1
else ""literal: string
count= 0
val exponentexponent: string = if expexp: int==std/core/int/(==): (x : int, y : int) -> bool0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then ""literal: string
count= 0
else "e"literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string (if expexp: int.is-posstd/core/int/is-pos: (i : int) -> bool then "+"literal: string
count= 1
else ""literal: string
count= 0
) ++std/core/types/(++): (x : string, y : string) -> string expexp: int.showstd/core/int/show: (i : int) -> string signsign: string ++std/core/types/(++): (x : string, y : string) -> string ss: string.headstd/core/sslice/head: (s : string) -> string ++std/core/types/(++): (x : string, y : string) -> string ss: string.tailstd/core/sslice/tail: (s : string) -> string.show-fracstd/num/decimal/show-frac: (frac : string, prec : int) -> string(precprec: int) ++std/core/types/(++): (x : string, y : string) -> string exponentexponent: string
fun show-fracstd/num/decimal/show-frac: (frac : string, prec : int) -> string( fracfrac: string : stringstd/core/types/string: V, precprec: int : intstd/core/types/int: V )result: -> total string : stringstd/core/types/string: V val frac-trimfrac-trim: string = fracfrac: string.trim-rightstd/core/sslice/trim-right: (s : string, sub : string) -> string("0"literal: string
count= 1
) val frac-fullfrac-full: string =if precprec: int >=std/core/int/(>=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then frac-trimfrac-trim: string.pad-rightstd/core/string/pad-right: (s : string, width : int, fill : ? char) -> string(precprec: int,'0'literal: char
unicode= u0030
) else frac-trimfrac-trim: string if frac-fullfrac-full: string.is-emptystd/core/string/is-empty: (s : string) -> bool then ""literal: string
count= 0
else "."literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string frac-fullfrac-full: string