package sun.security.util.math.intpoly;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.math.BigInteger;
import java.nio.*;
public class IntegerPolynomial1305 extends IntegerPolynomial {
protected static final int SUBTRAHEND = 5;
protected static final int NUM_LIMBS = 5;
private static final int POWER = 130;
private static final int BITS_PER_LIMB = 26;
private static final BigInteger MODULUS
= TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
public IntegerPolynomial1305() {
super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
}
protected void mult(long[] a, long[] b, long[] r) {
long c0 = (a[0] * b[0]);
long c1 = (a[0] * b[1]) + (a[1] * b[0]);
long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
long c5 = (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]);
long c6 = (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]);
long c7 = (a[3] * b[4]) + (a[4] * b[3]);
long c8 = (a[4] * b[4]);
carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8);
}
private void carryReduce(long[] r, long c0, long c1, long c2, long c3,
long c4, long c5, long c6, long c7, long c8) {
r[2] = c2 + (c7 * SUBTRAHEND);
c3 += (c8 * SUBTRAHEND);
long carry3 = carryValue(c3);
r[3] = c3 - (carry3 << BITS_PER_LIMB);
c4 += carry3;
long carry4 = carryValue(c4);
r[4] = c4 - (carry4 << BITS_PER_LIMB);
c5 += carry4;
r[0] = c0 + (c5 * SUBTRAHEND);
r[1] = c1 + (c6 * SUBTRAHEND);
carry(r);
}
@Override
protected void square(long[] a, long[] r) {
long c0 = (a[0] * a[0]);
long c1 = 2 * (a[0] * a[1]);
long c2 = 2 * (a[0] * a[2]) + (a[1] * a[1]);
long c3 = 2 * (a[0] * a[3] + a[1] * a[2]);
long c4 = 2 * (a[0] * a[4] + a[1] * a[3]) + (a[2] * a[2]);
long c5 = 2 * (a[1] * a[4] + a[2] * a[3]);
long c6 = 2 * (a[2] * a[4]) + (a[3] * a[3]);
long c7 = 2 * (a[3] * a[4]);
long c8 = (a[4] * a[4]);
carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8);
}
@Override
protected void encode(ByteBuffer buf, int length, byte highByte,
long[] result) {
if (length == 16) {
long low = buf.getLong();
long high = buf.getLong();
encode(high, low, highByte, result);
} else {
super.encode(buf, length, highByte, result);
}
}
protected void encode(long high, long low, byte highByte, long[] result) {
result[0] = low & 0x3FFFFFFL;
result[1] = (low >>> 26) & 0x3FFFFFFL;
result[2] = (low >>> 52) + ((high & 0x3FFFL) << 12);
result[3] = (high >>> 14) & 0x3FFFFFFL;
result[4] = (high >>> 40) + (highByte << 24L);
}
private static final VarHandle AS_LONG_LE = MethodHandles
.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
protected void encode(byte[] v, int offset, int length, byte highByte,
long[] result) {
if (length == 16) {
long low = (long) AS_LONG_LE.get(v, offset);
long high = (long) AS_LONG_LE.get(v, offset + 8);
encode(high, low, highByte, result);
} else {
super.encode(v, offset, length, highByte, result);
}
}
@Override
protected void reduceIn(long[] limbs, long x, int index) {
long reducedValue = (x * SUBTRAHEND);
limbs[index - NUM_LIMBS] += reducedValue;
}
@Override
protected void finalCarryReduceLast(long[] limbs) {
long carry = limbs[numLimbs - 1] >> bitsPerLimb;
limbs[numLimbs - 1] -= carry << bitsPerLimb;
reduceIn(limbs, carry, numLimbs);
}
protected final void modReduce(long[] limbs, int start, int end) {
for (int i = start; i < end; i++) {
reduceIn(limbs, limbs[i], i);
limbs[i] = 0;
}
}
protected void modReduce(long[] limbs) {
modReduce(limbs, NUM_LIMBS, NUM_LIMBS - 1);
}
@Override
protected long carryValue(long x) {
return x >> BITS_PER_LIMB;
}
@Override
protected void postEncodeCarry(long[] v) {
}
@Override
protected void reduce(long[] limbs) {
long carry3 = carryOut(limbs, 3);
long new4 = carry3 + limbs[4];
long carry4 = carryValue(new4);
limbs[4] = new4 - (carry4 << BITS_PER_LIMB);
reduceIn(limbs, carry4, 5);
carry(limbs);
}
}