package net.i2p.crypto.eddsa.math.bigint;
import java.io.Serializable;
import java.math.BigInteger;
import net.i2p.crypto.eddsa.math.Field;
import net.i2p.crypto.eddsa.math.FieldElement;
/**
* A particular element of the field \Z/(2^255-19).
* @author str4d
*
*/
public class BigIntegerFieldElement extends FieldElement implements Serializable {
private static final long serialVersionUID = 4890398908392808L;
/**
* Variable is package private for encoding.
*/
final BigInteger bi;
public BigIntegerFieldElement(Field f, BigInteger bi) {
super(f);
this.bi = bi;
}
public boolean isNonZero() {
return !bi.equals(BigInteger.ZERO);
}
public FieldElement add(FieldElement val) {
return new BigIntegerFieldElement(f, bi.add(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
}
@Override
public FieldElement addOne() {
return new BigIntegerFieldElement(f, bi.add(BigInteger.ONE)).mod(f.getQ());
}
public FieldElement subtract(FieldElement val) {
return new BigIntegerFieldElement(f, bi.subtract(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
}
@Override
public FieldElement subtractOne() {
return new BigIntegerFieldElement(f, bi.subtract(BigInteger.ONE)).mod(f.getQ());
}
public FieldElement negate() {
return f.getQ().subtract(this);
}
@Override
public FieldElement divide(FieldElement val) {
return divide(((BigIntegerFieldElement)val).bi);
}
public FieldElement divide(BigInteger val) {
return new BigIntegerFieldElement(f, bi.divide(val)).mod(f.getQ());
}
public FieldElement multiply(FieldElement val) {
return new BigIntegerFieldElement(f, bi.multiply(((BigIntegerFieldElement)val).bi)).mod(f.getQ());
}
public FieldElement square() {
return multiply(this);
}
public FieldElement squareAndDouble() {
FieldElement sq = square();
return sq.add(sq);
}
public FieldElement invert() {
// Euler's theorem
//return modPow(f.getQm2(), f.getQ());
return new BigIntegerFieldElement(f, bi.modInverse(((BigIntegerFieldElement)f.getQ()).bi));
}
public FieldElement mod(FieldElement m) {
return new BigIntegerFieldElement(f, bi.mod(((BigIntegerFieldElement)m).bi));
}
public FieldElement modPow(FieldElement e, FieldElement m) {
return new BigIntegerFieldElement(f, bi.modPow(((BigIntegerFieldElement)e).bi, ((BigIntegerFieldElement)m).bi));
}
public FieldElement pow(FieldElement e){
return modPow(e, f.getQ());
}
public FieldElement pow22523(){
return pow(f.getQm5d8());
}
@Override
public int hashCode() {
return bi.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BigIntegerFieldElement))
return false;
BigIntegerFieldElement fe = (BigIntegerFieldElement) obj;
return bi.equals(fe.bi);
}
@Override
public String toString() {
return "[BigIntegerFieldElement val="+bi+"]";
}
}