001 /* 002 * $Id: ModLong.java 3501 2011-01-23 19:33:54Z kredel $ 003 */ 004 005 package edu.jas.arith; 006 007 008 import edu.jas.structure.GcdRingElem; 009 import edu.jas.structure.NotInvertibleException; 010 011 012 /** 013 * ModLong class with RingElem interface. Objects of this class are immutable. 014 * @author Heinz Kredel 015 * @see ModInteger 016 */ 017 018 public final class ModLong implements GcdRingElem<ModLong>, Modular { 019 020 021 /** 022 * ModLongRing reference. 023 */ 024 public final ModLongRing ring; 025 026 027 /** 028 * Value part of the element data structure. 029 */ 030 protected final long val; 031 032 033 /** 034 * The constructor creates a ModLong object from a ModLongRing and a value 035 * part. 036 * @param m ModLongRing. 037 * @param a math.BigInteger. 038 */ 039 public ModLong(ModLongRing m, java.math.BigInteger a) { 040 this(m, a.mod(new java.math.BigInteger("" + m.modul)).longValue()); 041 } 042 043 044 /** 045 * The constructor creates a ModLong object from a ModLongRing and a long 046 * value part. 047 * @param m ModLongRing. 048 * @param a long. 049 */ 050 public ModLong(ModLongRing m, long a) { 051 ring = m; 052 long v = a % ring.modul; 053 val = (v >= 0L ? v : v + ring.modul); 054 } 055 056 057 /** 058 * The constructor creates a ModLong object from a ModLongRing and a Long 059 * value part. 060 * @param m ModLongRing. 061 * @param a Long. 062 */ 063 public ModLong(ModLongRing m, Long a) { 064 this(m, a.longValue()); 065 } 066 067 068 /** 069 * The constructor creates a ModLong object from a ModLongRing and a String 070 * value part. 071 * @param m ModLongRing. 072 * @param s String. 073 */ 074 public ModLong(ModLongRing m, String s) { 075 this(m, new Long(s.trim())); 076 } 077 078 079 /** 080 * The constructor creates a 0 ModLong object from a given ModLongRing. 081 * @param m ModLongRing. 082 */ 083 public ModLong(ModLongRing m) { 084 this(m, 0L); 085 } 086 087 088 /** 089 * Get the value part. 090 * @return val. 091 */ 092 public long getVal() { 093 return val; 094 } 095 096 097 /** 098 * Get the module part. 099 * @return modul. 100 */ 101 public long getModul() { 102 return ring.modul; 103 } 104 105 106 /** 107 * Get the corresponding element factory. 108 * @return factory for this Element. 109 * @see edu.jas.structure.Element#factory() 110 */ 111 public ModLongRing factory() { 112 return ring; 113 } 114 115 116 /** 117 * Get the symmetric value part. 118 * @return val with -modul/2 <= val < modul/2. 119 */ 120 public long getSymmetricVal() { 121 if ((val + val) > ring.modul) { 122 // val > m/2 as 2*val > m, make symmetric to 0 123 return val - ring.modul; 124 } 125 return val; 126 } 127 128 129 /** 130 * Return a BigInteger from this Element. 131 * @return a BigInteger of this. 132 */ 133 public BigInteger getInteger() { 134 return new BigInteger(val); 135 } 136 137 138 /** 139 * Return a symmetric BigInteger from this Element. 140 * @return a symmetric BigInteger of this. 141 */ 142 public BigInteger getSymmetricInteger() { 143 long v = val; 144 if ((val + val) > ring.modul) { 145 // val > m/2 as 2*val > m, make symmetric to 0 146 v = val - ring.modul; 147 } 148 return new BigInteger(v); 149 } 150 151 152 /** 153 * Clone this. 154 * @see java.lang.Object#clone() 155 */ 156 @Override 157 public ModLong clone() { 158 return new ModLong(ring, val); 159 } 160 161 162 /** 163 * Is ModLong number zero. 164 * @return If this is 0 then true is returned, else false. 165 * @see edu.jas.structure.RingElem#isZERO() 166 */ 167 public boolean isZERO() { 168 return val == 0L; 169 } 170 171 172 /** 173 * Is ModLong number one. 174 * @return If this is 1 then true is returned, else false. 175 * @see edu.jas.structure.RingElem#isONE() 176 */ 177 public boolean isONE() { 178 return val == 1L; 179 } 180 181 182 /** 183 * Is ModLong number a unit. 184 * @return If this is a unit then true is returned, else false. 185 * @see edu.jas.structure.RingElem#isUnit() 186 */ 187 public boolean isUnit() { 188 if (isZERO()) { 189 return false; 190 } 191 if (ring.isField()) { 192 return true; 193 } 194 long g = gcd(ring.modul, val); 195 return (g == 1L || g == -1L); 196 } 197 198 199 /** 200 * Get the String representation. 201 * @see java.lang.Object#toString() 202 */ 203 @Override 204 public String toString() { 205 return "" + val; 206 } 207 208 209 /** 210 * Get a scripting compatible string representation. 211 * @return script compatible representation for this Element. 212 * @see edu.jas.structure.Element#toScript() 213 */ 214 //JAVA6only: @Override 215 public String toScript() { 216 // Python case 217 return toString(); 218 } 219 220 221 /** 222 * Get a scripting compatible string representation of the factory. 223 * @return script compatible representation for this ElemFactory. 224 * @see edu.jas.structure.Element#toScriptFactory() 225 */ 226 //JAVA6only: @Override 227 public String toScriptFactory() { 228 // Python case 229 return factory().toScript(); 230 } 231 232 233 /** 234 * ModLong comparison. 235 * @param b ModLong. 236 * @return sign(this-b). 237 */ 238 //JAVA6only: @Override 239 public int compareTo(ModLong b) { 240 long v = b.val; 241 if (ring != b.ring) { 242 v = v % ring.modul; 243 } 244 if (val > v) { 245 return 1; 246 } 247 return (val < v ? -1 : 0); 248 } 249 250 251 /** 252 * Comparison with any other object. 253 * @see java.lang.Object#equals(java.lang.Object) 254 */ 255 @Override 256 public boolean equals(Object b) { 257 if (!(b instanceof ModLong)) { 258 return false; 259 } 260 return (0 == compareTo((ModLong) b)); 261 } 262 263 264 /** 265 * Hash code for this ModLong. 266 * @see java.lang.Object#hashCode() 267 */ 268 @Override 269 public int hashCode() { 270 return (int) val; 271 } 272 273 274 /** 275 * ModLong absolute value. 276 * @return the absolute value of this. 277 * @see edu.jas.structure.RingElem#abs() 278 */ 279 public ModLong abs() { 280 return new ModLong(ring, (val < 0 ? -val : val)); 281 } 282 283 284 /** 285 * ModLong negative. 286 * @see edu.jas.structure.RingElem#negate() 287 * @return -this. 288 */ 289 public ModLong negate() { 290 return new ModLong(ring, -val); 291 } 292 293 294 /** 295 * ModLong signum. 296 * @see edu.jas.structure.RingElem#signum() 297 * @return signum(this). 298 */ 299 public int signum() { 300 if (val > 0L) { 301 return 1; 302 } 303 return (val < 0L ? -1 : 0); 304 } 305 306 307 /** 308 * ModLong subtraction. 309 * @param S ModLong. 310 * @return this-S. 311 */ 312 public ModLong subtract(ModLong S) { 313 return new ModLong(ring, val - S.val); 314 } 315 316 317 /** 318 * ModLong divide. 319 * @param S ModLong. 320 * @return this/S. 321 */ 322 public ModLong divide(ModLong S) { 323 try { 324 return multiply(S.inverse()); 325 } catch (NotInvertibleException e) { 326 try { 327 if ((val % S.val) == 0L) { 328 return new ModLong(ring, val / S.val); 329 } 330 throw new NotInvertibleException(e.getCause()); 331 } catch (ArithmeticException a) { 332 throw new NotInvertibleException(a.getCause()); 333 } 334 } 335 } 336 337 338 /** 339 * ModLong inverse. 340 * @see edu.jas.structure.RingElem#inverse() 341 * @throws NotInvertibleException if the element is not invertible. 342 * @return S with S=1/this if defined. 343 */ 344 public ModLong inverse() /*throws NotInvertibleException*/{ 345 try { 346 return new ModLong(ring, modInverse(val, ring.modul)); 347 } catch (ArithmeticException e) { 348 long g = gcd( val, ring.modul ); 349 long f = ring.modul / g; 350 throw new ModularNotInvertibleException(e,new BigInteger(ring.modul),new BigInteger(g),new BigInteger(f)); 351 } 352 } 353 354 355 /** 356 * ModLong remainder. 357 * @param S ModLong. 358 * @return remainder(this,S). 359 */ 360 public ModLong remainder(ModLong S) { 361 if (S == null || S.isZERO()) { 362 throw new ArithmeticException(this.getClass().getName() + " division by zero"); 363 } 364 if (S.isONE()) { 365 return ring.getZERO(); 366 } 367 if (S.isUnit()) { 368 return ring.getZERO(); 369 } 370 return new ModLong(ring, val % S.val); 371 } 372 373 374 /** 375 * ModLong multiply. 376 * @param S ModLong. 377 * @return this*S. 378 */ 379 public ModLong multiply(ModLong S) { 380 return new ModLong(ring, val * S.val); 381 } 382 383 384 /** 385 * ModLong summation. 386 * @param S ModLong. 387 * @return this+S. 388 */ 389 public ModLong sum(ModLong S) { 390 return new ModLong(ring, val + S.val); 391 } 392 393 394 /** 395 * ModInteger greatest common divisor. 396 * @param S ModInteger. 397 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 398 */ 399 public ModLong gcd(ModLong S) { 400 if (S.isZERO()) { 401 return this; 402 } 403 if (isZERO()) { 404 return S; 405 } 406 if (isUnit() || S.isUnit()) { 407 return ring.getONE(); 408 } 409 return new ModLong(ring, gcd(val, S.val)); 410 } 411 412 413 /** 414 * ModInteger extended greatest common divisor. 415 * @param S ModInteger. 416 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 417 */ 418 public ModLong[] egcd(ModLong S) { 419 ModLong[] ret = new ModLong[3]; 420 ret[0] = null; 421 ret[1] = null; 422 ret[2] = null; 423 if (S == null || S.isZERO()) { 424 ret[0] = this; 425 return ret; 426 } 427 if (isZERO()) { 428 ret[0] = S; 429 return ret; 430 } 431 if (isUnit() || S.isUnit()) { 432 ret[0] = ring.getONE(); 433 if (isUnit() && S.isUnit()) { 434 //ModLong half = (new ModLong(ring, 2L)).inverse(); 435 //ret[1] = this.inverse().multiply(half); 436 //ret[2] = S.inverse().multiply(half); 437 // (1-1*this)/S 438 ret[1] = ring.getONE(); 439 ModLong x = ret[0].subtract(ret[1].multiply(this)); 440 ret[2] = x.divide(S); 441 return ret; 442 } 443 if (isUnit()) { 444 // oder inverse(S-1)? 445 ret[1] = this.inverse(); 446 ret[2] = ring.getZERO(); 447 return ret; 448 } 449 // if ( s.isUnit() ) { 450 // oder inverse(this-1)? 451 ret[1] = ring.getZERO(); 452 ret[2] = S.inverse(); 453 return ret; 454 //} 455 } 456 //System.out.println("this = " + this + ", S = " + S); 457 long q = this.val; 458 long r = S.val; 459 long c1 = 1L; // BigInteger.ONE.val; 460 long d1 = 0L; // BigInteger.ZERO.val; 461 long c2 = 0L; // BigInteger.ZERO.val; 462 long d2 = 1L; // BigInteger.ONE.val; 463 long x1; 464 long x2; 465 while (r != 0L) { 466 //qr = q.divideAndRemainder(r); 467 long a = q / r; 468 long b = q % r; 469 q = a; 470 x1 = c1 - q * d1; 471 x2 = c2 - q * d2; 472 c1 = d1; 473 c2 = d2; 474 d1 = x1; 475 d2 = x2; 476 q = r; 477 r = b; 478 } 479 System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); 480 ret[0] = new ModLong(ring, q); 481 ret[1] = new ModLong(ring, c1); 482 ret[2] = new ModLong(ring, c2); 483 return ret; 484 } 485 486 487 /** 488 * Long greatest common divisor. 489 * @param T long. 490 * @param S long. 491 * @return gcd(T,S). 492 */ 493 public long gcd(long T, long S) { 494 if (S == 0L) { 495 return T; 496 } 497 if (T == 0L) { 498 return S; 499 } 500 long a = T; 501 long b = S; 502 while (b != 0L) { 503 long r = a % b; 504 a = b; 505 b = r; 506 } 507 return a; 508 } 509 510 511 /** 512 * Long half extended greatest common divisor. 513 * @param T long. 514 * @param S long. 515 * @return [ gcd(T,S), a ] with a*T + b*S = gcd(T,S). 516 */ 517 public long[] hegcd(long T, long S) { 518 long[] ret = new long[2]; 519 if (S == 0L) { 520 ret[0] = T; 521 ret[1] = 1L; 522 return ret; 523 } 524 if (T == 0L) { 525 ret[0] = S; 526 ret[1] = 0L; 527 return ret; 528 } 529 //System.out.println("hegcd, T = " + T + ", S = " + S); 530 long a = T; 531 long b = S; 532 long a1 = 1L; 533 long b1 = 0L; 534 while (b != 0L) { 535 long q = a / b; 536 long r = a % b; 537 a = b; 538 b = r; 539 long r1 = a1 - q * b1; 540 a1 = b1; 541 b1 = r1; 542 } 543 if (a1 < 0L) { 544 a1 += S; 545 } 546 ret[0] = a; 547 ret[1] = a1; 548 return ret; 549 } 550 551 552 /** 553 * Long modular inverse. 554 * @param T long. 555 * @param m long. 556 * @return a with with a*T = 1 mod m. 557 */ 558 public long modInverse(long T, long m) { 559 if (T == 0L) { 560 throw new NotInvertibleException("zero is not invertible"); 561 } 562 long[] hegcd = hegcd(T, m); 563 long a = hegcd[0]; 564 if (!(a == 1L || a == -1L)) { // gcd != 1 565 throw new ModularNotInvertibleException("element not invertible, gcd != 1", 566 new BigInteger(m),new BigInteger(a),new BigInteger(m/a)); 567 } 568 long b = hegcd[1]; 569 if (b == 0L) { // when m divides this, e.g. m.isUnit() 570 throw new NotInvertibleException("element not invertible, divisible by modul"); 571 } 572 if (b < 0L) { 573 b += m; 574 } 575 return b; 576 } 577 578 }