123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679 |
- /* java.math.BigInteger -- Arbitary precision integers
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2010
- Free Software Foundation, Inc.
- This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- GNU Classpath is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
- package java.math;
- import gnu.classpath.Configuration;
- import gnu.java.lang.CPStringBuilder;
- import gnu.java.math.GMP;
- import gnu.java.math.MPN;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.util.Random;
- import java.util.logging.Logger;
- /**
- * Written using on-line Java Platform 1.2 API Specification, as well
- * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998) and
- * "Applied Cryptography, Second Edition" by Bruce Schneier (Wiley, 1996).
- *
- * Based primarily on IntNum.java BitOps.java by Per Bothner (per@bothner.com)
- * (found in Kawa 1.6.62).
- *
- * @author Warren Levy (warrenl@cygnus.com)
- * @date December 20, 1999.
- * @status believed complete and correct.
- */
- public class BigInteger extends Number implements Comparable<BigInteger>
- {
- private static final Logger log = Configuration.DEBUG ?
- Logger.getLogger(BigInteger.class.getName()) : null;
- /** All integers are stored in 2's-complement form.
- * If words == null, the ival is the value of this BigInteger.
- * Otherwise, the first ival elements of words make the value
- * of this BigInteger, stored in little-endian order, 2's-complement form. */
- private transient int ival;
- private transient int[] words;
- // Serialization fields.
- // the first three, although not used in the code, are present for
- // compatibility with older RI versions of this class. DO NOT REMOVE.
- private int bitCount = -1;
- private int bitLength = -1;
- private int lowestSetBit = -2;
- private byte[] magnitude;
- private int signum;
- private static final long serialVersionUID = -8287574255936472291L;
- /** We pre-allocate integers in the range minFixNum..maxFixNum.
- * Note that we must at least preallocate 0, 1, and 10. */
- private static final int minFixNum = -100;
- private static final int maxFixNum = 1024;
- private static final int numFixNum = maxFixNum-minFixNum+1;
- private static final BigInteger[] smallFixNums;
- /** The alter-ego GMP instance for this. */
- private transient GMP mpz;
- private static final boolean USING_NATIVE = Configuration.WANT_NATIVE_BIG_INTEGER
- && initializeLibrary();
- static
- {
- if (USING_NATIVE)
- {
- smallFixNums = null;
- ZERO = valueOf(0L);
- ONE = valueOf(1L);
- TEN = valueOf(10L);
- }
- else
- {
- smallFixNums = new BigInteger[numFixNum];
- for (int i = numFixNum; --i >= 0; )
- smallFixNums[i] = new BigInteger(i + minFixNum);
- ZERO = smallFixNums[-minFixNum];
- ONE = smallFixNums[1 - minFixNum];
- TEN = smallFixNums[10 - minFixNum];
- }
- }
- /**
- * The constant zero as a BigInteger.
- * @since 1.2
- */
- public static final BigInteger ZERO;
- /**
- * The constant one as a BigInteger.
- * @since 1.2
- */
- public static final BigInteger ONE;
- /**
- * The constant ten as a BigInteger.
- * @since 1.5
- */
- public static final BigInteger TEN;
- /* Rounding modes: */
- private static final int FLOOR = 1;
- private static final int CEILING = 2;
- private static final int TRUNCATE = 3;
- private static final int ROUND = 4;
- /** When checking the probability of primes, it is most efficient to
- * first check the factoring of small primes, so we'll use this array.
- */
- private static final int[] primes =
- { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
- 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
- 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
- 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 };
- /** HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Table 4.4. */
- private static final int[] k =
- {100,150,200,250,300,350,400,500,600,800,1250, Integer.MAX_VALUE};
- private static final int[] t =
- { 27, 18, 15, 12, 9, 8, 7, 6, 5, 4, 3, 2};
- private BigInteger()
- {
- super();
- if (USING_NATIVE)
- mpz = new GMP();
- }
- /* Create a new (non-shared) BigInteger, and initialize to an int. */
- private BigInteger(int value)
- {
- super();
- ival = value;
- }
- public BigInteger(String s, int radix)
- {
- this();
- int len = s.length();
- int i, digit;
- boolean negative;
- byte[] bytes;
- char ch = s.charAt(0);
- if (ch == '-')
- {
- negative = true;
- i = 1;
- bytes = new byte[len - 1];
- }
- else
- {
- negative = false;
- i = 0;
- bytes = new byte[len];
- }
- int byte_len = 0;
- for ( ; i < len; i++)
- {
- ch = s.charAt(i);
- digit = Character.digit(ch, radix);
- if (digit < 0)
- throw new NumberFormatException("Invalid character at position #" + i);
- bytes[byte_len++] = (byte) digit;
- }
- if (USING_NATIVE)
- {
- bytes = null;
- if (mpz.fromString(s, radix) != 0)
- throw new NumberFormatException("String \"" + s
- + "\" is NOT a valid number in base "
- + radix);
- }
- else
- {
- BigInteger result;
- // Testing (len < MPN.chars_per_word(radix)) would be more accurate,
- // but slightly more expensive, for little practical gain.
- if (len <= 15 && radix <= 16)
- result = valueOf(Long.parseLong(s, radix));
- else
- result = valueOf(bytes, byte_len, negative, radix);
- this.ival = result.ival;
- this.words = result.words;
- }
- }
- public BigInteger(String val)
- {
- this(val, 10);
- }
- /* Create a new (non-shared) BigInteger, and initialize from a byte array. */
- public BigInteger(byte[] val)
- {
- this();
- if (val == null || val.length < 1)
- throw new NumberFormatException();
- if (USING_NATIVE)
- mpz.fromByteArray(val);
- else
- {
- words = byteArrayToIntArray(val, val[0] < 0 ? -1 : 0);
- BigInteger result = make(words, words.length);
- this.ival = result.ival;
- this.words = result.words;
- }
- }
- public BigInteger(int signum, byte[] magnitude)
- {
- this();
- if (magnitude == null || signum > 1 || signum < -1)
- throw new NumberFormatException();
- if (signum == 0)
- {
- int i;
- for (i = magnitude.length - 1; i >= 0 && magnitude[i] == 0; --i)
- ;
- if (i >= 0)
- throw new NumberFormatException();
- return;
- }
- if (USING_NATIVE)
- mpz.fromSignedMagnitude(magnitude, signum == -1);
- else
- {
- // Magnitude is always positive, so don't ever pass a sign of -1.
- words = byteArrayToIntArray(magnitude, 0);
- BigInteger result = make(words, words.length);
- this.ival = result.ival;
- this.words = result.words;
- if (signum < 0)
- setNegative();
- }
- }
- public BigInteger(int numBits, Random rnd)
- {
- this();
- if (numBits < 0)
- throw new IllegalArgumentException();
- init(numBits, rnd);
- }
- private void init(int numBits, Random rnd)
- {
- if (USING_NATIVE)
- {
- int length = (numBits + 7) / 8;
- byte[] magnitude = new byte[length];
- rnd.nextBytes(magnitude);
- int discardedBitCount = numBits % 8;
- if (discardedBitCount != 0)
- {
- discardedBitCount = 8 - discardedBitCount;
- magnitude[0] = (byte)((magnitude[0] & 0xFF) >>> discardedBitCount);
- }
- mpz.fromSignedMagnitude(magnitude, false);
- magnitude = null;
- return;
- }
- int highbits = numBits & 31;
- // minimum number of bytes to store the above number of bits
- int highBitByteCount = (highbits + 7) / 8;
- // number of bits to discard from the last byte
- int discardedBitCount = highbits % 8;
- if (discardedBitCount != 0)
- discardedBitCount = 8 - discardedBitCount;
- byte[] highBitBytes = new byte[highBitByteCount];
- if (highbits > 0)
- {
- rnd.nextBytes(highBitBytes);
- highbits = (highBitBytes[highBitByteCount - 1] & 0xFF) >>> discardedBitCount;
- for (int i = highBitByteCount - 2; i >= 0; i--)
- highbits = (highbits << 8) | (highBitBytes[i] & 0xFF);
- }
- int nwords = numBits / 32;
- while (highbits == 0 && nwords > 0)
- {
- highbits = rnd.nextInt();
- --nwords;
- }
- if (nwords == 0 && highbits >= 0)
- {
- ival = highbits;
- }
- else
- {
- ival = highbits < 0 ? nwords + 2 : nwords + 1;
- words = new int[ival];
- words[nwords] = highbits;
- while (--nwords >= 0)
- words[nwords] = rnd.nextInt();
- }
- }
- public BigInteger(int bitLength, int certainty, Random rnd)
- {
- this();
- BigInteger result = new BigInteger();
- while (true)
- {
- result.init(bitLength, rnd);
- result = result.setBit(bitLength - 1);
- if (result.isProbablePrime(certainty))
- break;
- }
- if (USING_NATIVE)
- mpz.fromBI(result.mpz);
- else
- {
- this.ival = result.ival;
- this.words = result.words;
- }
- }
- /**
- * Return a BigInteger that is bitLength bits long with a
- * probability < 2^-100 of being composite.
- *
- * @param bitLength length in bits of resulting number
- * @param rnd random number generator to use
- * @throws ArithmeticException if bitLength < 2
- * @since 1.4
- */
- public static BigInteger probablePrime(int bitLength, Random rnd)
- {
- if (bitLength < 2)
- throw new ArithmeticException();
- return new BigInteger(bitLength, 100, rnd);
- }
- /** Return a (possibly-shared) BigInteger with a given long value. */
- public static BigInteger valueOf(long val)
- {
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- result.mpz.fromLong(val);
- return result;
- }
- if (val >= minFixNum && val <= maxFixNum)
- return smallFixNums[(int) val - minFixNum];
- int i = (int) val;
- if ((long) i == val)
- return new BigInteger(i);
- BigInteger result = alloc(2);
- result.ival = 2;
- result.words[0] = i;
- result.words[1] = (int)(val >> 32);
- return result;
- }
- /**
- * @return <code>true</code> if the GMP-based native implementation library
- * was successfully loaded. Returns <code>false</code> otherwise.
- */
- private static boolean initializeLibrary()
- {
- boolean result;
- try
- {
- System.loadLibrary("javamath");
- GMP.natInitializeLibrary();
- result = true;
- }
- catch (Throwable x)
- {
- result = false;
- if (Configuration.DEBUG)
- {
- log.info("Unable to use native BigInteger: " + x);
- log.info("Will use a pure Java implementation instead");
- }
- }
- return result;
- }
- /** Make a canonicalized BigInteger from an array of words.
- * The array may be reused (without copying). */
- private static BigInteger make(int[] words, int len)
- {
- if (words == null)
- return valueOf(len);
- len = BigInteger.wordsNeeded(words, len);
- if (len <= 1)
- return len == 0 ? ZERO : valueOf(words[0]);
- BigInteger num = new BigInteger();
- num.words = words;
- num.ival = len;
- return num;
- }
- /** Convert a big-endian byte array to a little-endian array of words. */
- private static int[] byteArrayToIntArray(byte[] bytes, int sign)
- {
- // Determine number of words needed.
- int[] words = new int[bytes.length/4 + 1];
- int nwords = words.length;
- // Create a int out of modulo 4 high order bytes.
- int bptr = 0;
- int word = sign;
- for (int i = bytes.length % 4; i > 0; --i, bptr++)
- word = (word << 8) | (bytes[bptr] & 0xff);
- words[--nwords] = word;
- // Elements remaining in byte[] are a multiple of 4.
- while (nwords > 0)
- words[--nwords] = bytes[bptr++] << 24 |
- (bytes[bptr++] & 0xff) << 16 |
- (bytes[bptr++] & 0xff) << 8 |
- (bytes[bptr++] & 0xff);
- return words;
- }
- /** Allocate a new non-shared BigInteger.
- * @param nwords number of words to allocate
- */
- private static BigInteger alloc(int nwords)
- {
- BigInteger result = new BigInteger();
- if (nwords > 1)
- result.words = new int[nwords];
- return result;
- }
- /** Change words.length to nwords.
- * We allow words.length to be upto nwords+2 without reallocating.
- */
- private void realloc(int nwords)
- {
- if (nwords == 0)
- {
- if (words != null)
- {
- if (ival > 0)
- ival = words[0];
- words = null;
- }
- }
- else if (words == null
- || words.length < nwords
- || words.length > nwords + 2)
- {
- int[] new_words = new int [nwords];
- if (words == null)
- {
- new_words[0] = ival;
- ival = 1;
- }
- else
- {
- if (nwords < ival)
- ival = nwords;
- System.arraycopy(words, 0, new_words, 0, ival);
- }
- words = new_words;
- }
- }
- private boolean isNegative()
- {
- return (words == null ? ival : words[ival - 1]) < 0;
- }
- public int signum()
- {
- if (USING_NATIVE)
- return mpz.compare(ZERO.mpz);
- if (ival == 0 && words == null)
- return 0;
- int top = words == null ? ival : words[ival-1];
- return top < 0 ? -1 : 1;
- }
- private static int compareTo(BigInteger x, BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- return x.mpz.compare(y.mpz);
- }
- if (x.words == null && y.words == null)
- return x.ival < y.ival ? -1 : x.ival > y.ival ? 1 : 0;
- boolean x_negative = x.isNegative();
- boolean y_negative = y.isNegative();
- if (x_negative != y_negative)
- return x_negative ? -1 : 1;
- int x_len = x.words == null ? 1 : x.ival;
- int y_len = y.words == null ? 1 : y.ival;
- if (x_len != y_len)
- return (x_len > y_len) != x_negative ? 1 : -1;
- return MPN.cmp(x.words, y.words, x_len);
- }
- /** @since 1.2 */
- public int compareTo(BigInteger val)
- {
- return compareTo(this, val);
- }
- public BigInteger min(BigInteger val)
- {
- return compareTo(this, val) < 0 ? this : val;
- }
- public BigInteger max(BigInteger val)
- {
- return compareTo(this, val) > 0 ? this : val;
- }
- private boolean isZero()
- {
- return words == null && ival == 0;
- }
- private boolean isOne()
- {
- return words == null && ival == 1;
- }
- /** Calculate how many words are significant in words[0:len-1].
- * Returns the least value x such that x>0 && words[0:x-1]==words[0:len-1],
- * when words is viewed as a 2's complement integer.
- */
- private static int wordsNeeded(int[] words, int len)
- {
- int i = len;
- if (i > 0)
- {
- int word = words[--i];
- if (word == -1)
- {
- while (i > 0 && (word = words[i - 1]) < 0)
- {
- i--;
- if (word != -1) break;
- }
- }
- else
- {
- while (word == 0 && i > 0 && (word = words[i - 1]) >= 0) i--;
- }
- }
- return i + 1;
- }
- private BigInteger canonicalize()
- {
- if (words != null
- && (ival = BigInteger.wordsNeeded(words, ival)) <= 1)
- {
- if (ival == 1)
- ival = words[0];
- words = null;
- }
- if (words == null && ival >= minFixNum && ival <= maxFixNum)
- return smallFixNums[ival - minFixNum];
- return this;
- }
- /** Add two ints, yielding a BigInteger. */
- private static BigInteger add(int x, int y)
- {
- return valueOf((long) x + (long) y);
- }
- /** Add a BigInteger and an int, yielding a new BigInteger. */
- private static BigInteger add(BigInteger x, int y)
- {
- if (x.words == null)
- return BigInteger.add(x.ival, y);
- BigInteger result = new BigInteger(0);
- result.setAdd(x, y);
- return result.canonicalize();
- }
- /** Set this to the sum of x and y.
- * OK if x==this. */
- private void setAdd(BigInteger x, int y)
- {
- if (x.words == null)
- {
- set((long) x.ival + (long) y);
- return;
- }
- int len = x.ival;
- realloc(len + 1);
- long carry = y;
- for (int i = 0; i < len; i++)
- {
- carry += ((long) x.words[i] & 0xffffffffL);
- words[i] = (int) carry;
- carry >>= 32;
- }
- if (x.words[len - 1] < 0)
- carry--;
- words[len] = (int) carry;
- ival = wordsNeeded(words, len + 1);
- }
- /** Destructively add an int to this. */
- private void setAdd(int y)
- {
- setAdd(this, y);
- }
- /** Destructively set the value of this to a long. */
- private void set(long y)
- {
- int i = (int) y;
- if ((long) i == y)
- {
- ival = i;
- words = null;
- }
- else
- {
- realloc(2);
- words[0] = i;
- words[1] = (int) (y >> 32);
- ival = 2;
- }
- }
- /** Destructively set the value of this to the given words.
- * The words array is reused, not copied. */
- private void set(int[] words, int length)
- {
- this.ival = length;
- this.words = words;
- }
- /** Destructively set the value of this to that of y. */
- private void set(BigInteger y)
- {
- if (y.words == null)
- set(y.ival);
- else if (this != y)
- {
- realloc(y.ival);
- System.arraycopy(y.words, 0, words, 0, y.ival);
- ival = y.ival;
- }
- }
- /** Add two BigIntegers, yielding their sum as another BigInteger. */
- private static BigInteger add(BigInteger x, BigInteger y, int k)
- {
- if (x.words == null && y.words == null)
- return valueOf((long) k * (long) y.ival + (long) x.ival);
- if (k != 1)
- {
- if (k == -1)
- y = BigInteger.neg(y);
- else
- y = BigInteger.times(y, valueOf(k));
- }
- if (x.words == null)
- return BigInteger.add(y, x.ival);
- if (y.words == null)
- return BigInteger.add(x, y.ival);
- // Both are big
- if (y.ival > x.ival)
- { // Swap so x is longer then y.
- BigInteger tmp = x; x = y; y = tmp;
- }
- BigInteger result = alloc(x.ival + 1);
- int i = y.ival;
- long carry = MPN.add_n(result.words, x.words, y.words, i);
- long y_ext = y.words[i - 1] < 0 ? 0xffffffffL : 0;
- for (; i < x.ival; i++)
- {
- carry += ((long) x.words[i] & 0xffffffffL) + y_ext;
- result.words[i] = (int) carry;
- carry >>>= 32;
- }
- if (x.words[i - 1] < 0)
- y_ext--;
- result.words[i] = (int) (carry + y_ext);
- result.ival = i+1;
- return result.canonicalize();
- }
- public BigInteger add(BigInteger val)
- {
- if (USING_NATIVE)
- {
- int dummy = val.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.add(val.mpz, result.mpz);
- return result;
- }
- return add(this, val, 1);
- }
- public BigInteger subtract(BigInteger val)
- {
- if (USING_NATIVE)
- {
- int dummy = val.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.subtract(val.mpz, result.mpz);
- return result;
- }
- return add(this, val, -1);
- }
- private static BigInteger times(BigInteger x, int y)
- {
- if (y == 0)
- return ZERO;
- if (y == 1)
- return x;
- int[] xwords = x.words;
- int xlen = x.ival;
- if (xwords == null)
- return valueOf((long) xlen * (long) y);
- boolean negative;
- BigInteger result = BigInteger.alloc(xlen + 1);
- if (xwords[xlen - 1] < 0)
- {
- negative = true;
- negate(result.words, xwords, xlen);
- xwords = result.words;
- }
- else
- negative = false;
- if (y < 0)
- {
- negative = !negative;
- y = -y;
- }
- result.words[xlen] = MPN.mul_1(result.words, xwords, xlen, y);
- result.ival = xlen + 1;
- if (negative)
- result.setNegative();
- return result.canonicalize();
- }
- private static BigInteger times(BigInteger x, BigInteger y)
- {
- if (y.words == null)
- return times(x, y.ival);
- if (x.words == null)
- return times(y, x.ival);
- boolean negative = false;
- int[] xwords;
- int[] ywords;
- int xlen = x.ival;
- int ylen = y.ival;
- if (x.isNegative())
- {
- negative = true;
- xwords = new int[xlen];
- negate(xwords, x.words, xlen);
- }
- else
- {
- negative = false;
- xwords = x.words;
- }
- if (y.isNegative())
- {
- negative = !negative;
- ywords = new int[ylen];
- negate(ywords, y.words, ylen);
- }
- else
- ywords = y.words;
- // Swap if x is shorter then y.
- if (xlen < ylen)
- {
- int[] twords = xwords; xwords = ywords; ywords = twords;
- int tlen = xlen; xlen = ylen; ylen = tlen;
- }
- BigInteger result = BigInteger.alloc(xlen+ylen);
- MPN.mul(result.words, xwords, xlen, ywords, ylen);
- result.ival = xlen+ylen;
- if (negative)
- result.setNegative();
- return result.canonicalize();
- }
- public BigInteger multiply(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.multiply(y.mpz, result.mpz);
- return result;
- }
- return times(this, y);
- }
- private static void divide(long x, long y,
- BigInteger quotient, BigInteger remainder,
- int rounding_mode)
- {
- boolean xNegative, yNegative;
- if (x < 0)
- {
- xNegative = true;
- if (x == Long.MIN_VALUE)
- {
- divide(valueOf(x), valueOf(y),
- quotient, remainder, rounding_mode);
- return;
- }
- x = -x;
- }
- else
- xNegative = false;
- if (y < 0)
- {
- yNegative = true;
- if (y == Long.MIN_VALUE)
- {
- if (rounding_mode == TRUNCATE)
- { // x != Long.Min_VALUE implies abs(x) < abs(y)
- if (quotient != null)
- quotient.set(0);
- if (remainder != null)
- remainder.set(x);
- }
- else
- divide(valueOf(x), valueOf(y),
- quotient, remainder, rounding_mode);
- return;
- }
- y = -y;
- }
- else
- yNegative = false;
- long q = x / y;
- long r = x % y;
- boolean qNegative = xNegative ^ yNegative;
- boolean add_one = false;
- if (r != 0)
- {
- switch (rounding_mode)
- {
- case TRUNCATE:
- break;
- case CEILING:
- case FLOOR:
- if (qNegative == (rounding_mode == FLOOR))
- add_one = true;
- break;
- case ROUND:
- add_one = r > ((y - (q & 1)) >> 1);
- break;
- }
- }
- if (quotient != null)
- {
- if (add_one)
- q++;
- if (qNegative)
- q = -q;
- quotient.set(q);
- }
- if (remainder != null)
- {
- // The remainder is by definition: X-Q*Y
- if (add_one)
- {
- // Subtract the remainder from Y.
- r = y - r;
- // In this case, abs(Q*Y) > abs(X).
- // So sign(remainder) = -sign(X).
- xNegative = ! xNegative;
- }
- else
- {
- // If !add_one, then: abs(Q*Y) <= abs(X).
- // So sign(remainder) = sign(X).
- }
- if (xNegative)
- r = -r;
- remainder.set(r);
- }
- }
- /** Divide two integers, yielding quotient and remainder.
- * @param x the numerator in the division
- * @param y the denominator in the division
- * @param quotient is set to the quotient of the result (iff quotient!=null)
- * @param remainder is set to the remainder of the result
- * (iff remainder!=null)
- * @param rounding_mode one of FLOOR, CEILING, TRUNCATE, or ROUND.
- */
- private static void divide(BigInteger x, BigInteger y,
- BigInteger quotient, BigInteger remainder,
- int rounding_mode)
- {
- if ((x.words == null || x.ival <= 2)
- && (y.words == null || y.ival <= 2))
- {
- long x_l = x.longValue();
- long y_l = y.longValue();
- if (x_l != Long.MIN_VALUE && y_l != Long.MIN_VALUE)
- {
- divide(x_l, y_l, quotient, remainder, rounding_mode);
- return;
- }
- }
- boolean xNegative = x.isNegative();
- boolean yNegative = y.isNegative();
- boolean qNegative = xNegative ^ yNegative;
- int ylen = y.words == null ? 1 : y.ival;
- int[] ywords = new int[ylen];
- y.getAbsolute(ywords);
- while (ylen > 1 && ywords[ylen - 1] == 0) ylen--;
- int xlen = x.words == null ? 1 : x.ival;
- int[] xwords = new int[xlen+2];
- x.getAbsolute(xwords);
- while (xlen > 1 && xwords[xlen-1] == 0) xlen--;
- int qlen, rlen;
- int cmpval = MPN.cmp(xwords, xlen, ywords, ylen);
- if (cmpval < 0) // abs(x) < abs(y)
- { // quotient = 0; remainder = num.
- int[] rwords = xwords; xwords = ywords; ywords = rwords;
- rlen = xlen; qlen = 1; xwords[0] = 0;
- }
- else if (cmpval == 0) // abs(x) == abs(y)
- {
- xwords[0] = 1; qlen = 1; // quotient = 1
- ywords[0] = 0; rlen = 1; // remainder = 0;
- }
- else if (ylen == 1)
- {
- qlen = xlen;
- // Need to leave room for a word of leading zeros if dividing by 1
- // and the dividend has the high bit set. It might be safe to
- // increment qlen in all cases, but it certainly is only necessary
- // in the following case.
- if (ywords[0] == 1 && xwords[xlen-1] < 0)
- qlen++;
- rlen = 1;
- ywords[0] = MPN.divmod_1(xwords, xwords, xlen, ywords[0]);
- }
- else // abs(x) > abs(y)
- {
- // Normalize the denominator, i.e. make its most significant bit set by
- // shifting it normalization_steps bits to the left. Also shift the
- // numerator the same number of steps (to keep the quotient the same!).
- int nshift = MPN.count_leading_zeros(ywords[ylen - 1]);
- if (nshift != 0)
- {
- // Shift up the denominator setting the most significant bit of
- // the most significant word.
- MPN.lshift(ywords, 0, ywords, ylen, nshift);
- // Shift up the numerator, possibly introducing a new most
- // significant word.
- int x_high = MPN.lshift(xwords, 0, xwords, xlen, nshift);
- xwords[xlen++] = x_high;
- }
- if (xlen == ylen)
- xwords[xlen++] = 0;
- MPN.divide(xwords, xlen, ywords, ylen);
- rlen = ylen;
- MPN.rshift0 (ywords, xwords, 0, rlen, nshift);
- qlen = xlen + 1 - ylen;
- if (quotient != null)
- {
- for (int i = 0; i < qlen; i++)
- xwords[i] = xwords[i+ylen];
- }
- }
- if (ywords[rlen-1] < 0)
- {
- ywords[rlen] = 0;
- rlen++;
- }
- // Now the quotient is in xwords, and the remainder is in ywords.
- boolean add_one = false;
- if (rlen > 1 || ywords[0] != 0)
- { // Non-zero remainder i.e. in-exact quotient.
- switch (rounding_mode)
- {
- case TRUNCATE:
- break;
- case CEILING:
- case FLOOR:
- if (qNegative == (rounding_mode == FLOOR))
- add_one = true;
- break;
- case ROUND:
- // int cmp = compareTo(remainder<<1, abs(y));
- BigInteger tmp = remainder == null ? new BigInteger() : remainder;
- tmp.set(ywords, rlen);
- tmp = shift(tmp, 1);
- if (yNegative)
- tmp.setNegative();
- int cmp = compareTo(tmp, y);
- // Now cmp == compareTo(sign(y)*(remainder<<1), y)
- if (yNegative)
- cmp = -cmp;
- add_one = (cmp == 1) || (cmp == 0 && (xwords[0]&1) != 0);
- }
- }
- if (quotient != null)
- {
- quotient.set(xwords, qlen);
- if (qNegative)
- {
- if (add_one) // -(quotient + 1) == ~(quotient)
- quotient.setInvert();
- else
- quotient.setNegative();
- }
- else if (add_one)
- quotient.setAdd(1);
- }
- if (remainder != null)
- {
- // The remainder is by definition: X-Q*Y
- remainder.set(ywords, rlen);
- if (add_one)
- {
- // Subtract the remainder from Y:
- // abs(R) = abs(Y) - abs(orig_rem) = -(abs(orig_rem) - abs(Y)).
- BigInteger tmp;
- if (y.words == null)
- {
- tmp = remainder;
- tmp.set(yNegative ? ywords[0] + y.ival : ywords[0] - y.ival);
- }
- else
- tmp = BigInteger.add(remainder, y, yNegative ? 1 : -1);
- // Now tmp <= 0.
- // In this case, abs(Q) = 1 + floor(abs(X)/abs(Y)).
- // Hence, abs(Q*Y) > abs(X).
- // So sign(remainder) = -sign(X).
- if (xNegative)
- remainder.setNegative(tmp);
- else
- remainder.set(tmp);
- }
- else
- {
- // If !add_one, then: abs(Q*Y) <= abs(X).
- // So sign(remainder) = sign(X).
- if (xNegative)
- remainder.setNegative();
- }
- }
- }
- public BigInteger divide(BigInteger val)
- {
- if (USING_NATIVE)
- {
- if (val.compareTo(ZERO) == 0)
- throw new ArithmeticException("divisor is zero");
- BigInteger result = new BigInteger();
- mpz.quotient(val.mpz, result.mpz);
- return result;
- }
- if (val.isZero())
- throw new ArithmeticException("divisor is zero");
- BigInteger quot = new BigInteger();
- divide(this, val, quot, null, TRUNCATE);
- return quot.canonicalize();
- }
- public BigInteger remainder(BigInteger val)
- {
- if (USING_NATIVE)
- {
- if (val.compareTo(ZERO) == 0)
- throw new ArithmeticException("divisor is zero");
- BigInteger result = new BigInteger();
- mpz.remainder(val.mpz, result.mpz);
- return result;
- }
- if (val.isZero())
- throw new ArithmeticException("divisor is zero");
- BigInteger rem = new BigInteger();
- divide(this, val, null, rem, TRUNCATE);
- return rem.canonicalize();
- }
- public BigInteger[] divideAndRemainder(BigInteger val)
- {
- if (USING_NATIVE)
- {
- if (val.compareTo(ZERO) == 0)
- throw new ArithmeticException("divisor is zero");
- BigInteger q = new BigInteger();
- BigInteger r = new BigInteger();
- mpz.quotientAndRemainder(val.mpz, q.mpz, r.mpz);
- return new BigInteger[] { q, r };
- }
- if (val.isZero())
- throw new ArithmeticException("divisor is zero");
- BigInteger[] result = new BigInteger[2];
- result[0] = new BigInteger();
- result[1] = new BigInteger();
- divide(this, val, result[0], result[1], TRUNCATE);
- result[0].canonicalize();
- result[1].canonicalize();
- return result;
- }
- public BigInteger mod(BigInteger m)
- {
- if (USING_NATIVE)
- {
- int dummy = m.signum; // force NPE check
- if (m.compareTo(ZERO) < 1)
- throw new ArithmeticException("non-positive modulus");
- BigInteger result = new BigInteger();
- mpz.modulo(m.mpz, result.mpz);
- return result;
- }
- if (m.isNegative() || m.isZero())
- throw new ArithmeticException("non-positive modulus");
- BigInteger rem = new BigInteger();
- divide(this, m, null, rem, FLOOR);
- return rem.canonicalize();
- }
- /** Calculate the integral power of a BigInteger.
- * @param exponent the exponent (must be non-negative)
- */
- public BigInteger pow(int exponent)
- {
- if (exponent <= 0)
- {
- if (exponent == 0)
- return ONE;
- throw new ArithmeticException("negative exponent");
- }
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.pow(exponent, result.mpz);
- return result;
- }
- if (isZero())
- return this;
- int plen = words == null ? 1 : ival; // Length of pow2.
- int blen = ((bitLength() * exponent) >> 5) + 2 * plen;
- boolean negative = isNegative() && (exponent & 1) != 0;
- int[] pow2 = new int [blen];
- int[] rwords = new int [blen];
- int[] work = new int [blen];
- getAbsolute(pow2); // pow2 = abs(this);
- int rlen = 1;
- rwords[0] = 1; // rwords = 1;
- for (;;) // for (i = 0; ; i++)
- {
- // pow2 == this**(2**i)
- // prod = this**(sum(j=0..i-1, (exponent>>j)&1))
- if ((exponent & 1) != 0)
- { // r *= pow2
- MPN.mul(work, pow2, plen, rwords, rlen);
- int[] temp = work; work = rwords; rwords = temp;
- rlen += plen;
- while (rwords[rlen - 1] == 0) rlen--;
- }
- exponent >>= 1;
- if (exponent == 0)
- break;
- // pow2 *= pow2;
- MPN.mul(work, pow2, plen, pow2, plen);
- int[] temp = work; work = pow2; pow2 = temp; // swap to avoid a copy
- plen *= 2;
- while (pow2[plen - 1] == 0) plen--;
- }
- if (rwords[rlen - 1] < 0)
- rlen++;
- if (negative)
- negate(rwords, rwords, rlen);
- return BigInteger.make(rwords, rlen);
- }
- private static int[] euclidInv(int a, int b, int prevDiv)
- {
- if (b == 0)
- throw new ArithmeticException("not invertible");
- if (b == 1)
- // Success: values are indeed invertible!
- // Bottom of the recursion reached; start unwinding.
- return new int[] { -prevDiv, 1 };
- int[] xy = euclidInv(b, a % b, a / b); // Recursion happens here.
- a = xy[0]; // use our local copy of 'a' as a work var
- xy[0] = a * -prevDiv + xy[1];
- xy[1] = a;
- return xy;
- }
- private static void euclidInv(BigInteger a, BigInteger b,
- BigInteger prevDiv, BigInteger[] xy)
- {
- if (b.isZero())
- throw new ArithmeticException("not invertible");
- if (b.isOne())
- {
- // Success: values are indeed invertible!
- // Bottom of the recursion reached; start unwinding.
- xy[0] = neg(prevDiv);
- xy[1] = ONE;
- return;
- }
- // Recursion happens in the following conditional!
- // If a just contains an int, then use integer math for the rest.
- if (a.words == null)
- {
- int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival);
- xy[0] = new BigInteger(xyInt[0]);
- xy[1] = new BigInteger(xyInt[1]);
- }
- else
- {
- BigInteger rem = new BigInteger();
- BigInteger quot = new BigInteger();
- divide(a, b, quot, rem, FLOOR);
- // quot and rem may not be in canonical form. ensure
- rem.canonicalize();
- quot.canonicalize();
- euclidInv(b, rem, quot, xy);
- }
- BigInteger t = xy[0];
- xy[0] = add(xy[1], times(t, prevDiv), -1);
- xy[1] = t;
- }
- public BigInteger modInverse(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- if (mpz.compare(ZERO.mpz) < 1)
- throw new ArithmeticException("non-positive modulo");
- BigInteger result = new BigInteger();
- mpz.modInverse(y.mpz, result.mpz);
- return result;
- }
- if (y.isNegative() || y.isZero())
- throw new ArithmeticException("non-positive modulo");
- // Degenerate cases.
- if (y.isOne())
- return ZERO;
- if (isOne())
- return ONE;
- // Use Euclid's algorithm as in gcd() but do this recursively
- // rather than in a loop so we can use the intermediate results as we
- // unwind from the recursion.
- // Used http://www.math.nmsu.edu/~crypto/EuclideanAlgo.html as reference.
- BigInteger result = new BigInteger();
- boolean swapped = false;
- if (y.words == null)
- {
- // The result is guaranteed to be less than the modulus, y (which is
- // an int), so simplify this by working with the int result of this
- // modulo y. Also, if this is negative, make it positive via modulo
- // math. Note that BigInteger.mod() must be used even if this is
- // already an int as the % operator would provide a negative result if
- // this is negative, BigInteger.mod() never returns negative values.
- int xval = (words != null || isNegative()) ? mod(y).ival : ival;
- int yval = y.ival;
- // Swap values so x > y.
- if (yval > xval)
- {
- int tmp = xval; xval = yval; yval = tmp;
- swapped = true;
- }
- // Normally, the result is in the 2nd element of the array, but
- // if originally x < y, then x and y were swapped and the result
- // is in the 1st element of the array.
- result.ival =
- euclidInv(yval, xval % yval, xval / yval)[swapped ? 0 : 1];
- // Result can't be negative, so make it positive by adding the
- // original modulus, y.ival (not the possibly "swapped" yval).
- if (result.ival < 0)
- result.ival += y.ival;
- }
- else
- {
- // As above, force this to be a positive value via modulo math.
- BigInteger x = isNegative() ? this.mod(y) : this;
- // Swap values so x > y.
- if (x.compareTo(y) < 0)
- {
- result = x; x = y; y = result; // use 'result' as a work var
- swapped = true;
- }
- // As above (for ints), result will be in the 2nd element unless
- // the original x and y were swapped.
- BigInteger rem = new BigInteger();
- BigInteger quot = new BigInteger();
- divide(x, y, quot, rem, FLOOR);
- // quot and rem may not be in canonical form. ensure
- rem.canonicalize();
- quot.canonicalize();
- BigInteger[] xy = new BigInteger[2];
- euclidInv(y, rem, quot, xy);
- result = swapped ? xy[0] : xy[1];
- // Result can't be negative, so make it positive by adding the
- // original modulus, y (which is now x if they were swapped).
- if (result.isNegative())
- result = add(result, swapped ? x : y, 1);
- }
- return result;
- }
- public BigInteger modPow(BigInteger exponent, BigInteger m)
- {
- if (USING_NATIVE)
- {
- int dummy = exponent.signum; // force NPE check
- if (m.mpz.compare(ZERO.mpz) < 1)
- throw new ArithmeticException("non-positive modulo");
- BigInteger result = new BigInteger();
- mpz.modPow(exponent.mpz, m.mpz, result.mpz);
- return result;
- }
- if (m.isNegative() || m.isZero())
- throw new ArithmeticException("non-positive modulo");
- if (exponent.isNegative())
- return modInverse(m).modPow(exponent.negate(), m);
- if (exponent.isOne())
- return mod(m);
- // To do this naively by first raising this to the power of exponent
- // and then performing modulo m would be extremely expensive, especially
- // for very large numbers. The solution is found in Number Theory
- // where a combination of partial powers and moduli can be done easily.
- //
- // We'll use the algorithm for Additive Chaining which can be found on
- // p. 244 of "Applied Cryptography, Second Edition" by Bruce Schneier.
- BigInteger s = ONE;
- BigInteger t = this;
- BigInteger u = exponent;
- while (!u.isZero())
- {
- if (u.and(ONE).isOne())
- s = times(s, t).mod(m);
- u = u.shiftRight(1);
- t = times(t, t).mod(m);
- }
- return s;
- }
- /** Calculate Greatest Common Divisor for non-negative ints. */
- private static int gcd(int a, int b)
- {
- // Euclid's algorithm, copied from libg++.
- int tmp;
- if (b > a)
- {
- tmp = a; a = b; b = tmp;
- }
- for(;;)
- {
- if (b == 0)
- return a;
- if (b == 1)
- return b;
- tmp = b;
- b = a % b;
- a = tmp;
- }
- }
- public BigInteger gcd(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.gcd(y.mpz, result.mpz);
- return result;
- }
- int xval = ival;
- int yval = y.ival;
- if (words == null)
- {
- if (xval == 0)
- return abs(y);
- if (y.words == null
- && xval != Integer.MIN_VALUE && yval != Integer.MIN_VALUE)
- {
- if (xval < 0)
- xval = -xval;
- if (yval < 0)
- yval = -yval;
- return valueOf(gcd(xval, yval));
- }
- xval = 1;
- }
- if (y.words == null)
- {
- if (yval == 0)
- return abs(this);
- yval = 1;
- }
- int len = (xval > yval ? xval : yval) + 1;
- int[] xwords = new int[len];
- int[] ywords = new int[len];
- getAbsolute(xwords);
- y.getAbsolute(ywords);
- len = MPN.gcd(xwords, ywords, len);
- BigInteger result = new BigInteger(0);
- result.ival = len;
- result.words = xwords;
- return result.canonicalize();
- }
- /**
- * <p>Returns <code>true</code> if this BigInteger is probably prime,
- * <code>false</code> if it's definitely composite. If <code>certainty</code>
- * is <code><= 0</code>, <code>true</code> is returned.</p>
- *
- * @param certainty a measure of the uncertainty that the caller is willing
- * to tolerate: if the call returns <code>true</code> the probability that
- * this BigInteger is prime exceeds <code>(1 - 1/2<sup>certainty</sup>)</code>.
- * The execution time of this method is proportional to the value of this
- * parameter.
- * @return <code>true</code> if this BigInteger is probably prime,
- * <code>false</code> if it's definitely composite.
- */
- public boolean isProbablePrime(int certainty)
- {
- if (certainty < 1)
- return true;
- if (USING_NATIVE)
- return mpz.testPrimality(certainty) != 0;
- /** We'll use the Rabin-Miller algorithm for doing a probabilistic
- * primality test. It is fast, easy and has faster decreasing odds of a
- * composite passing than with other tests. This means that this
- * method will actually have a probability much greater than the
- * 1 - .5^certainty specified in the JCL (p. 117), but I don't think
- * anyone will complain about better performance with greater certainty.
- *
- * The Rabin-Miller algorithm can be found on pp. 259-261 of "Applied
- * Cryptography, Second Edition" by Bruce Schneier.
- */
- // First rule out small prime factors
- BigInteger rem = new BigInteger();
- int i;
- for (i = 0; i < primes.length; i++)
- {
- if (words == null && ival == primes[i])
- return true;
- divide(this, smallFixNums[primes[i] - minFixNum], null, rem, TRUNCATE);
- if (rem.canonicalize().isZero())
- return false;
- }
- // Now perform the Rabin-Miller test.
- // Set b to the number of times 2 evenly divides (this - 1).
- // I.e. 2^b is the largest power of 2 that divides (this - 1).
- BigInteger pMinus1 = add(this, -1);
- int b = pMinus1.getLowestSetBit();
- // Set m such that this = 1 + 2^b * m.
- BigInteger m = pMinus1.divide(valueOf(2L).pow(b));
- // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note
- // 4.49 (controlling the error probability) gives the number of trials
- // for an error probability of 1/2**80, given the number of bits in the
- // number to test. we shall use these numbers as is if/when 'certainty'
- // is less or equal to 80, and twice as much if it's greater.
- int bits = this.bitLength();
- for (i = 0; i < k.length; i++)
- if (bits <= k[i])
- break;
- int trials = t[i];
- if (certainty > 80)
- trials *= 2;
- BigInteger z;
- for (int t = 0; t < trials; t++)
- {
- // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al.
- // Remark 4.28 states: "...A strategy that is sometimes employed
- // is to fix the bases a to be the first few primes instead of
- // choosing them at random.
- z = smallFixNums[primes[t] - minFixNum].modPow(m, this);
- if (z.isOne() || z.equals(pMinus1))
- continue; // Passes the test; may be prime.
- for (i = 0; i < b; )
- {
- if (z.isOne())
- return false;
- i++;
- if (z.equals(pMinus1))
- break; // Passes the test; may be prime.
- z = z.modPow(valueOf(2), this);
- }
- if (i == b && !z.equals(pMinus1))
- return false;
- }
- return true;
- }
- private void setInvert()
- {
- if (words == null)
- ival = ~ival;
- else
- {
- for (int i = ival; --i >= 0; )
- words[i] = ~words[i];
- }
- }
- private void setShiftLeft(BigInteger x, int count)
- {
- int[] xwords;
- int xlen;
- if (x.words == null)
- {
- if (count < 32)
- {
- set((long) x.ival << count);
- return;
- }
- xwords = new int[1];
- xwords[0] = x.ival;
- xlen = 1;
- }
- else
- {
- xwords = x.words;
- xlen = x.ival;
- }
- int word_count = count >> 5;
- count &= 31;
- int new_len = xlen + word_count;
- if (count == 0)
- {
- realloc(new_len);
- for (int i = xlen; --i >= 0; )
- words[i+word_count] = xwords[i];
- }
- else
- {
- new_len++;
- realloc(new_len);
- int shift_out = MPN.lshift(words, word_count, xwords, xlen, count);
- count = 32 - count;
- words[new_len-1] = (shift_out << count) >> count; // sign-extend.
- }
- ival = new_len;
- for (int i = word_count; --i >= 0; )
- words[i] = 0;
- }
- private void setShiftRight(BigInteger x, int count)
- {
- if (x.words == null)
- set(count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0);
- else if (count == 0)
- set(x);
- else
- {
- boolean neg = x.isNegative();
- int word_count = count >> 5;
- count &= 31;
- int d_len = x.ival - word_count;
- if (d_len <= 0)
- set(neg ? -1 : 0);
- else
- {
- if (words == null || words.length < d_len)
- realloc(d_len);
- MPN.rshift0 (words, x.words, word_count, d_len, count);
- ival = d_len;
- if (neg)
- words[d_len-1] |= -2 << (31 - count);
- }
- }
- }
- private void setShift(BigInteger x, int count)
- {
- if (count > 0)
- setShiftLeft(x, count);
- else
- setShiftRight(x, -count);
- }
- private static BigInteger shift(BigInteger x, int count)
- {
- if (x.words == null)
- {
- if (count <= 0)
- return valueOf(count > -32 ? x.ival >> (-count) : x.ival < 0 ? -1 : 0);
- if (count < 32)
- return valueOf((long) x.ival << count);
- }
- if (count == 0)
- return x;
- BigInteger result = new BigInteger(0);
- result.setShift(x, count);
- return result.canonicalize();
- }
- public BigInteger shiftLeft(int n)
- {
- if (n == 0)
- return this;
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- if (n < 0)
- mpz.shiftRight(-n, result.mpz);
- else
- mpz.shiftLeft(n, result.mpz);
- return result;
- }
- return shift(this, n);
- }
- public BigInteger shiftRight(int n)
- {
- if (n == 0)
- return this;
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- if (n < 0)
- mpz.shiftLeft(-n, result.mpz);
- else
- mpz.shiftRight(n, result.mpz);
- return result;
- }
- return shift(this, -n);
- }
- private void format(int radix, CPStringBuilder buffer)
- {
- if (words == null)
- buffer.append(Integer.toString(ival, radix));
- else if (ival <= 2)
- buffer.append(Long.toString(longValue(), radix));
- else
- {
- boolean neg = isNegative();
- int[] work;
- if (neg || radix != 16)
- {
- work = new int[ival];
- getAbsolute(work);
- }
- else
- work = words;
- int len = ival;
- if (radix == 16)
- {
- if (neg)
- buffer.append('-');
- int buf_start = buffer.length();
- for (int i = len; --i >= 0; )
- {
- int word = work[i];
- for (int j = 8; --j >= 0; )
- {
- int hex_digit = (word >> (4 * j)) & 0xF;
- // Suppress leading zeros:
- if (hex_digit > 0 || buffer.length() > buf_start)
- buffer.append(Character.forDigit(hex_digit, 16));
- }
- }
- }
- else
- {
- int i = buffer.length();
- for (;;)
- {
- int digit = MPN.divmod_1(work, work, len, radix);
- buffer.append(Character.forDigit(digit, radix));
- while (len > 0 && work[len-1] == 0) len--;
- if (len == 0)
- break;
- }
- if (neg)
- buffer.append('-');
- /* Reverse buffer. */
- int j = buffer.length() - 1;
- while (i < j)
- {
- char tmp = buffer.charAt(i);
- buffer.setCharAt(i, buffer.charAt(j));
- buffer.setCharAt(j, tmp);
- i++; j--;
- }
- }
- }
- }
- public String toString()
- {
- return toString(10);
- }
- public String toString(int radix)
- {
- if (USING_NATIVE)
- return mpz.toString(radix);
- if (words == null)
- return Integer.toString(ival, radix);
- if (ival <= 2)
- return Long.toString(longValue(), radix);
- int buf_size = ival * (MPN.chars_per_word(radix) + 1);
- CPStringBuilder buffer = new CPStringBuilder(buf_size);
- format(radix, buffer);
- return buffer.toString();
- }
- public int intValue()
- {
- if (USING_NATIVE)
- {
- int result = mpz.absIntValue();
- return mpz.compare(ZERO.mpz) < 0 ? - result : result;
- }
- if (words == null)
- return ival;
- return words[0];
- }
- public long longValue()
- {
- if (USING_NATIVE)
- {
- long result;
- result = (abs().shiftRight(32)).mpz.absIntValue();
- result <<= 32;
- result |= mpz.absIntValue() & 0xFFFFFFFFL;
- return this.compareTo(ZERO) < 0 ? - result : result;
- }
- if (words == null)
- return ival;
- if (ival == 1)
- return words[0];
- return ((long)words[1] << 32) + ((long)words[0] & 0xffffffffL);
- }
- public int hashCode()
- {
- // FIXME: May not match hashcode of JDK.
- if (USING_NATIVE)
- {
- // TODO: profile to decide whether to make it native
- byte[] bytes = this.toByteArray();
- int result = 0;
- for (int i = 0; i < bytes.length; i++)
- result ^= (bytes[i] & 0xFF) << (8 * (i % 4));
- return result;
- }
- return words == null ? ival : (words[0] + words[ival - 1]);
- }
- /* Assumes x and y are both canonicalized. */
- private static boolean equals(BigInteger x, BigInteger y)
- {
- if (USING_NATIVE)
- return x.mpz.compare(y.mpz) == 0;
- if (x.words == null && y.words == null)
- return x.ival == y.ival;
- if (x.words == null || y.words == null || x.ival != y.ival)
- return false;
- for (int i = x.ival; --i >= 0; )
- {
- if (x.words[i] != y.words[i])
- return false;
- }
- return true;
- }
- /* Assumes this and obj are both canonicalized. */
- public boolean equals(Object obj)
- {
- if (! (obj instanceof BigInteger))
- return false;
- return equals(this, (BigInteger) obj);
- }
- private static BigInteger valueOf(byte[] digits, int byte_len,
- boolean negative, int radix)
- {
- int chars_per_word = MPN.chars_per_word(radix);
- int[] words = new int[byte_len / chars_per_word + 1];
- int size = MPN.set_str(words, digits, byte_len, radix);
- if (size == 0)
- return ZERO;
- if (words[size-1] < 0)
- words[size++] = 0;
- if (negative)
- negate(words, words, size);
- return make(words, size);
- }
- public double doubleValue()
- {
- if (USING_NATIVE)
- return mpz.doubleValue();
- if (words == null)
- return (double) ival;
- if (ival <= 2)
- return (double) longValue();
- if (isNegative())
- return neg(this).roundToDouble(0, true, false);
- return roundToDouble(0, false, false);
- }
- public float floatValue()
- {
- return (float) doubleValue();
- }
- /** Return true if any of the lowest n bits are one.
- * (false if n is negative). */
- private boolean checkBits(int n)
- {
- if (n <= 0)
- return false;
- if (words == null)
- return n > 31 || ((ival & ((1 << n) - 1)) != 0);
- int i;
- for (i = 0; i < (n >> 5) ; i++)
- if (words[i] != 0)
- return true;
- return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0;
- }
- /** Convert a semi-processed BigInteger to double.
- * Number must be non-negative. Multiplies by a power of two, applies sign,
- * and converts to double, with the usual java rounding.
- * @param exp power of two, positive or negative, by which to multiply
- * @param neg true if negative
- * @param remainder true if the BigInteger is the result of a truncating
- * division that had non-zero remainder. To ensure proper rounding in
- * this case, the BigInteger must have at least 54 bits. */
- private double roundToDouble(int exp, boolean neg, boolean remainder)
- {
- // Compute length.
- int il = bitLength();
- // Exponent when normalized to have decimal point directly after
- // leading one. This is stored excess 1023 in the exponent bit field.
- exp += il - 1;
- // Gross underflow. If exp == -1075, we let the rounding
- // computation determine whether it is minval or 0 (which are just
- // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit
- // patterns).
- if (exp < -1075)
- return neg ? -0.0 : 0.0;
- // gross overflow
- if (exp > 1023)
- return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- // number of bits in mantissa, including the leading one.
- // 53 unless it's denormalized
- int ml = (exp >= -1022 ? 53 : 53 + exp + 1022);
- // Get top ml + 1 bits. The extra one is for rounding.
- long m;
- int excess_bits = il - (ml + 1);
- if (excess_bits > 0)
- m = ((words == null) ? ival >> excess_bits
- : MPN.rshift_long(words, ival, excess_bits));
- else
- m = longValue() << (- excess_bits);
- // Special rounding for maxval. If the number exceeds maxval by
- // any amount, even if it's less than half a step, it overflows.
- if (exp == 1023 && ((m >> 1) == (1L << 53) - 1))
- {
- if (remainder || checkBits(il - ml))
- return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- else
- return neg ? - Double.MAX_VALUE : Double.MAX_VALUE;
- }
- // Normal round-to-even rule: round up if the bit dropped is a one, and
- // the bit above it or any of the bits below it is a one.
- if ((m & 1) == 1
- && ((m & 2) == 2 || remainder || checkBits(excess_bits)))
- {
- m += 2;
- // Check if we overflowed the mantissa
- if ((m & (1L << 54)) != 0)
- {
- exp++;
- // renormalize
- m >>= 1;
- }
- // Check if a denormalized mantissa was just rounded up to a
- // normalized one.
- else if (ml == 52 && (m & (1L << 53)) != 0)
- exp++;
- }
- // Discard the rounding bit
- m >>= 1;
- long bits_sign = neg ? (1L << 63) : 0;
- exp += 1023;
- long bits_exp = (exp <= 0) ? 0 : ((long)exp) << 52;
- long bits_mant = m & ~(1L << 52);
- return Double.longBitsToDouble(bits_sign | bits_exp | bits_mant);
- }
- /** Copy the abolute value of this into an array of words.
- * Assumes words.length >= (this.words == null ? 1 : this.ival).
- * Result is zero-extended, but need not be a valid 2's complement number.
- */
- private void getAbsolute(int[] words)
- {
- int len;
- if (this.words == null)
- {
- len = 1;
- words[0] = this.ival;
- }
- else
- {
- len = this.ival;
- for (int i = len; --i >= 0; )
- words[i] = this.words[i];
- }
- if (words[len - 1] < 0)
- negate(words, words, len);
- for (int i = words.length; --i > len; )
- words[i] = 0;
- }
- /** Set dest[0:len-1] to the negation of src[0:len-1].
- * Return true if overflow (i.e. if src is -2**(32*len-1)).
- * Ok for src==dest. */
- private static boolean negate(int[] dest, int[] src, int len)
- {
- long carry = 1;
- boolean negative = src[len-1] < 0;
- for (int i = 0; i < len; i++)
- {
- carry += ((long) (~src[i]) & 0xffffffffL);
- dest[i] = (int) carry;
- carry >>= 32;
- }
- return (negative && dest[len-1] < 0);
- }
- /** Destructively set this to the negative of x.
- * It is OK if x==this.*/
- private void setNegative(BigInteger x)
- {
- int len = x.ival;
- if (x.words == null)
- {
- if (len == Integer.MIN_VALUE)
- set(- (long) len);
- else
- set(-len);
- return;
- }
- realloc(len + 1);
- if (negate(words, x.words, len))
- words[len++] = 0;
- ival = len;
- }
- /** Destructively negate this. */
- private void setNegative()
- {
- setNegative(this);
- }
- private static BigInteger abs(BigInteger x)
- {
- return x.isNegative() ? neg(x) : x;
- }
- public BigInteger abs()
- {
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.abs(result.mpz);
- return result;
- }
- return abs(this);
- }
- private static BigInteger neg(BigInteger x)
- {
- if (x.words == null && x.ival != Integer.MIN_VALUE)
- return valueOf(- x.ival);
- BigInteger result = new BigInteger(0);
- result.setNegative(x);
- return result.canonicalize();
- }
- public BigInteger negate()
- {
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.negate(result.mpz);
- return result;
- }
- return neg(this);
- }
- /** Calculates ceiling(log2(this < 0 ? -this : this+1))
- * See Common Lisp: the Language, 2nd ed, p. 361.
- */
- public int bitLength()
- {
- if (USING_NATIVE)
- return mpz.bitLength();
- if (words == null)
- return MPN.intLength(ival);
- return MPN.intLength(words, ival);
- }
- public byte[] toByteArray()
- {
- if (signum() == 0)
- return new byte[1];
- if (USING_NATIVE)
- {
- // the minimal number of bytes required to represent the MPI is function
- // of (a) its bit-length, and (b) its sign. only when this MPI is both
- // positive, and its bit-length is a multiple of 8 do we add one zero
- // bit for its sign. we do this so if we construct a new MPI from the
- // resulting byte array, we wouldn't mistake a positive number, whose
- // bit-length is a multiple of 8, for a similar-length negative one.
- int bits = bitLength();
- if (bits % 8 == 0 || this.signum() == 1)
- bits++;
- byte[] bytes = new byte[(bits + 7) / 8];
- mpz.toByteArray(bytes);
- return bytes;
- }
- // Determine number of bytes needed. The method bitlength returns
- // the size without the sign bit, so add one bit for that and then
- // add 7 more to emulate the ceil function using integer math.
- byte[] bytes = new byte[(bitLength() + 1 + 7) / 8];
- int nbytes = bytes.length;
- int wptr = 0;
- int word;
- // Deal with words array until one word or less is left to process.
- // If BigInteger is an int, then it is in ival and nbytes will be <= 4.
- while (nbytes > 4)
- {
- word = words[wptr++];
- for (int i = 4; i > 0; --i, word >>= 8)
- bytes[--nbytes] = (byte) word;
- }
- // Deal with the last few bytes. If BigInteger is an int, use ival.
- word = (words == null) ? ival : words[wptr];
- for ( ; nbytes > 0; word >>= 8)
- bytes[--nbytes] = (byte) word;
- return bytes;
- }
- /** Return the boolean opcode (for bitOp) for swapped operands.
- * I.e. bitOp(swappedOp(op), x, y) == bitOp(op, y, x).
- */
- private static int swappedOp(int op)
- {
- return
- "\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017"
- .charAt(op);
- }
- /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
- private static BigInteger bitOp(int op, BigInteger x, BigInteger y)
- {
- switch (op)
- {
- case 0: return ZERO;
- case 1: return x.and(y);
- case 3: return x;
- case 5: return y;
- case 15: return valueOf(-1);
- }
- BigInteger result = new BigInteger();
- setBitOp(result, op, x, y);
- return result.canonicalize();
- }
- /** Do one the the 16 possible bit-wise operations of two BigIntegers. */
- private static void setBitOp(BigInteger result, int op,
- BigInteger x, BigInteger y)
- {
- if ((y.words != null) && (x.words == null || x.ival < y.ival))
- {
- BigInteger temp = x; x = y; y = temp;
- op = swappedOp(op);
- }
- int xi;
- int yi;
- int xlen, ylen;
- if (y.words == null)
- {
- yi = y.ival;
- ylen = 1;
- }
- else
- {
- yi = y.words[0];
- ylen = y.ival;
- }
- if (x.words == null)
- {
- xi = x.ival;
- xlen = 1;
- }
- else
- {
- xi = x.words[0];
- xlen = x.ival;
- }
- if (xlen > 1)
- result.realloc(xlen);
- int[] w = result.words;
- int i = 0;
- // Code for how to handle the remainder of x.
- // 0: Truncate to length of y.
- // 1: Copy rest of x.
- // 2: Invert rest of x.
- int finish = 0;
- int ni;
- switch (op)
- {
- case 0: // clr
- ni = 0;
- break;
- case 1: // and
- for (;;)
- {
- ni = xi & yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi < 0) finish = 1;
- break;
- case 2: // andc2
- for (;;)
- {
- ni = xi & ~yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi >= 0) finish = 1;
- break;
- case 3: // copy x
- ni = xi;
- finish = 1; // Copy rest
- break;
- case 4: // andc1
- for (;;)
- {
- ni = ~xi & yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi < 0) finish = 2;
- break;
- case 5: // copy y
- for (;;)
- {
- ni = yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- break;
- case 6: // xor
- for (;;)
- {
- ni = xi ^ yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- finish = yi < 0 ? 2 : 1;
- break;
- case 7: // ior
- for (;;)
- {
- ni = xi | yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi >= 0) finish = 1;
- break;
- case 8: // nor
- for (;;)
- {
- ni = ~(xi | yi);
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi >= 0) finish = 2;
- break;
- case 9: // eqv [exclusive nor]
- for (;;)
- {
- ni = ~(xi ^ yi);
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- finish = yi >= 0 ? 2 : 1;
- break;
- case 10: // c2
- for (;;)
- {
- ni = ~yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- break;
- case 11: // orc2
- for (;;)
- {
- ni = xi | ~yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi < 0) finish = 1;
- break;
- case 12: // c1
- ni = ~xi;
- finish = 2;
- break;
- case 13: // orc1
- for (;;)
- {
- ni = ~xi | yi;
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi >= 0) finish = 2;
- break;
- case 14: // nand
- for (;;)
- {
- ni = ~(xi & yi);
- if (i+1 >= ylen) break;
- w[i++] = ni; xi = x.words[i]; yi = y.words[i];
- }
- if (yi < 0) finish = 2;
- break;
- default:
- case 15: // set
- ni = -1;
- break;
- }
- // Here i==ylen-1; w[0]..w[i-1] have the correct result;
- // and ni contains the correct result for w[i+1].
- if (i+1 == xlen)
- finish = 0;
- switch (finish)
- {
- case 0:
- if (i == 0 && w == null)
- {
- result.ival = ni;
- return;
- }
- w[i++] = ni;
- break;
- case 1: w[i] = ni; while (++i < xlen) w[i] = x.words[i]; break;
- case 2: w[i] = ni; while (++i < xlen) w[i] = ~x.words[i]; break;
- }
- result.ival = i;
- }
- /** Return the logical (bit-wise) "and" of a BigInteger and an int. */
- private static BigInteger and(BigInteger x, int y)
- {
- if (x.words == null)
- return valueOf(x.ival & y);
- if (y >= 0)
- return valueOf(x.words[0] & y);
- int len = x.ival;
- int[] words = new int[len];
- words[0] = x.words[0] & y;
- while (--len > 0)
- words[len] = x.words[len];
- return make(words, x.ival);
- }
- /** Return the logical (bit-wise) "and" of two BigIntegers. */
- public BigInteger and(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.and(y.mpz, result.mpz);
- return result;
- }
- if (y.words == null)
- return and(this, y.ival);
- else if (words == null)
- return and(y, ival);
- BigInteger x = this;
- if (ival < y.ival)
- {
- BigInteger temp = this; x = y; y = temp;
- }
- int i;
- int len = y.isNegative() ? x.ival : y.ival;
- int[] words = new int[len];
- for (i = 0; i < y.ival; i++)
- words[i] = x.words[i] & y.words[i];
- for ( ; i < len; i++)
- words[i] = x.words[i];
- return make(words, len);
- }
- /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */
- public BigInteger or(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.or(y.mpz, result.mpz);
- return result;
- }
- return bitOp(7, this, y);
- }
- /** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */
- public BigInteger xor(BigInteger y)
- {
- if (USING_NATIVE)
- {
- int dummy = y.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.xor(y.mpz, result.mpz);
- return result;
- }
- return bitOp(6, this, y);
- }
- /** Return the logical (bit-wise) negation of a BigInteger. */
- public BigInteger not()
- {
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.not(result.mpz);
- return result;
- }
- return bitOp(12, this, ZERO);
- }
- public BigInteger andNot(BigInteger val)
- {
- if (USING_NATIVE)
- {
- int dummy = val.signum; // force NPE check
- BigInteger result = new BigInteger();
- mpz.andNot(val.mpz, result.mpz);
- return result;
- }
- return and(val.not());
- }
- public BigInteger clearBit(int n)
- {
- if (n < 0)
- throw new ArithmeticException();
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.setBit(n, false, result.mpz);
- return result;
- }
- return and(ONE.shiftLeft(n).not());
- }
- public BigInteger setBit(int n)
- {
- if (n < 0)
- throw new ArithmeticException();
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.setBit(n, true, result.mpz);
- return result;
- }
- return or(ONE.shiftLeft(n));
- }
- public boolean testBit(int n)
- {
- if (n < 0)
- throw new ArithmeticException();
- if (USING_NATIVE)
- return mpz.testBit(n) != 0;
- return !and(ONE.shiftLeft(n)).isZero();
- }
- public BigInteger flipBit(int n)
- {
- if (n < 0)
- throw new ArithmeticException();
- if (USING_NATIVE)
- {
- BigInteger result = new BigInteger();
- mpz.flipBit(n, result.mpz);
- return result;
- }
- return xor(ONE.shiftLeft(n));
- }
- public int getLowestSetBit()
- {
- if (USING_NATIVE)
- return mpz.compare(ZERO.mpz) == 0 ? -1 : mpz.lowestSetBit();
- if (isZero())
- return -1;
- if (words == null)
- return MPN.findLowestBit(ival);
- else
- return MPN.findLowestBit(words);
- }
- // bit4count[I] is number of '1' bits in I.
- private static final byte[] bit4_count = { 0, 1, 1, 2, 1, 2, 2, 3,
- 1, 2, 2, 3, 2, 3, 3, 4};
- private static int bitCount(int i)
- {
- int count = 0;
- while (i != 0)
- {
- count += bit4_count[i & 15];
- i >>>= 4;
- }
- return count;
- }
- private static int bitCount(int[] x, int len)
- {
- int count = 0;
- while (--len >= 0)
- count += bitCount(x[len]);
- return count;
- }
- /** Count one bits in a BigInteger.
- * If argument is negative, count zero bits instead. */
- public int bitCount()
- {
- if (USING_NATIVE)
- return mpz.bitCount();
- int i, x_len;
- int[] x_words = words;
- if (x_words == null)
- {
- x_len = 1;
- i = bitCount(ival);
- }
- else
- {
- x_len = ival;
- i = bitCount(x_words, x_len);
- }
- return isNegative() ? x_len * 32 - i : i;
- }
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException
- {
- if (USING_NATIVE)
- {
- mpz = new GMP();
- s.defaultReadObject();
- if (signum != 0)
- mpz.fromByteArray(magnitude);
- // else it's zero and we need to do nothing
- }
- else
- {
- s.defaultReadObject();
- if (magnitude.length == 0 || signum == 0)
- {
- this.ival = 0;
- this.words = null;
- }
- else
- {
- words = byteArrayToIntArray(magnitude, signum < 0 ? -1 : 0);
- BigInteger result = make(words, words.length);
- this.ival = result.ival;
- this.words = result.words;
- }
- }
- }
- private void writeObject(ObjectOutputStream s)
- throws IOException, ClassNotFoundException
- {
- signum = signum();
- magnitude = signum == 0 ? new byte[0] : toByteArray();
- s.defaultWriteObject();
- magnitude = null; // not needed anymore
- }
- // inner class(es) ..........................................................
- }
|