package org.spaceroots.rkcheck;

import java.math.BigInteger;
import java.math.BigDecimal;

/**
 * This class implements quadratic
 * irrational numbers (which are also called quadratic surds).

 * 

Quadratic irrational numbers are roots of quadratic polynoms * with integer coefficients. They can be written: *

 *         p1 + p2 sqrt (d)
 *   z =  ------------------
 *               q
 *   
* where p1 and p2 are integers, d is a square free strictly positive * integer and q is a strictly positive integer. This number is a root * of: *
 *     2  2                2       2
 *    q  X  - 2 q p1 X + p1  - d p2  = 0
 *   
*

*

The set of quadratic irrational numbers associated with a given * number d is a field denoted F[sqrt(d)]. This class implements * computation within such a field.

* @version $Id: QuadraticSurd.java,v 1.4 2004/05/23 19:41:36 luc Exp $ * @author L. Maisonobe */ public class QuadraticSurd { /** * Simple constructor. * Build a null quadratic surd */ public QuadraticSurd() { p1 = BigInteger.ZERO; p2 = BigInteger.ZERO; d = BigInteger.ZERO; q = BigInteger.ONE; } /** * Simple constructor. * Build a quadratic surd from a single integer * @param l value of the quadratic surd */ public QuadraticSurd(long l) { p1 = BigInteger.valueOf(l); p2 = BigInteger.ZERO; d = BigInteger.ZERO; q = BigInteger.ONE; } /** * Simple constructor. * Build a quadratic surd from a single integer * @param l value of the quadratic surd */ public QuadraticSurd(BigInteger l) { p1 = l; p2 = BigInteger.ZERO; d = BigInteger.ZERO; q = BigInteger.ONE; } /** * Simple constructor. * Build a quadratic surd from a numerator and a denominator. This * is a simple rational number. * @param numerator numerator of the quadratic surd * @param denominator denominator of the quadratic surd * @exception ArithmeticException if the denominator is zero */ public QuadraticSurd(long numerator, long denominator) { this(BigInteger.valueOf(numerator), BigInteger.ZERO, BigInteger.ZERO, BigInteger.valueOf(denominator)); } /** * Simple constructor. * Build a quadratic surd from a numerator and a denominator. This * is a simple rational number. * @param numerator numerator of the quadratic surd * @param denominator denominator of the quadratic surd * @exception ArithmeticException if the denominator is zero */ public QuadraticSurd(BigInteger numerator, BigInteger denominator) { this(numerator, BigInteger.ZERO, BigInteger.ZERO, denominator); } /** * Simple constructor. * Build a quadratic surd from its coordinates * @param p1 integer part of the numerator * @param p2 coefficient of the root part of the numerator * @param d root * @param q denominator * @exception ArithmeticException if the root is negative * @exception ArithmeticException if the denominator is zero */ public QuadraticSurd(long p1, long p2, long d, long q) { this(BigInteger.valueOf(p1), BigInteger.valueOf(p2), BigInteger.valueOf(d), BigInteger.valueOf(q)); } /** * Simple constructor. * Build a quadratic surd from its coordinates * @param p1 integer part of the numerator * @param p2 coefficient of the root part of the numerator * @param d root * @param q denominator * @exception ArithmeticException if the root is negative * @exception ArithmeticException if the denominator is zero */ public QuadraticSurd(BigInteger p1, BigInteger p2, BigInteger d, BigInteger q) { if (d.signum() < 0) { throw new ArithmeticException("negative root"); } if (q.signum() == 0) { throw new ArithmeticException("divide by zero"); } this.p1 = p1; this.p2 = p2; this.d = d; this.q = q; simplify(); } /** Simple constructor. * Build a quadratic surd by approximating a BigDecimal to a given * tolerance using continued fractions * @param r real number to approximate * @param tolerance tolerance allowed for the approximation */ public QuadraticSurd(BigDecimal r, BigDecimal tolerance) { p2 = BigInteger.ZERO; d = BigInteger.ZERO; boolean negative = (r.signum() < 0); BigDecimal a = negative ? r.negate() : r; // initialize the recurrence relation BigInteger An2 = BigInteger.ZERO; BigInteger Bn2 = BigInteger.ONE; BigInteger An1 = BigInteger.ONE; BigInteger Bn1 = BigInteger.ZERO; BigDecimal zero = new BigDecimal(BigInteger.ZERO); BigDecimal one = new BigDecimal(BigInteger.ONE); do { BigInteger p = a.toBigInteger(); BigInteger An = p.multiply(An1).add(An2); p1 = negative ? An.negate() : An; q = p.multiply(Bn1).add(Bn2); a = a.subtract(new BigDecimal(p)); if (a.compareTo(zero) == 0) { return; } a = one.divide(a, r.scale(), BigDecimal.ROUND_HALF_EVEN); An2 = An1; An1 = An; Bn2 = Bn1; Bn1 = q; } while (bigDecimalValue(r.scale()).subtract(r).abs().compareTo(tolerance) > 0); } /** * Copy-constructor. * @param qs quadratic surd to copy */ public QuadraticSurd(QuadraticSurd qs) { p1 = qs.p1; p2 = qs.p2; d = qs.d; q = qs.q; } /** * Check if a quadratic surd belong to the same field as the * instance. * @param qs quadratic surd to check against the instance * @return true if the specified quadratic surd belong to the same * field as the instance */ public boolean sameField(QuadraticSurd qs) { return (p2.signum() == 0) || (qs.p2.signum() == 0) || (d.compareTo(qs.d) == 0); } /** * Check if a quadratic surd belong to the same field as the * instance. * @param qs quadratic surd to check against the instance * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ private void chokeIfDifferentField(QuadraticSurd qs) throws ArithmeticException { if (! sameField(qs)) { throw new ArithmeticException("forbidden operation between" + " quadratic surds belonging" + " to different fields: " + this + " vs. " + qs); } } /** * Negate the instance */ public void negateSelf() { p1 = p1.negate(); p2 = p2.negate(); } /** * Negate a quadratic surd. * @param qs quadratic surd to negate * @return a new quadratic surd which is the opposite of r */ public static QuadraticSurd negate(QuadraticSurd qs) { QuadraticSurd copy = new QuadraticSurd(qs); copy.negateSelf(); return copy; } /** * Add a quadratic surd to the instance. * @param qs quadratic surd to add. * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public void addToSelf(QuadraticSurd qs) throws ArithmeticException { // safety check chokeIfDifferentField(qs); // computation if (p2.signum() == 0) { d = qs.d; } p1 = p1.multiply(qs.q).add(q.multiply(qs.p1)); p2 = p2.multiply(qs.q).add(q.multiply(qs.p2)); q = q.multiply(qs.q); // simplification simplify(); } /** Add two quadratic surds. * @param qs1 first quadratic surd * @param qs2 second quadratic surd * @return a new quadratic surd which is the sum of qs1 and qs2 * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public static QuadraticSurd add(QuadraticSurd qs1, QuadraticSurd qs2) throws ArithmeticException { QuadraticSurd copy = new QuadraticSurd(qs1); copy.addToSelf(qs2); return copy; } /** * Subtract a quadratic surd to the instance. * @param qs quadratic surd to subtract. * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public void subtractFromSelf(QuadraticSurd qs) throws ArithmeticException { // safety check chokeIfDifferentField(qs); // computation if (p2.signum() == 0) { d = qs.d; } p1 = p1.multiply(qs.q).subtract(q.multiply(qs.p1)); p2 = p2.multiply(qs.q).subtract(q.multiply(qs.p2)); q = q.multiply(qs.q); // simplification simplify(); } /** Subtract two quadratic surds. * @param qs1 first quadratic surd * @param qs2 second quadratic surd * @return a new quadratic surd which is the difference qs1 minus qs2 * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public static QuadraticSurd subtract(QuadraticSurd qs1, QuadraticSurd qs2) throws ArithmeticException { QuadraticSurd copy = new QuadraticSurd(qs1); copy.subtractFromSelf(qs2); return copy; } /** Multiply the instance by an integer. * @param l integer to multiply by */ public void multiplySelf(long l) { BigInteger bl = BigInteger.valueOf(l); p1 = p1.multiply(bl); p2 = p2.multiply(bl); simplify(); } /** Multiply a quadratic surd by an integer. * @param qs quadratic surd * @param l integer to multiply by */ public static QuadraticSurd multiply(QuadraticSurd qs, long l) { QuadraticSurd copy = new QuadraticSurd(qs); copy.multiplySelf(l); return copy; } /** Multiply the instance by a quadratic surd. * @param qs quadratic surd to multiply by * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public void multiplySelf(QuadraticSurd qs) throws ArithmeticException { // safety check chokeIfDifferentField(qs); // computation if (p2.signum() == 0) { d = qs.d; } BigInteger newP1 = p1.multiply(qs.p1).add(p2.multiply(qs.p2).multiply(d)); p2 = p1.multiply(qs.p2).add(p2.multiply(qs.p1)); p1 = newP1; q = q.multiply(qs.q); // simplification simplify(); } /** Multiply two quadratic surds. * @param qs1 first quadratic surd * @param qs2 second quadratic surd * @return a new quadratic surd which is the product of qs1 and qs2 * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public static QuadraticSurd multiply(QuadraticSurd qs1, QuadraticSurd qs2) throws ArithmeticException { QuadraticSurd copy = new QuadraticSurd(qs1); copy.multiplySelf(qs2); return copy; } /** Divide the instance by an integer. * @param l integer to divide by * @exception ArithmeticException if l is zero */ public void divideSelf(long l) throws ArithmeticException { if (l == 0l) { throw new ArithmeticException("divide by zero"); } q = q.multiply(BigInteger.valueOf(l)); simplify(); } /** Divide a quadratic surd by an integer * @param qs quadratic surd * @param l integer * @return a new quadratic surd which is the quotient of qs by l * @exception ArithmeticException if l is zero */ public static QuadraticSurd divide(QuadraticSurd qs, long l) throws ArithmeticException { QuadraticSurd copy = new QuadraticSurd(qs); copy.divideSelf(l); return copy; } /** Divide the instance by a quadratic surd. * @param qs quadratic surd to divide by * @exception ArithmeticException if qs is zero * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public void divideSelf(QuadraticSurd qs) throws ArithmeticException { multiplySelf(QuadraticSurd.invert(qs)); } /** Divide two quadratic surds. * @param qs1 first quadratic surd * @param qs2 second quadratic surd * @return a new quadratic surd which is the quotient of qs1 by qs2 * @exception ArithmeticException if qs2 is zero * @exception ArithmeticException if the two quadratic surds do not * belong to the same field (i.e. if they do not share the same * root) */ public static QuadraticSurd divide(QuadraticSurd qs1, QuadraticSurd qs2) { QuadraticSurd copy = new QuadraticSurd(qs1); copy.divideSelf(qs2); return copy; } /** Invert the instance. * Replace the instance by its inverse. * @exception ArithmeticException if the instance is zero */ public void invertSelf() throws ArithmeticException { // safety check if (isZero()) { throw new ArithmeticException("divide by zero"); } // computation BigInteger newP1 = q.multiply(p1); BigInteger newP2 = q.multiply(p2).negate(); q = p1.multiply(p1).subtract(d.multiply(p2).multiply(p2)); p1 = newP1; p2 = newP2; // simplification simplify(); } /** Invert a quadratic surd. * @param qs quadratic surd to invert * @return a new quadratic surd which is the inverse of qs * @exception ArithmeticException if qs is zero */ public static QuadraticSurd invert(QuadraticSurd qs) throws ArithmeticException { QuadraticSurd copy = new QuadraticSurd(qs); copy.invertSelf(); return copy; } /** Check if the instance is equal to 0. * @return true if the instance is equal to 0 */ public boolean isZero() { return (p1.signum() == 0) && (p2.signum() == 0); } /** Check if the instance is equal to 1. * @return true if the instance is equal to 1 */ public boolean isOne() { return (p1.compareTo(BigInteger.ONE) == 0) && (p2.signum() == 0) && (q.compareTo(BigInteger.ONE) == 0); } /** Check if the number is integer. * @return true if the number is an integer */ public boolean isInteger() { return (p2.signum() == 0) && (q.compareTo(BigInteger.ONE) == 0); } /** Check if the instance holds a rational number. * @return true if the instance holds a rational number */ public boolean isRational() { return p2.signum() == 0; } /** Check if the instance is equal to another quadratic surd. * Equality here is having the same value. * @return true if the object is a quadratic surd which has the * same value as the instance */ public boolean equals(Object o) { if (o instanceof QuadraticSurd) { QuadraticSurd qs = (QuadraticSurd ) o; return (p1.compareTo(qs.p1) == 0) && (p2.compareTo(qs.p2) == 0) && (d.compareTo(qs.d) == 0) && (q.compareTo(qs.q) == 0); } else { return false; } } /** Returns a hash code value for the object. * The hash code value is computed from the reduced coefficents, * hence equal quadratic surds have the same hash code, as required * by the method specification. * @return a hash code value for this object. */ public int hashCode() { return (int)((p1.hashCode() << 12) ^ (p2.hashCode() << 8) ^ (d.hashCode() << 4) ^ q.hashCode()); } /** Simplify a quadratic surd. * Simplification involves normalizing the signs, removing small * square factors from the root and removing common factors. */ private void simplify() { // handle specific case if (isZero()) { d = BigInteger.ZERO; q = BigInteger.ONE; return; } // normalize signs if (q.signum() < 0) { p1 = p1.negate(); p2 = p2.negate(); q = q.negate(); } // try to remove exact square terms from d // using the primes smaller than 5000 int k = 0; long squaredPrime; do { squaredPrime = primes[k] * primes[k]; if (d.remainder(BigInteger.valueOf(squaredPrime)).signum() == 0) { d = d.divide(BigInteger.valueOf(squaredPrime)); p2 = p2.multiply(BigInteger.valueOf(primes[k])); } else { ++k; } } while ((k < primes.length) && (d.compareTo(BigInteger.valueOf(squaredPrime)) >= 0)); // remove common factors BigInteger gcd = q.gcd(p1.gcd(p2)); if (gcd.compareTo(BigInteger.ONE) > 0) { p1 = p1.divide(gcd); p2 = p2.divide(gcd); q = q.divide(gcd); } } /** Get the numerator of the rational part. *

If the instance is a number of the form: *

   *         p1 + p2 sqrt (d)
   *   z =  ------------------
   *               q
   * 
* then this method returns p1

* @return numerator of the rational part */ public BigInteger getRationalNumerator() { return p1; } /** Get the coefficient of the irrational part. *

If the instance is a number of the form: *

   *         p1 + p2 sqrt (d)
   *   z =  ------------------
   *               q
   * 
* then this method returns p2

* @return coefficient of the irrational part */ public BigInteger getRootCoefficient() { return p2; } /** Get the root element of the irrational part. *

If the instance is a number of the form: *

   *         p1 + p2 sqrt (d)
   *   z =  ------------------
   *               q
   * 
* then this method returns d

* @return root element of the irrational part */ public BigInteger getRootElement() { return d; } /** Get the denominator. *

If the instance is a number of the form: *

   *         p1 + p2 sqrt (d)
   *   z =  ------------------
   *               q
   * 
* then this method returns q

* @return denominator */ public BigInteger getDenominator() { return q; } /** Returns the value of the underlying number as a double. * @return the numeric value represented by this object after * conversion to type double. */ public double doubleValue() { if (p2.signum() == 0) { return p1.doubleValue() / q.doubleValue(); } else { return (p1.doubleValue() + p2.doubleValue() * Math.sqrt(d.doubleValue())) / q.doubleValue(); } } /** Returns the value of the underlying number as a BigDecimal. * @param scale scale of the BigDecimal to return * @return the numeric value represented by this object after * conversion to type BigDecimal. */ public BigDecimal bigDecimalValue(int scale) { if (p2.signum() == 0) { return new BigDecimal(p1).divide(new BigDecimal(q), scale, BigDecimal.ROUND_HALF_EVEN); } else { // compute sqrt(d) BigDecimal s = new BigDecimal(Math.sqrt(d.doubleValue())); BigDecimal bdD = new BigDecimal(d); s = s.setScale(scale, BigDecimal.ROUND_HALF_EVEN); BigDecimal oldS; do { oldS = s; BigDecimal s2 = s.multiply(s); BigDecimal num = s.multiply(s2.add(BigDecimal.valueOf(3l).multiply(bdD))); BigDecimal den = s2.multiply(BigDecimal.valueOf(3l)).add(bdD); s = num.divide(den, scale, BigDecimal.ROUND_HALF_EVEN); } while (s.subtract(oldS).abs().signum() != 0); // compute the quadratic surd value BigDecimal a = new BigDecimal(p1).add(new BigDecimal(p2).multiply(s)); return a.divide(new BigDecimal(q), scale, BigDecimal.ROUND_HALF_EVEN); } } /** Returns a string representation of the underlying number. * @return a string representation of the underlying number */ public String toString() { StringBuffer sb = new StringBuffer(); if ((p1.signum() == 0) && (p2.signum() == 0)) { return "0"; } if (p1.signum() != 0) { sb.append(p1); if (p2.signum() != 0) { sb.append((p2.signum() < 0) ? " -" : " +"); if (p2.abs().compareTo(BigInteger.ONE) != 0) { sb.append(' '); sb.append(p2.abs()); } sb.append(" sqrt("); sb.append(d); sb.append(')'); } } else { if (p2.signum() != 0) { sb.append((p2.signum() < 0) ? '-' : '+'); if (p2.abs().compareTo(BigInteger.ONE) != 0) { sb.append(' '); sb.append(p2.abs()); } sb.append(" sqrt("); sb.append(d); sb.append(')'); } } if (q.compareTo(BigInteger.ONE) != 0) { if (sb.indexOf(" ") > 0) { sb.insert(0, '('); sb.append(')'); } sb.append(" / "); sb.append(q); } return sb.toString(); } /** Rational numerator. */ private BigInteger p1; /** Root coefficient. */ private BigInteger p2; /** Root element. */ private BigInteger d; /** Denominator. */ private BigInteger q; /** Non trivial primes (i.e. 1 is not included) smaller than 5000. */ private static long[] primes = { 2l, 3l, 5l, 7l, 11l, 13l, 17l, 19l, 23l, 29l, 31l, 37l, 41l, 43l, 47l, 53l, 59l, 61l, 67l, 71l, 73l, 79l, 83l, 89l, 97l, 101l, 103l, 107l, 109l, 113l, 127l, 131l, 137l, 139l, 149l, 151l, 157l, 163l, 167l, 173l, 179l, 181l, 191l, 193l, 197l, 199l, 211l, 223l, 227l, 229l, 233l, 239l, 241l, 251l, 257l, 263l, 269l, 271l, 277l, 281l, 283l, 293l, 307l, 311l, 313l, 317l, 331l, 337l, 347l, 349l, 353l, 359l, 367l, 373l, 379l, 383l, 389l, 397l, 401l, 409l, 419l, 421l, 431l, 433l, 439l, 443l, 449l, 457l, 461l, 463l, 467l, 479l, 487l, 491l, 499l, 503l, 509l, 521l, 523l, 541l, 547l, 557l, 563l, 569l, 571l, 577l, 587l, 593l, 599l, 601l, 607l, 613l, 617l, 619l, 631l, 641l, 643l, 647l, 653l, 659l, 661l, 673l, 677l, 683l, 691l, 701l, 709l, 719l, 727l, 733l, 739l, 743l, 751l, 757l, 761l, 769l, 773l, 787l, 797l, 809l, 811l, 821l, 823l, 827l, 829l, 839l, 853l, 857l, 859l, 863l, 877l, 881l, 883l, 887l, 907l, 911l, 919l, 929l, 937l, 941l, 947l, 953l, 967l, 971l, 977l, 983l, 991l, 997l, 1009l, 1013l, 1019l, 1021l, 1031l, 1033l, 1039l, 1049l, 1051l, 1061l, 1063l, 1069l, 1087l, 1091l, 1093l, 1097l, 1103l, 1109l, 1117l, 1123l, 1129l, 1151l, 1153l, 1163l, 1171l, 1181l, 1187l, 1193l, 1201l, 1213l, 1217l, 1223l, 1229l, 1231l, 1237l, 1249l, 1259l, 1277l, 1279l, 1283l, 1289l, 1291l, 1297l, 1301l, 1303l, 1307l, 1319l, 1321l, 1327l, 1361l, 1367l, 1373l, 1381l, 1399l, 1409l, 1423l, 1427l, 1429l, 1433l, 1439l, 1447l, 1451l, 1453l, 1459l, 1471l, 1481l, 1483l, 1487l, 1489l, 1493l, 1499l, 1511l, 1523l, 1531l, 1543l, 1549l, 1553l, 1559l, 1567l, 1571l, 1579l, 1583l, 1597l, 1601l, 1607l, 1609l, 1613l, 1619l, 1621l, 1627l, 1637l, 1657l, 1663l, 1667l, 1669l, 1693l, 1697l, 1699l, 1709l, 1721l, 1723l, 1733l, 1741l, 1747l, 1753l, 1759l, 1777l, 1783l, 1787l, 1789l, 1801l, 1811l, 1823l, 1831l, 1847l, 1861l, 1867l, 1871l, 1873l, 1877l, 1879l, 1889l, 1901l, 1907l, 1913l, 1931l, 1933l, 1949l, 1951l, 1973l, 1979l, 1987l, 1993l, 1997l, 1999l, 2003l, 2011l, 2017l, 2027l, 2029l, 2039l, 2053l, 2063l, 2069l, 2081l, 2083l, 2087l, 2089l, 2099l, 2111l, 2113l, 2129l, 2131l, 2137l, 2141l, 2143l, 2153l, 2161l, 2179l, 2203l, 2207l, 2213l, 2221l, 2237l, 2239l, 2243l, 2251l, 2267l, 2269l, 2273l, 2281l, 2287l, 2293l, 2297l, 2309l, 2311l, 2333l, 2339l, 2341l, 2347l, 2351l, 2357l, 2371l, 2377l, 2381l, 2383l, 2389l, 2393l, 2399l, 2411l, 2417l, 2423l, 2437l, 2441l, 2447l, 2459l, 2467l, 2473l, 2477l, 2503l, 2521l, 2531l, 2539l, 2543l, 2549l, 2551l, 2557l, 2579l, 2591l, 2593l, 2609l, 2617l, 2621l, 2633l, 2647l, 2657l, 2659l, 2663l, 2671l, 2677l, 2683l, 2687l, 2689l, 2693l, 2699l, 2707l, 2711l, 2713l, 2719l, 2729l, 2731l, 2741l, 2749l, 2753l, 2767l, 2777l, 2789l, 2791l, 2797l, 2801l, 2803l, 2819l, 2833l, 2837l, 2843l, 2851l, 2857l, 2861l, 2879l, 2887l, 2897l, 2903l, 2909l, 2917l, 2927l, 2939l, 2953l, 2957l, 2963l, 2969l, 2971l, 2999l, 3001l, 3011l, 3019l, 3023l, 3037l, 3041l, 3049l, 3061l, 3067l, 3079l, 3083l, 3089l, 3109l, 3119l, 3121l, 3137l, 3163l, 3167l, 3169l, 3181l, 3187l, 3191l, 3203l, 3209l, 3217l, 3221l, 3229l, 3251l, 3253l, 3257l, 3259l, 3271l, 3299l, 3301l, 3307l, 3313l, 3319l, 3323l, 3329l, 3331l, 3343l, 3347l, 3359l, 3361l, 3371l, 3373l, 3389l, 3391l, 3407l, 3413l, 3433l, 3449l, 3457l, 3461l, 3463l, 3467l, 3469l, 3491l, 3499l, 3511l, 3517l, 3527l, 3529l, 3533l, 3539l, 3541l, 3547l, 3557l, 3559l, 3571l, 3581l, 3583l, 3593l, 3607l, 3613l, 3617l, 3623l, 3631l, 3637l, 3643l, 3659l, 3671l, 3673l, 3677l, 3691l, 3697l, 3701l, 3709l, 3719l, 3727l, 3733l, 3739l, 3761l, 3767l, 3769l, 3779l, 3793l, 3797l, 3803l, 3821l, 3823l, 3833l, 3847l, 3851l, 3853l, 3863l, 3877l, 3881l, 3889l, 3907l, 3911l, 3917l, 3919l, 3923l, 3929l, 3931l, 3943l, 3947l, 3967l, 3989l, 4001l, 4003l, 4007l, 4013l, 4019l, 4021l, 4027l, 4049l, 4051l, 4057l, 4073l, 4079l, 4091l, 4093l, 4099l, 4111l, 4127l, 4129l, 4133l, 4139l, 4153l, 4157l, 4159l, 4177l, 4201l, 4211l, 4217l, 4219l, 4229l, 4231l, 4241l, 4243l, 4253l, 4259l, 4261l, 4271l, 4273l, 4283l, 4289l, 4297l, 4327l, 4337l, 4339l, 4349l, 4357l, 4363l, 4373l, 4391l, 4397l, 4409l, 4421l, 4423l, 4441l, 4447l, 4451l, 4457l, 4463l, 4481l, 4483l, 4493l, 4507l, 4513l, 4517l, 4519l, 4523l, 4547l, 4549l, 4561l, 4567l, 4583l, 4591l, 4597l, 4603l, 4621l, 4637l, 4639l, 4643l, 4649l, 4651l, 4657l, 4663l, 4673l, 4679l, 4691l, 4703l, 4721l, 4723l, 4729l, 4733l, 4751l, 4759l, 4783l, 4787l, 4789l, 4793l, 4799l, 4801l, 4813l, 4817l, 4831l, 4861l, 4871l, 4877l, 4889l, 4903l, 4909l, 4919l, 4931l, 4933l, 4937l, 4943l, 4951l, 4957l, 4967l, 4969l, 4973l, 4987l, 4993l, 4999l }; }

Ads help maintain this website.