Category talk:Wren-long: Difference between revisions

Content added Content deleted
(→‎Source code: Added largestPrime and prevPrime methods to ULong class.)
(→‎Source code: Added support for ranges of Longs and ULongs.)
Line 48: Line 48:


===Source code===
===Source code===

<syntaxhighlight lang="ecmascript">/* Module "long.wren" */
<syntaxhighlight lang="ecmascript">/* Module "long.wren" */


Line 943: Line 944:
// Returns the string representation of the current instance in base 10.
// Returns the string representation of the current instance in base 10.
toString { toBaseString_(10) }
toString { toBaseString_(10) }

// Creates and returns a range of ULongs from 'this' to 'n' with a step of 1.
// 'this' and 'n' must both be 'small' integers >= 0. 'n' can be a Num, a ULong or a Long.
..(n) { ULongs.range(this, n, 1, true) } // inclusive of 'n'
...(n) { ULongs.range(this, n, 1, false) } // exclusive of 'n'


/* Prime factorization methods. */
/* Prime factorization methods. */
Line 1,199: Line 1,205:
}
}


/* ULongs contains various routines applicable to lists of unsigned 64-bit integers. */
/* ULongs contains various routines applicable to lists of unsigned 64-bit integers
and for creating and iterating though ranges of such numbers. */
class ULongs {
class ULongs is Sequence {
static sum(a) { a.reduce(ULong.zero) { |acc, x| acc + x } }
static sum(a) { a.reduce(ULong.zero) { |acc, x| acc + x } }
static mean(a) { sum(a)/a.count }
static mean(a) { sum(a)/a.count }
Line 1,206: Line 1,213:
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }

// Private helper method for creating ranges.
static checkValue_(v, name) {
if (v is ULong && v.isSmall) {
return v.toSmall
} else if (v is Long && v.isSmall && !v.isNegative) {
return v.toSmall
} else if (v is Num && v.isInteger && v >= 0 && v <= Num.maxSafeInteger) {
return v
} else {
Fiber.abort("Invalid value for '%(name)'.")
}
}

// Creates a range of 'small' ULongs analogous to the Range class but allowing for steps > 1.
// Use the 'ascending' parameter to check that the range's direction is as intended.
construct range(from, to, step, inclusive, ascending) {
from = ULongs.checkValue_(from, "from")
to = ULongs.checkValue_(to, "to")
step = ULongs.checkValue_(step, "step")
if (step < 1) Fiber.abort("'step' must be a positive integer.")
if (ascending && from > to) Fiber.abort("'from' cannot exceed 'to'.")
if (!ascending && from < to) Fiber.abort("'to' cannot exceed 'from'.")
_rng = inclusive ? from..to : from...to
_step = step
}

// Convenience versions of 'range' which use default values for some parameters.
static range(from, to, step, inclusive) { range(from, to, step, inclusive, from <= to) }
static range(from, to, step) { range(from, to, step, true, from <= to) }
static range(from, to) { range(from, to, 1, true, from <= to) }

// Iterator protocol methods.
iterate(iterator) {
if (!iterator || _step == 1) {
return _rng.iterate(iterator)
} else {
var count = _step
while (count > 0 && iterator) {
iterator = _rng.iterate(iterator)
count = count - 1
}
return iterator
}
}

iteratorValue(iterate) { ULong.fromSmall_(_rng.iteratorValue(iterate)) }
}
}


Line 1,577: Line 1,631:
// Returns the string representation of the current instance in base 10.
// Returns the string representation of the current instance in base 10.
toString { toBaseString(10) }
toString { toBaseString(10) }

// Creates and returns a range of Longs from 'this' to 'n' with a step of 1.
// 'this' and 'n' must both be 'small' integers. 'n' can be a Num, a Long or a ULong.
..(n) { Longs.range(this, n, 1, true) } // inclusive of 'n'
...(n) { Longs.range(this, n, 1, false) } // exclusive of 'n'
}
}


/* Longs contains various routines applicable to lists of signed 64-bit integers. */
/* Longs contains various routines applicable to lists of signed 64-bit integers
and for creating and iterating though ranges of such numbers. */
class Longs {
class Longs is Sequence {
static sum(a) { a.reduce(Long.zero) { |acc, x| acc + x } }
static sum(a) { a.reduce(Long.zero) { |acc, x| acc + x } }
static mean(a) { sum(a)/a.count }
static mean(a) { sum(a)/a.count }
Line 1,586: Line 1,646:
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }

// Private helper method for creating ranges.
static checkValue_(v, name) {
if ((v is Long || v is ULong) && v.isSmall) {
return v.toSmall
} else if (v is Num && v.isInteger && v.abs <= Num.maxSafeInteger) {
return v
} else {
Fiber.abort("Invalid value for '%(name)'.")
}
}

// Creates a range of 'small' Longs analogous to the Range class but allowing for steps > 1.
// Use the 'ascending' parameter to check that the range's direction is as intended.
construct range(from, to, step, inclusive, ascending) {
from = Longs.checkValue_(from, "from")
to = Longs.checkValue_(to, "to")
step = Longs.checkValue_(step, "step")
if (step < 1) Fiber.abort("'step' must be a positive integer.")
if (ascending && from > to) Fiber.abort("'from' cannot exceed 'to'.")
if (!ascending && from < to) Fiber.abort("'to' cannot exceed 'from'.")
_rng = inclusive ? from..to : from...to
_step = step
}

// Convenience versions of 'range' which use default values for some parameters.
static range(from, to, step, inclusive) { range(from, to, step, inclusive, from <= to) }
static range(from, to, step) { range(from, to, step, true, from <= to) }
static range(from, to) { range(from, to, 1, true, from <= to) }

// Iterator protocol methods.
iterate(iterator) {
if (!iterator || _step == 1) {
return _rng.iterate(iterator)
} else {
var count = _step
while (count > 0 && iterator) {
iterator = _rng.iterate(iterator)
count = count - 1
}
return iterator
}
}

iteratorValue(iterate) { Long.fromSmall_(_rng.iteratorValue(iterate)) }
}</syntaxhighlight>
}</syntaxhighlight>