Category talk:Wren-big: Difference between revisions

→‎Source code: Added BigDec and BigDecs classes.
(→‎Source code: Added BigInt.prevPrime method.)
(→‎Source code: Added BigDec and BigDecs classes.)
Line 2,017:
static mean(a) { sum(a)/a.count }
static prod(a) { a.reduce(BigRat.one) { |acc, x| acc * x } }
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }
}
 
/* BigDec represents an arbitrary length decimal number. Internally, it is simply a BigRat object
but with the number of decimal places in its expansion limited to a given 'precision'.
The minimum and default precision is 16 decimal places. BigDec objects are immutable.
*/
class BigDec is Comparable {
// Private helper function to check that 'o' is a suitable type and throw an error otherwise.
// Numbers, rational numbers and numeric strings are returned as BigDecs.
static check_(o) {
if (o is BigDec) return o
if (o is Num || o is String) return new(o)
if (o.type.toString == "Rat") return new_(BigRat.fromRat(o))
if (o is BigRat) return fromBigRat(o)
if (o is BigInt) return fromBigInt(o)
Fiber.abort("Argument must either be a number, a rational number or a numeric string.")
}
 
// Numeric constants (all have default precision)
static minusOne { fromInt(-1) }
static zero { fromInt(0) }
static one { fromInt(1) }
static two { fromInt(2) }
static three { fromInt(3) }
static four { fromInt(4) }
static five { fromInt(5) }
static six { fromInt(6) }
static seven { fromInt(7) }
static eight { fromInt(8) }
static nine { fromInt(9) }
static ten { fromInt(10) }
static half { new(0.5) }
static quarter { new(0.25) }
static fifth { new(0.2) }
static eighth { new(0.125) }
static tenth { new(0.1) }
 
// Transcendental constants (all have precision 64)
static e { new("2.7182818284590452353602874713526624977572470936999595749669676277", 64) }
static ln2 { new("0.6931471805599453094172321214581765680755001343602552541206800095", 64) }
static ln10 { new("2.3025850929940456840179914546843642076011014886287729760333279010", 64) }
static pi { new("3.1415926535897932384626433832795028841971693993751058209749445923", 64) }
static tau { new("6.2831853071795864769252867665590057683943387987502116419498891846", 64) }
static phi { new("1.6180339887498948482045868343656381177203091798057628621354486227", 64) }
static sqrt2 { new("1.4142135623730950488016887242096980785696718753769480731766797380", 64) }
 
// Returns the greater of two BigDec objects.
static max(d1, d2) { (d1 < d2) ? d2 : d1 }
 
// Returns the smaller of two BigDec objects.
static min(d1, d2) { (d1 < d2) ? d1 : d2 }
 
// Constructs a BigDec object from a number or decimal numeric string.
construct new(s, prec) {
_prec = prec.max(16)
_br = BigRat.fromDecimal(s)
if (s is String) _br = _br.round(_prec)
}
 
// Constructs a BigDec object from an integer.
construct fromInt(i, prec) {
if (!(i is Num && i.isInteger)) Fiber.abort ("Argument must be an integer.")
_br = BigRat.new(i, 1)
_prec = prec.max(16)
}
 
// Constructs a BigDec object from a big integer.
construct fromBigInt(bi, prec) {
if (!(bi is BigInt)) Fiber.abort ("Argument must be a big integer.")
_br = BigRat.new(bi, BigInt.one)
_prec = prec.max(16)
}
 
// Constructs a BigDec object from a rational number.
construct fromRat(r, prec) {
_br = BigRat.fromRat(r)
_prec = prec.max(16)
}
 
// Constructs a BigDec object from a big rational number.
construct fromBigRat(br, prec) {
if (!(br is BigRat)) Fiber.abort ("Argument must be a big rational number.")
_br = br.copy()
_prec = prec.max(16)
}
 
// Convenience versions of the above constructors which always use a precision of 16.
static new(s) { new(s, 16) }
static fromInt(i) { fromInt(i, 16) }
static fromBigInt(bi) { fromBigInt(bi, 16) }
static fromRat(r) { fromRat(r, 16) }
static fromBigRat(br) { fromBigRat(br, 16) }
 
// Private constructor.
construct new_(br, prec) {
_br = br.round(prec)
_prec = prec
}
// Private method to return the internal BigRat without copying.
br_ { _br }
 
// Get or sets the precision for this object.
prec { _prec }
prec=(p) { _prec = p.floor.max(16) }
 
// Other properties.
isInteger { _br.isInteger } // checks if integral or not
isPositive { _br.isPositive } // checks if positive
isNegative { _br.isNegative } // checks if negative
isUnit { _br.isUnit } // checks if plus or minus one
isZero { _br.isZero } // checks if zero
 
/* Note that the result of unary operations has the same precision as the operand
and the result of binary operations has the greater precision of the operands */
 
// Rounding methods (similar to those in Num class).
ceil { BigDec.new_(_br.ceil, _prec) } // higher integer, towards zero
floor { BigDec.new_(_br.floor, _prec) } // lower integer
truncate { BigDec.new_(_br.truncate, _prec) } // lower integer, towards zero
round { BigDec.new_(_br.round, _prec) } // nearer integer
roundUp { BigDec.new_(_br.roundUp, _prec) } // higher integer, away from zero
 
round(digits) { BigDec.new(_br.round(digits), _prec) } // rounds to 'digits' decimal places
fraction { this - truncate } // fractional part (same sign as this)
 
// Negation.
- { BigDec.new (-_br, _prec) }
 
// Arithmetic operators (work with numbers, rational numbers and numeric strings
// as well as other decimal numbers).
+(o) { (o = BigDec.check_(o)) && BigDec.new_(_br + o.br_, _prec.max(o.prec)) }
-(o) { (o = BigDec.check_(o)) && BigDec.new_(_br - o.br_, _prec.max(o.prec)) }
*(o) { (o = BigDec.check_(o)) && BigDec.new_(_br * o.br_, _prec.max(o.prec)) }
/(o) { (o = BigDec.check_(o)) && BigDec.new_(_br / o.br_, _prec.max(o.prec)) }
%(o) { (o = BigDec.check_(o)) && BigDec.new_(_br % o.br_, _prec.max(o.prec)) }
 
// Integral power methods.
pow(i) { BigDec.new_(_br.pow(i), _prec) }
square { BigDec.new_(_br.square, _prec) }
cube { BigDec.new_(_br.cube, _prec) }
 
// Roots to 'digits' places or 16 places by default.
sqrt(digits) { BigDec.new_(_br.sqrt(digits), _prec) }
cbrt(digits) { BigDec.new_(_br.cbrt(digits), _prec) }
sqrt { sqrt(16) }
cbrt { cbrt(16) }
 
// Other methods.
inverse { BigDec.new_(_br.inverse, _prec) } // inverse
idiv(o) { (this/o).truncate } // integer division
inc { this + BigDec.one } // increment
dec { this - BigDec.one } // decrement
abs { BigDec.new_(_br.abs, _prec)} // absolute value
sign { _br.num.sign } // sign
 
// The inherited 'clone' method just returns 'this' as BigDec objects are immutable.
// If you need an actual copy use this method instead.
copy() { BigDec.new_(_br.copy(), _prec) }
 
// Compares this BigDec with another one to enable comparison operators via Comparable trait.
compare(other) { _br.compare(other.br_) }
 
// As above but compares the absolute values of the BigDecs.
compareAbs(other) { _br.compareAbs(other.br_) }
 
// Returns this BigDec expressed as a BigInt with any fractional part truncated.
toBigInt { _br.num/_br.den }
 
// Returns this BigDec expressed as a BigRat.
toBigRat { _br.copy() }
 
// Converts the current instance to a Num where possible.
// Will probably lose accuracy for larger numbers.
toFloat { Num.fromString(this.toString(14)) }
 
// Converts the current instance to an integer where possible with any fractional part truncated.
// Will probably lose accuracy for integers >= 2^53.
toInt { this.toFloat.truncate }
 
// Returns the string representation of this BigDec object to 'digits' decimal places.
// If 'rounded' is true, the value is rounded to that number of places with halves
// being rounded away from zero. Otherwise the value is truncated to that number of places.
// If 'zfill' is true, any unfilled decimal places are filled with zeros.
toString(digits, rounded, zfill) { _br.toDecimal(digits, rounded, zfill) }
 
// Convenience versions of the above which use default values for some or all parameters
// and never add trailing zeros.
toString(digits, rounded) { toString(digits, rounded, false) }
toString(digits) { toString(digits, true, false) } // always rounded
toString { toString(_prec, true, false) } // precision digits, always rounded
toDefaultString { toString(16, true, false) } // 16 digits, always rounded
}
 
/* BigDecs contains various routines applicable to lists of big decimal numbers */
class BigDecs {
static sum(a) { a.reduce(BigDec.zero) { |acc, x| acc + x } }
static mean(a) { sum(a)/a.count }
static prod(a) { a.reduce(BigDec.one) { |acc, x| acc * x } }
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }
9,485

edits