Category talk:Wren-i64: Difference between revisions

(→‎Source code (Wren): Removed the previous limitation on the U64.isPrime method.)
 
(5 intermediate revisions by the same user not shown)
Line 28:
 
==Source code (Wren)==
<syntaxhighlight lang="ecmascriptwren">/* Module "i64.wren" */
 
import "./trait" for Comparable
Line 63:
// If 'n' is less than 0, returns zero. O.pow(0) returns one.
static pow(x, n) {
if (!(x is I64)Num) x = from(x)
if (!(n is I64)Num) n = from(n)
if (n < 0) return zero
if (n.isZero) return one
Line 95:
// Throws an error if 'x' is negative and 'n' is even.
static root(x, n) {
if (!(x is I64)Num) x = from(x)
if (!((n is Num) && n.isInteger && n > 0)) {
Fiber.abort("'n' must be a positive integer.")
Line 134:
// The arguments can either be I64 objects or Nums but 'mod' must be non-zero.
static modPow(x, exp, mod) {
if (!(x is I64)Num) x = from(x)
exp = from(exp)
if (!(mod is I64)Num) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modPow with modulus 0.")
var r = one
Line 156:
// The arguments can either be I64 objects or Nums but must be co-prime.
static modInv(x, n) {
if (!(x is I64)Num) x = from(x)
if (!(n is I64)Num) n = from(n)
var r = from(n)
var newR = from(x).abs
Line 179:
// Returns the smaller of two I64 objects.
static min(x, y) {
if (!(x is I64)Num) x = from(x)
if (!(y is I64)Num) y = from(y)
if (x < y) return x
return y
Line 187:
// Returns the greater of two I64 objects.
static max(x, y) {
if (!(x is I64)Num) x = from(x)
if (!(y is I64)Num) y = from(y)
if (x > y) return x
return y
Line 195:
// Returns the positive difference of two I64 objects.
static dim(x, y) {
if (!(x is I64)Num) x = from(x)
if (!(y is I64)Num) y = from(y)
if (x >= y) return x - y
return zero
Line 360:
copy() { I64.from(this) } // copies 'this' to a new I64 object
 
isOdd { this % I64.two =!= I64.onezero } // true if 'this' is odd
isEven { this % I64.two == I64.zero } // true if 'this' is even
isZero { this == I64.zero } // true if 'this' is zero
Line 407:
static maxSafe { from(9007199254740991) }
static maxU32 { from(4294967295) }
 
// Returns the largest prime less than 2^64.
static largestPrime { U64.fromStr("18446744073709551557") }
 
// Returns a U64 object equal in value to 'x' raised to the power of 'n'.
Line 412 ⟶ 415:
// If 'n' is less than 0, returns zero. O.pow(0) returns one.
static pow(x, n) {
if (!(x is U64)Num) x = from(x)
if (!(n is U64)Num) n = from(n)
if (n.isZero) return one
if (n.isOne) return x.copy()
Line 439 ⟶ 442:
// 'x' can either be a U64 object or a Num but 'n' must be a positive integer.
static root(x, n) {
if (!(x is U64)Num) x = from(x)
if (!((n is Num) && n.isInteger && n > 0)) {
Fiber.abort("'n' must be a positive integer.")
Line 453 ⟶ 456:
}
return s
}
 
// Private helper method for modMul method to avoid overflow.
static isBasicPrime_checkedAdd_(na, b, c) {
var isbproom = isBasicPrime_(x)c - U64.one - a
} else if (xb <= 1373653room) {
a = [2].add(b)
} else if (x < 9080191) {
a.set(b =- [2,room 3,- 5]U64.one)
}
}
 
Line 458 ⟶ 471:
// The arguments can either be U64 objects or Nums.
static modMul(x, n, mod) {
if (!(x is U64)Num) x = from(x)
n = from(n)
if (!(mod is U64)) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modMul with modulus 0.")
var z = zero
var y = x.copy() % mod
n.rem(mod)
if (n <> 49y) return true{
avar =t [2,= 3]y
ay = [31, 73]n
an = [2, 7, 61]t
}
while (n > zero) {
if (n.isOdd) checkedAdd_(z.add(, y).rem(, mod)
y.lsh(1).remcheckedAdd_(y, y, mod)
n.rsh(1)
}
Line 474 ⟶ 494:
// The arguments can either be U64 objects or Nums but 'mod' must be non-zero.
static modPow(x, exp, mod) {
if (!(x is U64)Num) x = from(x)
exp = from(exp)
if (!(mod is U64)Num) mod = from(mod)
if (mod.isZero) Fiber.abort("Cannot take modPow with modulus 0.")
var r = one
Line 492 ⟶ 512:
// The arguments can either be U64 objects or Nums but must be co-prime.
static modInv(x, n) {
if (!(x is U64)Num) x = from(x)
if (!(n is U64)Num) n = from(n)
return I64.modInv(x.toI64, n.toI64).toU64
}
Line 499 ⟶ 519:
// Returns the smaller of two U64 objects.
static min(x, y) {
if (!(x is U64)Num) x = from(x)
if (!(y is U64)Num) y = from(y)
if (x < y) return x
return y
Line 507 ⟶ 527:
// Returns the greater of two U64 objects.
static max(x, y) {
if (!(x is U64)Num) x = from(x)
if (!(y is U64)Num) y = from(y)
if (x > y) return x
return y
Line 515 ⟶ 535:
// Returns the positive difference of two U64 objects.
static dim(x, y) {
if (!(x is U64)Num) x = from(x)
if (!(y is U64)Num) y = from(y)
if (x >= y) return x - y
return zero
Line 580 ⟶ 600:
// Returns whether or not 'x' is an instance of U64.
static isInstance(x) { x is U64 }
 
// Private method to determine if a U64 is a basic prime or not.
static isBasicPrime_(n) {
if (n.isOne) return false
if (n == two || n == three || n == five) return true
if (n.isEven || n.isDivisible(three) || n.isDivisible(five)) return false
if (n < 49) return true
return null // unknown if prime or not
}
 
// Private method to apply the Miller-Rabin test.
Line 618 ⟶ 629:
}
}
}
return true
}
 
// Private helper method for 'isPrime' method.
// Determines whether 'x' is prime using a wheel with basis [2, 3, 5].
// Should be faster than Miller-Rabin if 'x' is below 2^37.
static isPrimeWheel_(x) {
if (n.isOnex < 2) return false
var n = x.copy()
if (n.isEven) return n == 2
if ((n%3).isZero) return n == 3
if ((n%5).isZero) return n == 5
var d = U64.seven
} else ifwhile (xd*d <= 25326001n) {
if ((n%d).isZero) return false
a = [2, 3, 5, 7]d.add(4)
if ((n%d).isZero) return false
d.add(2)
if ((n%d).isZero) return false
d.add(4)
if ((n%d).isZero) return false
d.add(2)
if ((n%d).isZero) return false
d.add(4)
if ((n%d).isZero) return false
d.add(6)
if ((n%d).isZero) return false
d.add(2)
if ((n%d).isZero) return false
d.add(6)
if ((n%d).isZero) return false
}
return true
Line 624 ⟶ 667:
// Returns true if 'x' is prime, false otherwise.
static isPrime(x) {
if (!(x is U64)Num) x = from(x)
if (x < 137438953472) return isPrimeWheel_(x) // use wheel if below 2^37
var isbp = isBasicPrime_(x)
if (isbpx.isEven !=|| nullx.isDivisible(three) return|| x.isDivisible(five) || isbp
if (n.isEven || n.isDivisible(three) || nx.isDivisible(fiveseven)) return false
var a
if (x < 20471122004669633) {
a = [2]
} else if (x < 1373653) {
a = [2, 3]
} else if (x < 9080191) {
a = [31, 73]
} else if (x < 25326001) {
a = [2, 3, 5]
} else if (x < 3215031751) {
a = [2, 3, 5, 7]
} else if (x < 4759123141) {
a = [2, 7, 61]
} else if (x < 1122004669633) {
a = [2, 13, 23, 1662803]
} else if (x < 2152302898747) {
Line 648 ⟶ 680:
} else if (x < 341550071728321) {
a = [2, 3, 5, 7, 11, 13, 17]
} else if (x < fromfromStr("3825123056546413051")) {
a = [2, 3, 5, 7, 11, 13, 17, 19, 23]
} else {
Line 658 ⟶ 690:
// Returns the next prime number greater than 'x'.
static nextPrime(x) {
if (!(x is U64)Num) x = from(x)
if (x < two) return U64.two
var n = x.isEven ? x + one : x + two
while (true) {
if (isPrime(n)) return n
n.add(two)
}
}
 
// Returns the previous prime number less than 'x' or null if there isn't one.
static prevPrime(x) {
if (x is Num) x = from(x)
if (x < three) return null
if (n == two || nx == three || n == five) return trueU64.two
var n = x.isEven ? x - one : x - two
while (true) {
if (isPrime(n)) return n
n.sub(two)
}
}
Line 1,047 ⟶ 1,092:
copy() { U64.from(this) } // copies 'this' to a new U64 object
 
isOdd { this % U64.two == 1 } // true if 'this' is odd
isEven { this % U64.two == 0 } // true if 'this' is even
isZero { this == 0 } // true if 'this' is zero
isOne { this == 1 } // true if 'this' is one
isSafe { this <= U64.maxSafe } // true if 'this' is safe
 
isDivisible(d) { this % d == U64.zero } // true if 'this' is divisible by d
Line 1,067 ⟶ 1,112:
return 0
}
// Return a list of the current instance's base 10 digits
digits { toString.map { |d| Num.fromString(d) }.toList }
 
digits { toString.map { |d| Num.fromString(d) }.toList } // aReturns listthe sum of the current instance's base 10 digits.
digitSum {
digitSum { digits.reduce(0) { |acc, d| acc = acc + d } } // the sum of those digits
var sum = 0
for (d in toString.bytes) sum = sum + d - 48
return sum
}
}
 
9,482

edits