Category talk:Wren-i64: Difference between revisions

→‎Source code (Wren): Complete overhaul including new constants, 'divisor' methods and several bug fixes.
(U64.isPrime method now uses a 'witness' list appropriate to the size of number.)
(→‎Source code (Wren): Complete overhaul including new constants, 'divisor' methods and several bug fixes.)
Line 47:
static four { from(4) }
static five { from(5) }
static six { from(6) }
static seven { from(7) }
static eight { from(8) }
static nine { from(9) }
static ten { from(10) }
 
Line 58 ⟶ 62:
// The arguments can be either I64 objects or Nums.
// If 'n' is less than 0, returns zero. O.pow(0) returns one.
// Returns zero if the calculation would otherwise overflow or underflow.
static pow(x, n) {
if (!(x is I64)) x = from(x)
Line 72 ⟶ 75:
value = value.pow(n.toNum)
if (value <= 9007199254740991) return neg ? from(-value) : from(value)
if (value >= 2.pow(63)) return zero
x = x.copy()
var y = one
var z = n.copy()
while (true) {
if (z.isOdd) {
Line 83 ⟶ 85:
if (z.isZero) break
z.rsh(1)
x.squaremul(x)
}
return y
Line 101 ⟶ 103:
var neg = t < 0
if (neg) {
if (n % 2 == 0.isDivisible(two)) {
Fiber.abort("Cannot take the %(n)th root of a negative number.")
} else {
Line 120 ⟶ 122:
// The arguments can either be I64 objects or Nums but 'mod' must be non-zero.
static modMul(x, n, mod) {
if (!(x is I64)) x = from(x)
if (!(n is I64)) n = from(n)
if (!(mod is I64)) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modMul with modulus 0.")
var sign = x.sign * n.sign
Line 133 ⟶ 135:
static modPow(x, exp, mod) {
if (!(x is I64)) x = from(x)
if (!(exp is I64)) exp = from(exp)
if (!(mod is I64)) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modPow with modulus 0.")
Line 144 ⟶ 146:
while (exp > 0) {
if (base.isZero) return zero
if (exp.isOdd) r.set(modMul(r, base, mod))
exp.rsh(1)
base.set(modMul(base, base, mod))
Line 177 ⟶ 179:
// Returns the smaller of two I64 objects.
static min(x, y) {
if (!(x is I64)) x = from(x)
if (!(y is I64)) y = from(y)
if (x < y) return x
return y
Line 183 ⟶ 187:
// Returns the greater of two I64 objects.
static max(x, y) {
if (!(x is I64)) x = from(x)
if (!(y is I64)) y = from(y)
if (x > y) return x
return y
Line 189 ⟶ 195:
// Returns the positive difference of two I64 objects.
static dim(x, y) {
if (!(x is I64)) x = from(x)
if (!(y is I64)) y = from(y)
if (x >= y) return x - y
return zero
Line 195 ⟶ 203:
// Returns the greatest common divisor of two I64 objects.
static gcd(x, y) {
x = from(x)
y = from(y)
while (y != zero) {
var t = y
y = .set(x % y)
x = .set(t)
}
return x.abs
Line 205 ⟶ 215:
// Returns the least common multiple of two I64 objects.
static lcm(x, y) {
x = from(x)
y = from(y)
if (x.isZero && y.isZero) return zero
return (x*y).abs / gcd(x, y)
Line 334 ⟶ 346:
 
foreign cmpU64(op) // compare this to a U64 object
 
/* Miscellaneous methods. */
 
Line 340 ⟶ 352:
max(op) { (op > this) ? op : this } // returns the maximum of this and another I64 object
 
clamp(min, max) { // clamps this to the interval [min, max]
if (thismin <> minmax) setFiber.abort(min"Range cannot be decreasing.")
if (this < min) set(min) else if (this > max) set(max)
return this.copy()
}
 
copy() { I64.from(this) } // copies 'this' to a new I64 object
 
isOdd { this % I64.two == I64.one } // true if 'this' is odd
Line 353 ⟶ 366:
isSafe { this >= I64.minSafe && this <= I64.maxSafe } // true if 'this' is safe
 
isDivisible(d) { this % d == I64.zero } // true if 'this' is divisible by d
 
isRoot(n) { // true if 'this' is an exact nth root of another I64 object
var r = I64.root(this, n)
return I64.pow(r, n) == this
}
 
isSquare { isRoot(2) } // true if 'this' is an exact square root of another I64 object
isCube { isRoot(3) } // true if 'this' is an exact cube root of another I64 object
 
sign { // the sign of 'this'
if (this < I64.zero) return -1
if (this > I64.zero) return 1
Line 384 ⟶ 397:
static four { from(4) }
static five { from(5) }
static six { from(6) }
static seven { from(7) }
static eight { from(8) }
static nine { from(9) }
static ten { from(10) }
 
Line 394 ⟶ 411:
// The arguments can be either U64 objects or Nums.
// If 'n' is less than 0, returns zero. O.pow(0) returns one.
// Returns zero if the calculation would otherwise overflow.
static pow(x, n) {
if (!(x is U64)) x = from(x)
Line 404 ⟶ 420:
var value = x.toNum.pow(n.toNum)
if (value <= 9007199254740991) return from(value)
if (value >= 2.pow(64)) return zero
x = x.copy()
var y = one
var z = n.copy()
while (true) {
if (z.isOdd) {
Line 415 ⟶ 430:
if (z.isZero) break
z.rsh(1)
x.squaremul(x)
}
return y
Line 444 ⟶ 459:
static modMul(x, n, mod) {
if (!(x is U64)) x = from(x)
if (!(n is U64)) n = from(n) else n = n.copy()
if (!(mod is U64)) mod = from(mod)
var z = zero
Line 460 ⟶ 475:
static modPow(x, exp, mod) {
if (!(x is U64)) x = from(x)
if (!(exp is U64)) exp = from(exp) else exp = exp.copy()
if (!(mod is U64)) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modPow with modulus 0.")
Line 484 ⟶ 499:
// Returns the smaller of two U64 objects.
static min(x, y) {
if (!(x is U64)) x = from(x)
if (!(y is U64)) y = from(y)
if (x < y) return x
return y
Line 490 ⟶ 507:
// Returns the greater of two U64 objects.
static max(x, y) {
if (!(x is U64)) x = from(x)
if (!(y is U64)) y = from(y)
if (x > y) return x
return y
Line 496 ⟶ 515:
// Returns the positive difference of two U64 objects.
static dim(x, y) {
if (!(x is U64)) x = from(x)
if (!(y is U64)) y = from(y)
if (x >= y) return x - y
return zero
Line 502 ⟶ 523:
// Returns the greatest common divisor of two U64 objects.
static gcd(x, y) {
x = from(x)
y = from(y)
while (y != zero) {
var t = y
y = .set(x % y)
x = .set(t)
}
return x
Line 512 ⟶ 535:
// Returns the least common multiple of two U64 objects.
static lcm(x, y) {
x = from(x)
y = from(y)
if (x.isZero && y.isZero) return zero
return x * y / gcd(x, y)
Line 524 ⟶ 549:
if (n < 2) return one
var fact = one
var i = two2
while (i <= n) {
fact.mul(i)
i.inc = i + 1
}
return fact
Line 547 ⟶ 572:
if (e > 1) prod.mul(factorial(e))
}
return factorial(n)/.div(prod)
}
 
Line 632 ⟶ 657:
return millerRabinTest_(x, a)
}
 
// Returns the next prime number greater than 'x'.
static nextPrime(x) {
Line 645 ⟶ 670:
// Private worker method for Pollard's Rho algorithm.
static pollardRho_(m, seed, c) {
var g = Fn.new { |x| x.copy(x * x).square.add(c).rem(m) }
var x = from(seed)
var y = from(seed)
Line 652 ⟶ 677:
var count = 0
while (true) {
x = .set(g.call(x))
y = .set(g.call(g.call(y)))
if (x >= y) d.sub(x, y).rem(m) else d.sub(y, x).rem(m)
z.mul(d)
Line 724 ⟶ 749:
while (n > one) {
if (checkPrime && isPrime(n)) {
factors.add(n.copy())
break
}
Line 798 ⟶ 823:
 
// As 'divisors' method but uses a different algorithm.
// Better for largelarger numbers with a small number of prime factors.
static divisors2(n) {
if (n <=is 0Num) returnn []= from(n)
var factorspf = primeFactors(n)
varif divs(pf.count == 0) return (n == 1) ? [one] : pf
forvar (parr in= factors) {[]
forif (ipf.count in== 0...divs.count1) divs.add(divs[i]*p){
arr.add([pf[0].copy(), 1])
} else {
var prevPrime = pf[0]
var count = 1
for (i in 1...pf.count) {
if (pf[i] == prevPrime) {
count = count + 1
} else {
arr.add([prevPrime.copy(), count])
prevPrime = pf[i]
count = 1
}
}
arr.add([prevPrime.copy(), count])
}
divs.sort()var divisors = []
var c = divs.countgenerateDivs
ifgenerateDivs (c= > 1)Fn.new { |currIndex, currDivisor|
forif (icurrIndex in== c-1arr..1count) {
if divisors.add(divs[i-1] == divs[i]) divscurrDivisor.removeAtcopy(i))
return
}
for (i in 0..arr[currIndex][1]) {
generateDivs.call(currIndex+1, currDivisor)
currDivisor = currDivisor * arr[currIndex][0]
}
}
returngenerateDivs.call(0, divsone)
return divisors.sort()
}
 
Line 821 ⟶ 866:
var c = d.count
return (c <= 1) ? [] : d[0..-2]
}
 
// Returns the sum of all the divisors of 'n' including 1 and 'n' itself.
static divisorSum(n) {
if (n < 1) return zero
n = from(n)
var total = one
var power = two
while (n.isDivisible(two)) {
total.add(power)
power.mul(2)
n.div(2)
}
var i = three
while (i * i <= n) {
var sum = one
power.set(i)
while (n.isDivisible(i)) {
sum.add(power)
power.mul(i)
n.div(i)
}
total.mul(sum)
i = i + 2
}
if (n > 1) total.mul(n + 1)
return total
}
 
// Returns the number of divisors of 'n' including 1 and 'n' itself.
static divisorCount(n) {
if (n < 1) return 0
n = from(n)
var count = 0
var prod = 1
while (n.isDivisible(two)) {
count = count + 1
n.div(2)
}
prod = prod * (1 + count)
var i = three
while (i * i <= n) {
count = 0
while (n.isDivisible(i)) {
count = count + 1
n.div(i)
}
prod = prod * (1 + count)
i.add(2)
}
if (n > 2) prod = prod * 2
return prod
}
 
Line 944 ⟶ 1,041:
max(op) { (op > this) ? op : this } // returns the maximum of this and another U64 object
 
clamp(min, max) { // clamps this to the interval [min, max]
if (thismin <> minmax) setFiber.abort(min"Range cannot be decreasing.")
if (this < min) set(min) else if (this > max) set(max)
return this.copy()
}
 
copy() { U64.from(this) } // copies 'this' to a new U64 object
 
isOdd { this % U64.two == 1 } // true if 'this' is odd
Line 959 ⟶ 1,057:
isDivisible(d) { this % d == U64.zero } // true if 'this' is divisible by d
 
isRoot(n) { // true if 'this' is an exact nth root of another U64 object
var r = U64.root(this, n)
return U64.pow(r, n) == this
}
 
isSquare { isRoot(2) } // true if 'this' is an exact square root of another U64 object
isCube { isRoot(3) } // true if 'this' is an exact cube root of another U64 object
 
sign { // the sign of 'this'
if (this > U64.zero) return 1
return 0
9,476

edits