package com.scytl.math;

import static com.scytl.math.BigIntegers.isNegative;
import static com.scytl.math.BigIntegers.isNonNegative;
import static com.scytl.math.BigIntegers.isNonPositive;
import static com.scytl.math.BigIntegers.isNonZero;
import static com.scytl.math.BigIntegers.isOne;
import static com.scytl.math.BigIntegers.isPositive;
import static com.scytl.math.BigIntegers.isZero;
import static com.scytl.math.BigIntegers.modMultiply;
import static com.scytl.math.BigIntegers.modPow;
import static com.scytl.math.BigIntegers.modSquare;
import static com.scytl.math.BigIntegers.multiply;
import static com.scytl.math.BigIntegers.square;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.math.BigInteger;

import org.junit.Test;

/**
 * Tests of {@link BigIntegers}.
 * 
 * @author aakimov
 */
public class BigIntegersTest {
    private static final BigInteger NUMBER1 = BigInteger.valueOf(3);
    private static final BigInteger NUMBER2 = BigInteger.valueOf(5);
    private static final BigInteger MODULUS = BigInteger.valueOf(7);
    private static final BigInteger EXPONENT = BigInteger.valueOf(11);

    @Test
    public void testIsNegative() {
        assertFalse(isNegative(NUMBER1));
        assertFalse(isNegative(BigInteger.ZERO));
        assertTrue(isNegative(NUMBER1.negate()));
    }

    @Test
    public void testIsNonNegative() {
        assertTrue(isNonNegative(NUMBER1));
        assertTrue(isNonNegative(BigInteger.ZERO));
        assertFalse(isNonNegative(NUMBER1.negate()));
    }

    @Test
    public void testIsNonPositive() {
        assertFalse(isNonPositive(NUMBER1));
        assertTrue(isNonPositive(BigInteger.ZERO));
        assertTrue(isNonPositive(NUMBER1.negate()));
    }

    @Test
    public void testIsNonZero() {
        assertTrue(isNonZero(NUMBER1));
        assertFalse(isNonZero(BigInteger.ZERO));
        assertTrue(isNonZero(NUMBER1.negate()));
    }

    @Test
    public void testIsOne() {
        assertFalse(isOne(NUMBER1));
        assertTrue(isOne(BigInteger.ONE));
        assertFalse(isOne(NUMBER1.negate()));
    }

    @Test
    public void testIsPositive() {
        assertTrue(isPositive(NUMBER1));
        assertFalse(isPositive(BigInteger.ZERO));
        assertFalse(isPositive(NUMBER1.negate()));
    }

    @Test
    public void testIsZero() {
        assertFalse(isZero(NUMBER1));
        assertTrue(isZero(BigInteger.ZERO));
        assertFalse(isZero(NUMBER1.negate()));
    }

    @Test
    public void testModMultiply() {
        assertEquals(NUMBER1.multiply(NUMBER2).mod(MODULUS),
                modMultiply(NUMBER1, NUMBER2, MODULUS));
    }

    @Test
    public void testModMultiplyNegative() {
        assertEquals(NUMBER1.multiply(NUMBER2.negate()).mod(MODULUS),
                modMultiply(NUMBER1, NUMBER2.negate(), MODULUS));
    }

    @Test
    public void testModPow() {
        assertEquals(NUMBER1.modPow(EXPONENT, MODULUS),
                modPow(NUMBER1, EXPONENT, MODULUS));
    }

    @Test
    public void testModSquare() {
        assertEquals(NUMBER1.multiply(NUMBER1).mod(MODULUS),
                modSquare(NUMBER1, MODULUS));
    }

    @Test
    public void testMultiply() {
        assertEquals(NUMBER1.multiply(NUMBER2), multiply(NUMBER1, NUMBER2));
    }

    @Test
    public void testSquare() {
        assertEquals(NUMBER1.multiply(NUMBER1), square(NUMBER1));
    }
}
