
edu.jas.arith.ModLong Maven / Gradle / Ivy
The newest version!
/*
* $Id: ModLong.java 4148 2012-08-31 19:49:27Z kredel $
*/
package edu.jas.arith;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.NotInvertibleException;
/**
* ModLong class with RingElem interface. Objects of this class are immutable.
* @author Heinz Kredel
* @see ModInteger
*/
public final class ModLong implements GcdRingElem, Modular {
/**
* ModLongRing reference.
*/
public final ModLongRing ring;
/**
* Value part of the element data structure.
*/
public final long val;
/**
* The constructor creates a ModLong object from a ModLongRing and a value
* part.
* @param m ModLongRing.
* @param a math.BigInteger.
*/
public ModLong(ModLongRing m, java.math.BigInteger a) {
this(m, a.mod(new java.math.BigInteger("" + m.modul)).longValue());
}
/**
* The constructor creates a ModLong object from a ModLongRing and a long
* value part.
* @param m ModLongRing.
* @param a long.
*/
public ModLong(ModLongRing m, long a) {
ring = m;
long v = a % ring.modul;
val = (v >= 0L ? v : v + ring.modul);
}
/**
* The constructor creates a ModLong object from a ModLongRing and a Long
* value part.
* @param m ModLongRing.
* @param a Long.
*/
public ModLong(ModLongRing m, Long a) {
this(m, a.longValue());
}
/**
* The constructor creates a ModLong object from a ModLongRing and a String
* value part.
* @param m ModLongRing.
* @param s String.
*/
public ModLong(ModLongRing m, String s) {
this(m, new Long(s.trim()));
}
/**
* The constructor creates a 0 ModLong object from a given ModLongRing.
* @param m ModLongRing.
*/
public ModLong(ModLongRing m) {
this(m, 0L);
}
/**
* Get the value part.
* @return val.
*/
public long getVal() {
return val;
}
/**
* Get the module part.
* @return modul.
*/
public long getModul() {
return ring.modul;
}
/**
* Get the corresponding element factory.
* @return factory for this Element.
* @see edu.jas.structure.Element#factory()
*/
public ModLongRing factory() {
return ring;
}
/**
* Get the symmetric value part.
* @return val with -modul/2 <= val < modul/2.
*/
public long getSymmetricVal() {
if ((val + val) > ring.modul) {
// val > m/2 as 2*val > m, make symmetric to 0
return val - ring.modul;
}
return val;
}
/**
* Return a BigInteger from this Element.
* @return a BigInteger of this.
*/
public BigInteger getInteger() {
return new BigInteger(val);
}
/**
* Return a symmetric BigInteger from this Element.
* @return a symmetric BigInteger of this.
*/
public BigInteger getSymmetricInteger() {
long v = val;
if ((val + val) > ring.modul) {
// val > m/2 as 2*val > m, make symmetric to 0
v = val - ring.modul;
}
return new BigInteger(v);
}
/**
* Clone this.
* @see java.lang.Object#clone()
*/
@Override
public ModLong copy() {
return new ModLong(ring, val);
}
/**
* Is ModLong number zero.
* @return If this is 0 then true is returned, else false.
* @see edu.jas.structure.RingElem#isZERO()
*/
public boolean isZERO() {
return val == 0L;
}
/**
* Is ModLong number one.
* @return If this is 1 then true is returned, else false.
* @see edu.jas.structure.RingElem#isONE()
*/
public boolean isONE() {
return val == 1L;
}
/**
* Is ModLong number a unit.
* @return If this is a unit then true is returned, else false.
* @see edu.jas.structure.RingElem#isUnit()
*/
public boolean isUnit() {
if (isZERO()) {
return false;
}
if (ring.isField()) {
return true;
}
long g = gcd(ring.modul, val);
return (g == 1L || g == -1L);
}
/**
* Get the String representation.
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "" + val;
}
/**
* Get a scripting compatible string representation.
* @return script compatible representation for this Element.
* @see edu.jas.structure.Element#toScript()
*/
//JAVA6only: @Override
public String toScript() {
// Python case
return toString();
}
/**
* Get a scripting compatible string representation of the factory.
* @return script compatible representation for this ElemFactory.
* @see edu.jas.structure.Element#toScriptFactory()
*/
//JAVA6only: @Override
public String toScriptFactory() {
// Python case
return factory().toScript();
}
/**
* ModLong comparison.
* @param b ModLong.
* @return sign(this-b).
*/
//JAVA6only: @Override
public int compareTo(ModLong b) {
long v = b.val;
if (ring != b.ring) {
v = v % ring.modul;
}
if (val > v) {
return 1;
}
return (val < v ? -1 : 0);
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object b) {
if (!(b instanceof ModLong)) {
return false;
}
return (0 == compareTo((ModLong) b));
}
/**
* Hash code for this ModLong.
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return (int) val;
}
/**
* ModLong absolute value.
* @return the absolute value of this.
* @see edu.jas.structure.RingElem#abs()
*/
public ModLong abs() {
return new ModLong(ring, (val < 0 ? -val : val));
}
/**
* ModLong negative.
* @see edu.jas.structure.RingElem#negate()
* @return -this.
*/
public ModLong negate() {
return new ModLong(ring, -val);
}
/**
* ModLong signum.
* @see edu.jas.structure.RingElem#signum()
* @return signum(this).
*/
public int signum() {
if (val > 0L) {
return 1;
}
return (val < 0L ? -1 : 0);
}
/**
* ModLong subtraction.
* @param S ModLong.
* @return this-S.
*/
public ModLong subtract(ModLong S) {
return new ModLong(ring, val - S.val);
}
/**
* ModLong divide.
* @param S ModLong.
* @return this/S.
*/
public ModLong divide(ModLong S) {
try {
return multiply(S.inverse());
} catch (NotInvertibleException e) {
try {
if ((val % S.val) == 0L) {
return new ModLong(ring, val / S.val);
}
throw new NotInvertibleException(e.getCause());
} catch (ArithmeticException a) {
throw new NotInvertibleException(a.getCause());
}
}
}
/**
* ModLong inverse.
* @see edu.jas.structure.RingElem#inverse()
* @throws NotInvertibleException if the element is not invertible.
* @return S with S=1/this if defined.
*/
public ModLong inverse() /*throws NotInvertibleException*/{
try {
return new ModLong(ring, modInverse(val, ring.modul));
} catch (ArithmeticException e) {
long g = gcd(val, ring.modul);
long f = ring.modul / g;
throw new ModularNotInvertibleException(e, new BigInteger(ring.modul), new BigInteger(g),
new BigInteger(f));
}
}
/**
* ModLong remainder.
* @param S ModLong.
* @return remainder(this,S).
*/
public ModLong remainder(ModLong S) {
if (S == null || S.isZERO()) {
throw new ArithmeticException("division by zero");
}
if (S.isONE()) {
return ring.getZERO();
}
if (S.isUnit()) {
return ring.getZERO();
}
return new ModLong(ring, val % S.val);
}
/**
* ModLong multiply.
* @param S ModLong.
* @return this*S.
*/
public ModLong multiply(ModLong S) {
return new ModLong(ring, val * S.val);
}
/**
* ModLong summation.
* @param S ModLong.
* @return this+S.
*/
public ModLong sum(ModLong S) {
return new ModLong(ring, val + S.val);
}
/**
* ModInteger greatest common divisor.
* @param S ModInteger.
* @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
*/
public ModLong gcd(ModLong S) {
if (S.isZERO()) {
return this;
}
if (isZERO()) {
return S;
}
if (isUnit() || S.isUnit()) {
return ring.getONE();
}
return new ModLong(ring, gcd(val, S.val));
}
/**
* ModInteger extended greatest common divisor.
* @param S ModInteger.
* @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
*/
public ModLong[] egcd(ModLong S) {
ModLong[] ret = new ModLong[3];
ret[0] = null;
ret[1] = null;
ret[2] = null;
if (S == null || S.isZERO()) {
ret[0] = this;
return ret;
}
if (isZERO()) {
ret[0] = S;
return ret;
}
if (isUnit() || S.isUnit()) {
ret[0] = ring.getONE();
if (isUnit() && S.isUnit()) {
//ModLong half = (new ModLong(ring, 2L)).inverse();
//ret[1] = this.inverse().multiply(half);
//ret[2] = S.inverse().multiply(half);
// (1-1*this)/S
ret[1] = ring.getONE();
ModLong x = ret[0].subtract(ret[1].multiply(this));
ret[2] = x.divide(S);
return ret;
}
if (isUnit()) {
// oder inverse(S-1)?
ret[1] = this.inverse();
ret[2] = ring.getZERO();
return ret;
}
// if ( s.isUnit() ) {
// oder inverse(this-1)?
ret[1] = ring.getZERO();
ret[2] = S.inverse();
return ret;
//}
}
//System.out.println("this = " + this + ", S = " + S);
long q = this.val;
long r = S.val;
long c1 = 1L; // BigInteger.ONE.val;
long d1 = 0L; // BigInteger.ZERO.val;
long c2 = 0L; // BigInteger.ZERO.val;
long d2 = 1L; // BigInteger.ONE.val;
long x1;
long x2;
while (r != 0L) {
//qr = q.divideAndRemainder(r);
long a = q / r;
long b = q % r;
q = a;
x1 = c1 - q * d1;
x2 = c2 - q * d2;
c1 = d1;
c2 = d2;
d1 = x1;
d2 = x2;
q = r;
r = b;
}
System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2);
ret[0] = new ModLong(ring, q);
ret[1] = new ModLong(ring, c1);
ret[2] = new ModLong(ring, c2);
return ret;
}
/**
* Long greatest common divisor.
* @param T long.
* @param S long.
* @return gcd(T,S).
*/
public long gcd(long T, long S) {
if (S == 0L) {
return T;
}
if (T == 0L) {
return S;
}
long a = T;
long b = S;
while (b != 0L) {
long r = a % b;
a = b;
b = r;
}
return a;
}
/**
* Long half extended greatest common divisor.
* @param T long.
* @param S long.
* @return [ gcd(T,S), a ] with a*T + b*S = gcd(T,S).
*/
public long[] hegcd(long T, long S) {
long[] ret = new long[2];
if (S == 0L) {
ret[0] = T;
ret[1] = 1L;
return ret;
}
if (T == 0L) {
ret[0] = S;
ret[1] = 0L;
return ret;
}
//System.out.println("hegcd, T = " + T + ", S = " + S);
long a = T;
long b = S;
long a1 = 1L;
long b1 = 0L;
while (b != 0L) {
long q = a / b;
long r = a % b;
a = b;
b = r;
long r1 = a1 - q * b1;
a1 = b1;
b1 = r1;
}
if (a1 < 0L) {
a1 += S;
}
ret[0] = a;
ret[1] = a1;
return ret;
}
/**
* Long modular inverse.
* @param T long.
* @param m long.
* @return a with with a*T = 1 mod m.
*/
public long modInverse(long T, long m) {
if (T == 0L) {
throw new NotInvertibleException("zero is not invertible");
}
long[] hegcd = hegcd(T, m);
long a = hegcd[0];
if (!(a == 1L || a == -1L)) { // gcd != 1
throw new ModularNotInvertibleException("element not invertible, gcd != 1", new BigInteger(m),
new BigInteger(a), new BigInteger(m / a));
}
long b = hegcd[1];
if (b == 0L) { // when m divides this, e.g. m.isUnit()
throw new NotInvertibleException("element not invertible, divisible by modul");
}
if (b < 0L) {
b += m;
}
return b;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy