* chrem - Chinese remainder theorem/problem solver
* When possible, chrem finds solutions for x of a set of congruences
* where the residues r1, r2, ... and the moduli m1, m2, ... are
* given integers. The Chinese remainder theorem states that if
* m1, m2, ... are relatively prime in pairs, the above congruences
* have a unique solution modulo m1 * m2 * ... If m1, m2, ...
* are not relatively prime in pairs, it is possible that no solution
* exists. If solutions exist, the general solution is expressible as:
* where m = lcm(m1,m2,...), and if m > 0, 0 <= r < m. This
* solution may be interpreted as:
* x = r + k * m [[NOTE 1]]
* where k is an arbitrary integer.
* chrem(r1,m1 [,r2,m2, ...])
* r1, r2, ... remainder integers or null values
* m1, m2, ... moduli integers
* chrem(r_list, [m_list])
* r_list list (r1,r2, ...)
* m_list list (m1,m2, ...)
* If m_list is omitted, then 'defaultmlist' is used.
* This default list is a global value that may be changed
* by the user. Initially it is the first 8 primes.
* If a remainder is null(), then the corresponding congruence is
* ignored. This is useful when working with a fixed list of moduli.
* If there are more remainders than moduli, then the later moduli are
* The moduli may be any integers, not necessarily relatively prime in
* pairs (as required for the Chinese remainder theorem). Any moduli
* may be zero; x = r (mod 0) has the meaning of x = r.
* If args were integer pairs:
* r ('r' is defined above, see [[NOTE 1]])
* If 1 or 2 list args were given:
* (r, m) ('r' and 'm' are defined above, see [[NOTE 1]])
* NOTE: In all cases, null() is returned if there is no solution.
* This function may be used to solve the following historical problems:
* Sun-Tsu, 1st century A.D.
* To find a number for which the reminders after division by 3, 5, 7
* are 2, 3, 2, respectively:
* chrem(2,3,3,5,2,7) ---> 23
* Fibonacci, 13th century A.D.
* To find a number divisible by 7 which leaves remainder 1 when
* divided by 2, 3, 4, 5, or 6:
* chrem(list(0,1,1,1,1,1),list(7,2,3,4,5,6)) ---> (301,420)
* i.e., any value that is 301 mod 420.
* Written by: Ernest W Bowen <ernie@neumann.une.edu.au>
* Interface by: Landon Curt Noll <chongo@toad.com>
static defaultmlist = list(2,3,5,7,11,13,17,19); /* The first eight primes */
local argc; /* number of args given */
local rlist; /* reminder list - ri */
local mlist; /* modulus list - mi */
local list_args; /* true => args given are lists, not r1,m1, ... */
quit "usage: chrem(r1,m1 [,r2,m2 ...]) or chrem(r_list, m_list)";
list_args = islist(param(1));
mlist = (argc == 1) ? defaultmlist : param(2);
if (size(rlist) > size(mlist)) {
quit "too many residues";
quit "odd number integers given";
for (i=1; i <= argc; i+=2) {
* solve the problem found in rlist & mlist
} else if (((y) && (r % y != z % y)) || (r != z))
* return information as required
print "chrem(r1,m1 [,r2,m2 ...]) defined";
print "chrem(rlist [,mlist]) defined";