1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Elena Semukhina
19 */
20
21package org.apache.harmony.tests.java.math;
22
23import junit.framework.TestCase;
24import java.math.BigInteger;
25
26/**
27 * Class:   java.math.BigInteger
28 * Methods: modPow, modInverse, and gcd
29 */
30public class BigIntegerModPowTest extends TestCase {
31	/**
32	 * modPow: non-positive modulus
33	 */
34	public void testModPowException() {
35		byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
36		byte eBytes[] = {1, 2, 3, 4, 5};
37		byte mBytes[] = {1, 2, 3};
38		int aSign = 1;
39		int eSign = 1;
40		int mSign = -1;
41		BigInteger aNumber = new BigInteger(aSign, aBytes);
42		BigInteger exp = new BigInteger(eSign, eBytes);
43		BigInteger modulus = new BigInteger(mSign, mBytes);
44		try {
45			aNumber.modPow(exp, modulus);
46			fail("ArithmeticException has not been caught");
47		} catch (ArithmeticException e) {
48		}
49
50        try {
51            BigInteger.ZERO.modPow(new BigInteger("-1"), new BigInteger("10"));
52            fail("ArithmeticException has not been caught");
53        } catch (ArithmeticException e) {
54            // expected
55        }
56	}
57
58	/**
59	 * modPow: positive exponent
60	 */
61	public void testModPowPosExp() {
62		byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
63		byte eBytes[] = {27, -15, 65, 39};
64		byte mBytes[] = {-128, 2, 3, 4, 5};
65		int aSign = 1;
66		int eSign = 1;
67		int mSign = 1;
68		byte rBytes[] = {113, 100, -84, -28, -85};
69		BigInteger aNumber = new BigInteger(aSign, aBytes);
70		BigInteger exp = 	 new BigInteger(eSign, eBytes);
71		BigInteger modulus = new BigInteger(mSign, mBytes);
72		BigInteger result = aNumber.modPow(exp, modulus);
73		byte resBytes[] = new byte[rBytes.length];
74		resBytes = result.toByteArray();
75		for(int i = 0; i < resBytes.length; i++) {
76			assertTrue(resBytes[i] == rBytes[i]);
77		}
78		assertEquals("incorrect sign", 1, result.signum());
79	}
80
81	/**
82	 * modPow: negative exponent
83	 */
84	public void testModPowNegExp() {
85		byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
86		byte eBytes[] = {27, -15, 65, 39};
87		byte mBytes[] = {-128, 2, 3, 4, 5};
88		int aSign = 1;
89		int eSign = -1;
90		int mSign = 1;
91		byte rBytes[] = {12, 118, 46, 86, 92};
92		BigInteger aNumber = new BigInteger(aSign, aBytes);
93		BigInteger exp = 	 new BigInteger(eSign, eBytes);
94		BigInteger modulus = new BigInteger(mSign, mBytes);
95		BigInteger result = aNumber.modPow(exp, modulus);
96		byte resBytes[] = new byte[rBytes.length];
97		resBytes = result.toByteArray();
98		for(int i = 0; i < resBytes.length; i++) {
99			assertTrue(resBytes[i] == rBytes[i]);
100		}
101		assertEquals("incorrect sign", 1, result.signum());
102	}
103
104    public void testModPowZeroExp() {
105        BigInteger exp = new BigInteger("0");
106        BigInteger[] base = new BigInteger[] {new BigInteger("-1"), new BigInteger("0"), new BigInteger("1")};
107        BigInteger[] mod = new BigInteger[] {new BigInteger("2"), new BigInteger("10"), new BigInteger("2147483648")};
108
109        for (int i = 0; i < base.length; ++i) {
110            for (int j = 0; j < mod.length; ++j) {
111                assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
112                        + ") should be " + BigInteger.ONE, BigInteger.ONE,
113                        base[i].modPow(exp, mod[j]));
114            }
115        }
116
117        mod = new BigInteger[] {new BigInteger("1")};
118        for (int i = 0; i < base.length; ++i) {
119            for (int j = 0; j < mod.length; ++j) {
120                assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
121                        + ") should be " + BigInteger.ZERO, BigInteger.ZERO,
122                        base[i].modPow(exp, mod[j]));
123            }
124        }
125    }
126
127	/**
128	 * modInverse: non-positive modulus
129	 */
130	public void testmodInverseException() {
131		byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
132		byte mBytes[] = {1, 2, 3};
133		int aSign = 1;
134		int mSign = -1;
135		BigInteger aNumber = new BigInteger(aSign, aBytes);
136		BigInteger modulus = new BigInteger(mSign, mBytes);
137		try {
138			aNumber.modInverse(modulus);
139			fail("ArithmeticException has not been caught");
140		} catch (ArithmeticException e) {
141		}
142	}
143
144	/**
145	 * modInverse: non-invertible number
146	 */
147	public void testmodInverseNonInvertible() {
148		byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
149		byte mBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
150		int aSign = 1;
151		int mSign = 1;
152		BigInteger aNumber = new BigInteger(aSign, aBytes);
153		BigInteger modulus = new BigInteger(mSign, mBytes);
154		try {
155			aNumber.modInverse(modulus);
156			fail("ArithmeticException has not been caught");
157		} catch (ArithmeticException e) {
158		}
159	}
160
161	/**
162	 * modInverse: positive number
163	 */
164	public void testmodInversePos1() {
165		byte aBytes[] = {24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
166		byte mBytes[] = {122, 45, 36, 100, 122, 45};
167		int aSign = 1;
168		int mSign = 1;
169		byte rBytes[] = {47, 3, 96, 62, 87, 19};
170		BigInteger aNumber = new BigInteger(aSign, aBytes);
171		BigInteger modulus = new BigInteger(mSign, mBytes);
172		BigInteger result = aNumber.modInverse(modulus);
173		byte resBytes[] = new byte[rBytes.length];
174		resBytes = result.toByteArray();
175		for(int i = 0; i < resBytes.length; i++) {
176			assertTrue(resBytes[i] == rBytes[i]);
177		}
178		assertEquals("incorrect sign", 1, result.signum());
179	}
180
181	/**
182	 * modInverse: positive number (another case: a < 0)
183	 */
184	public void testmodInversePos2() {
185		byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
186		byte mBytes[] = {2, 122, 45, 36, 100};
187		int aSign = 1;
188		int mSign = 1;
189		byte rBytes[] = {1, -93, 40, 127, 73};
190		BigInteger aNumber = new BigInteger(aSign, aBytes);
191		BigInteger modulus = new BigInteger(mSign, mBytes);
192		BigInteger result = aNumber.modInverse(modulus);
193		byte resBytes[] = new byte[rBytes.length];
194		resBytes = result.toByteArray();
195		for(int i = 0; i < resBytes.length; i++) {
196			assertTrue(resBytes[i] == rBytes[i]);
197		}
198		assertEquals("incorrect sign", 1, result.signum());
199	}
200
201	/**
202	 * modInverse: negative number
203	 */
204	public void testmodInverseNeg1() {
205		byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
206		byte mBytes[] = {2, 122, 45, 36, 100};
207		int aSign = -1;
208		int mSign = 1;
209		byte rBytes[] = {0, -41, 4, -91, 27};
210		BigInteger aNumber = new BigInteger(aSign, aBytes);
211		BigInteger modulus = new BigInteger(mSign, mBytes);
212		BigInteger result = aNumber.modInverse(modulus);
213		byte resBytes[] = new byte[rBytes.length];
214		resBytes = result.toByteArray();
215		for(int i = 0; i < resBytes.length; i++) {
216			assertTrue(resBytes[i] == rBytes[i]);
217		}
218		assertEquals("incorrect sign", 1, result.signum());
219	}
220
221	/**
222	 * modInverse: negative number (another case: x < 0)
223	 */
224	public void testmodInverseNeg2() {
225		byte aBytes[] = {-15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
226		byte mBytes[] = {122, 2, 4, 122, 2, 4};
227		byte rBytes[] = {85, 47, 127, 4, -128, 45};
228		BigInteger aNumber = new BigInteger(aBytes);
229		BigInteger modulus = new BigInteger(mBytes);
230		BigInteger result = aNumber.modInverse(modulus);
231		byte resBytes[] = new byte[rBytes.length];
232		resBytes = result.toByteArray();
233		for(int i = 0; i < resBytes.length; i++) {
234			assertTrue(resBytes[i] == rBytes[i]);
235		}
236		assertEquals("incorrect sign", 1, result.signum());
237	}
238
239	/**
240	 * gcd: the second number is zero
241	 */
242	public void testGcdSecondZero() {
243		byte aBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
244		byte bBytes[] = {0};
245		int aSign = 1;
246		int bSign = 1;
247		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
248		BigInteger aNumber = new BigInteger(aSign, aBytes);
249		BigInteger bNumber = new BigInteger(bSign, bBytes);
250		BigInteger result = aNumber.gcd(bNumber);
251		byte resBytes[] = new byte[rBytes.length];
252		resBytes = result.toByteArray();
253		for(int i = 0; i < resBytes.length; i++) {
254			assertTrue(resBytes[i] == rBytes[i]);
255		}
256		assertEquals("incorrect sign", 1, result.signum());
257	}
258
259	/**
260	 * gcd: the first number is zero
261	 */
262	public void testGcdFirstZero() {
263		byte aBytes[] = {0};
264		byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
265		int aSign = 1;
266		int bSign = 1;
267		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
268		BigInteger aNumber = new BigInteger(aSign, aBytes);
269		BigInteger bNumber = new BigInteger(bSign, bBytes);
270		BigInteger result = aNumber.gcd(bNumber);
271		byte resBytes[] = new byte[rBytes.length];
272		resBytes = result.toByteArray();
273		for(int i = 0; i < resBytes.length; i++) {
274			assertTrue(resBytes[i] == rBytes[i]);
275		}
276		assertEquals("incorrect sign", 1, result.signum());
277	}
278
279	/**
280	 * gcd: the first number is ZERO
281	 */
282	public void testGcdFirstZERO() {
283		byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
284		int bSign = 1;
285		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
286		BigInteger aNumber = BigInteger.ZERO;
287		BigInteger bNumber = new BigInteger(bSign, bBytes);
288		BigInteger result = aNumber.gcd(bNumber);
289		byte resBytes[] = new byte[rBytes.length];
290		resBytes = result.toByteArray();
291		for(int i = 0; i < resBytes.length; i++) {
292			assertTrue(resBytes[i] == rBytes[i]);
293		}
294		assertEquals("incorrect sign", 1, result.signum());
295	}
296
297	/**
298	 * gcd: both numbers are zeros
299	 */
300	public void testGcdBothZeros() {
301		byte rBytes[] = {0};
302		BigInteger aNumber = new BigInteger("0");
303		BigInteger bNumber = BigInteger.valueOf(0L);
304		BigInteger result = aNumber.gcd(bNumber);
305		byte resBytes[] = result.toByteArray();
306		for(int i = 0; i < resBytes.length; i++) {
307			assertTrue(resBytes[i] == rBytes[i]);
308		}
309		assertEquals("incorrect sign", 0, result.signum());
310	}
311
312	/**
313	 * gcd: the first number is longer
314	 */
315	public void testGcdFirstLonger() {
316		byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
317		byte bBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
318		int aSign = 1;
319		int bSign = 1;
320		byte rBytes[] = {7};
321		BigInteger aNumber = new BigInteger(aSign, aBytes);
322		BigInteger bNumber = new BigInteger(bSign, bBytes);
323		BigInteger result = aNumber.gcd(bNumber);
324		byte resBytes[] = new byte[rBytes.length];
325		resBytes = result.toByteArray();
326		for(int i = 0; i < resBytes.length; i++) {
327			assertTrue(resBytes[i] == rBytes[i]);
328		}
329		assertEquals("incorrect sign", 1, result.signum());
330	}
331
332	/**
333	 * gcd: the second number is longer
334	 */
335	public void testGcdSecondLonger() {
336		byte aBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
337		byte bBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
338		int aSign = 1;
339		int bSign = 1;
340		byte rBytes[] = {7};
341		BigInteger aNumber = new BigInteger(aSign, aBytes);
342		BigInteger bNumber = new BigInteger(bSign, bBytes);
343		BigInteger result = aNumber.gcd(bNumber);
344		byte resBytes[] = new byte[rBytes.length];
345		resBytes = result.toByteArray();
346		for(int i = 0; i < resBytes.length; i++) {
347			assertTrue(resBytes[i] == rBytes[i]);
348		}
349		assertEquals("incorrect sign", 1, result.signum());
350	}
351}
352