001/* 002 * $Id: ModLongRing.java 5925 2018-09-19 21:24:52Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.Iterator; 011import java.util.List; 012import java.util.Random; 013 014import edu.jas.kern.StringUtil; 015 016 017/** 018 * ModLongRing factory with RingFactory interface. Effectively immutable. 019 * @author Heinz Kredel 020 */ 021 022public final class ModLongRing implements ModularRingFactory<ModLong>, Iterable<ModLong> { 023 024 025 /** 026 * Module part of the factory data structure. 027 */ 028 public final long modul; 029 030 031 /** 032 * Random number generator. 033 */ 034 private final static Random random = new Random(); 035 036 037 /** 038 * Indicator if this ring is a field. 039 */ 040 private int isField = -1; // initially unknown 041 042 043 /* 044 * Certainty if module is probable prime. 045 */ 046 //private final int certainty = 10; 047 048 049 /** 050 * maximal representable integer. 051 */ 052 public final static java.math.BigInteger MAX_LONG = new java.math.BigInteger( 053 String.valueOf(Integer.MAX_VALUE)); // not larger! 054 055 056 /** 057 * The constructor creates a ModLongRing object from a long integer as 058 * module part. 059 * @param m long integer. 060 */ 061 public ModLongRing(long m) { 062 modul = m; 063 } 064 065 066 /** 067 * The constructor creates a ModLongRing object from a long integer as 068 * module part. 069 * @param m long integer. 070 * @param isField indicator if m is prime. 071 */ 072 public ModLongRing(long m, boolean isField) { 073 modul = m; 074 this.isField = (isField ? 1 : 0); 075 } 076 077 078 /** 079 * The constructor creates a ModLongRing object from a Long integer as 080 * module part. 081 * @param m Long integer. 082 */ 083 public ModLongRing(Long m) { 084 this(m.longValue()); 085 } 086 087 088 /** 089 * The constructor creates a ModLongRing object from a Long integer as 090 * module part. 091 * @param m Long integer. 092 * @param isField indicator if m is prime. 093 */ 094 public ModLongRing(Long m, boolean isField) { 095 this(m.longValue(), isField); 096 } 097 098 099 /** 100 * The constructor creates a ModLongRing object from a BigInteger converted 101 * to long as module part. 102 * @param m java.math.BigInteger. 103 */ 104 public ModLongRing(java.math.BigInteger m) { 105 this(m.longValue()); 106 if (MAX_LONG.compareTo(m) < 0) { // m > max 107 //System.out.println("modul to large for long " + m + ",max=" + MAX_LONG); 108 throw new IllegalArgumentException("modul to large for long " + m + ", max=" + MAX_LONG); 109 } 110 } 111 112 113 /** 114 * The constructor creates a ModLongRing object from a BigInteger converted 115 * to long as module part. 116 * @param m java.math.BigInteger. 117 * @param isField indicator if m is prime. 118 */ 119 public ModLongRing(java.math.BigInteger m, boolean isField) { 120 this(m.longValue(), isField); 121 if (MAX_LONG.compareTo(m) < 0) { // m > max 122 //System.out.println("modul to large for long " + m + ",max=" + MAX_LONG); 123 throw new IllegalArgumentException("modul to large for long " + m + ", max=" + MAX_LONG); 124 } 125 } 126 127 128 /** 129 * The constructor creates a ModLongRing object from a String object as 130 * module part. 131 * @param m String. 132 */ 133 public ModLongRing(String m) { 134 this(Long.valueOf(m.trim())); 135 } 136 137 138 /** 139 * The constructor creates a ModLongRing object from a String object as 140 * module part. 141 * @param m String. 142 * @param isField indicator if m is prime. 143 */ 144 public ModLongRing(String m, boolean isField) { 145 this(Long.valueOf(m.trim()), isField); 146 } 147 148 149 /** 150 * Get the module part as BigInteger. 151 * @return modul. 152 */ 153 public java.math.BigInteger getModul() { 154 return new java.math.BigInteger(Long.toString(modul)); 155 } 156 157 158 /** 159 * Get the module part as long. 160 * @return modul. 161 */ 162 public long getLongModul() { 163 return modul; 164 } 165 166 167 /** 168 * Get the module part as BigInteger. 169 * @return modul. 170 */ 171 public BigInteger getIntegerModul() { 172 return new BigInteger(modul); 173 } 174 175 176 /** 177 * Create ModLong element c. 178 * @param c 179 * @return a ModLong of c. 180 */ 181 public ModLong create(java.math.BigInteger c) { 182 return new ModLong(this, c); 183 } 184 185 186 /** 187 * Create ModLong element c. 188 * @param c 189 * @return a ModLong of c. 190 */ 191 public ModLong create(long c) { 192 return new ModLong(this, c); 193 } 194 195 196 /** 197 * Create ModLong element c. 198 * @param c 199 * @return a ModLong of c. 200 */ 201 public ModLong create(String c) { 202 return parse(c); 203 } 204 205 206 /** 207 * Copy ModLong element c. 208 * @param c 209 * @return a copy of c. 210 */ 211 public ModLong copy(ModLong c) { 212 return new ModLong(this, c.val); 213 } 214 215 216 /** 217 * Get the zero element. 218 * @return 0 as ModLong. 219 */ 220 public ModLong getZERO() { 221 return new ModLong(this, 0L); 222 } 223 224 225 /** 226 * Get the one element. 227 * @return 1 as ModLong. 228 */ 229 public ModLong getONE() { 230 return new ModLong(this, 1L); 231 } 232 233 234 /** 235 * Get a list of the generating elements. 236 * @return list of generators for the algebraic structure. 237 * @see edu.jas.structure.ElemFactory#generators() 238 */ 239 public List<ModLong> generators() { 240 List<ModLong> g = new ArrayList<ModLong>(1); 241 g.add(getONE()); 242 return g; 243 } 244 245 246 /** 247 * Is this structure finite or infinite. 248 * @return true if this structure is finite, else false. 249 * @see edu.jas.structure.ElemFactory#isFinite() 250 */ 251 public boolean isFinite() { 252 return true; 253 } 254 255 256 /** 257 * Query if this ring is commutative. 258 * @return true. 259 */ 260 public boolean isCommutative() { 261 return true; 262 } 263 264 265 /** 266 * Query if this ring is associative. 267 * @return true. 268 */ 269 public boolean isAssociative() { 270 return true; 271 } 272 273 274 /** 275 * Query if this ring is a field. 276 * @return true if module is prime, else false. 277 */ 278 public boolean isField() { 279 if (isField > 0) { 280 return true; 281 } 282 if (isField == 0) { 283 return false; 284 } 285 //System.out.println("isProbablePrime " + modul + " = " + modul.isProbablePrime(certainty)); 286 java.math.BigInteger m = new java.math.BigInteger(Long.toString(modul)); 287 if (m.isProbablePrime(m.bitLength())) { 288 isField = 1; 289 return true; 290 } 291 isField = 0; 292 return false; 293 } 294 295 296 /** 297 * Characteristic of this ring. 298 * @return characteristic of this ring. 299 */ 300 public java.math.BigInteger characteristic() { 301 return new java.math.BigInteger(Long.toString(modul)); 302 } 303 304 305 /** 306 * Get a ModLong element from a BigInteger value. 307 * @param a BigInteger. 308 * @return a ModLong. 309 */ 310 public ModLong fromInteger(java.math.BigInteger a) { 311 return new ModLong(this, a); 312 } 313 314 315 /** 316 * Get a ModLong element from a long value. 317 * @param a long. 318 * @return a ModLong. 319 */ 320 public ModLong fromInteger(long a) { 321 return new ModLong(this, a); 322 } 323 324 325 /** 326 * Get the String representation. 327 * @see java.lang.Object#toString() 328 */ 329 @Override 330 public String toString() { 331 return " mod(" + modul + ")"; //",max=" + MAX_LONG + ")"; 332 } 333 334 335 /** 336 * Get a scripting compatible string representation. 337 * @return script compatible representation for this ElemFactory. 338 * @see edu.jas.structure.ElemFactory#toScript() 339 */ 340 @Override 341 public String toScript() { 342 // Python and Ruby case 343 if (isField()) { 344 return "GFL(" + modul + ")"; 345 } 346 return "ZML(" + modul + ")"; 347 } 348 349 350 /** 351 * Comparison with any other object. 352 * @see java.lang.Object#equals(java.lang.Object) 353 */ 354 @Override 355 public boolean equals(Object b) { 356 if (!(b instanceof ModLongRing)) { 357 return false; 358 } 359 ModLongRing m = (ModLongRing) b; 360 return (modul == m.modul); 361 } 362 363 364 /** 365 * Hash code for this ModLongRing. 366 * @see java.lang.Object#hashCode() 367 */ 368 @Override 369 public int hashCode() { 370 return (int) modul; 371 } 372 373 374 /** 375 * ModLong random. 376 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 377 * @return a random integer mod modul. 378 */ 379 public ModLong random(int n) { 380 return random(n, random); 381 } 382 383 384 /** 385 * ModLong random. 386 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 387 * @param rnd is a source for random bits. 388 * @return a random integer mod modul. 389 */ 390 public ModLong random(int n, Random rnd) { 391 java.math.BigInteger v = new java.math.BigInteger(n, rnd); 392 return new ModLong(this, v); // rnd.nextLong() not ok 393 } 394 395 396 /** 397 * Parse ModLong from String. 398 * @param s String. 399 * @return ModLong from s. 400 */ 401 public ModLong parse(String s) { 402 return new ModLong(this, s); 403 } 404 405 406 /** 407 * Parse ModLong from Reader. 408 * @param r Reader. 409 * @return next ModLong from r. 410 */ 411 public ModLong parse(Reader r) { 412 return parse(StringUtil.nextString(r)); 413 } 414 415 416 /** 417 * ModLong chinese remainder algorithm. This is a factory method. Assert 418 * c.modul >= a.modul and c.modul * a.modul = this.modul. 419 * @param c ModLong. 420 * @param ci inverse of c.modul in ring of a. 421 * @param a other ModLong. 422 * @return S, with S mod c.modul == c and S mod a.modul == a. 423 */ 424 public ModLong chineseRemainder(ModLong c, ModLong ci, ModLong a) { 425 //if (true) { 426 // if (c.ring.modul < a.ring.modul) { 427 // System.out.println("ModLong error " + c.ring + ", " + a.ring); 428 // } 429 //} 430 ModLong b = a.ring.fromInteger(c.val); // c mod a.modul 431 ModLong d = a.subtract(b); // a-c mod a.modul 432 if (d.isZERO()) { 433 return new ModLong(this, c.val); 434 } 435 b = d.multiply(ci); // b = (a-c)*ci mod a.modul 436 // (c.modul*b)+c mod this.modul = c mod c.modul = 437 // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul 438 long s = c.ring.modul * b.val; 439 s = s + c.val; 440 return new ModLong(this, s); 441 } 442 443 444 /** 445 * Modular digit list chinese remainder algorithm. m1 and m2 are positive 446 * beta-integers, with GCD(m1,m2)=1 and m=m1*m2 less than beta. L1 and L2 447 * are lists of elements of Z(m1) and Z(m2) respectively. L is a list of all 448 * a in Z(m) such that a is congruent to a1 modulo m1 and a is congruent to 449 * a2 modulo m2 with a1 in L1 and a2 in L2. This is a factory method. Assert 450 * c.modul >= a.modul and c.modul * a.modul = this.modul. 451 * @param m1 ModLong. 452 * @param m2 other ModLong. 453 * @return L list of congruences. 454 */ 455 public static List<ModLong> chineseRemainder(ModLong m1, ModLong m2, List<ModLong> L1, List<ModLong> L2) { 456 long mm = m1.ring.modul * m2.ring.modul; 457 ModLongRing m = new ModLongRing(mm); 458 ModLong m21 = m2.ring.fromInteger(m1.ring.modul); 459 ModLong mi1 = m21.inverse(); 460 461 List<ModLong> L = new ArrayList<ModLong>(); 462 for (ModLong a : L1) { 463 for (ModLong b : L2) { 464 ModLong c = m.chineseRemainder(a, mi1, b); 465 L.add(c); 466 } 467 } 468 return L; 469 } 470 471 472 /** 473 * Get a ModLong iterator. 474 * @return a iterator over all modular integers in this ring. 475 */ 476 public Iterator<ModLong> iterator() { 477 return new ModLongIterator(this); 478 } 479 480} 481 482 483/** 484 * Modular integer iterator. 485 * @author Heinz Kredel 486 */ 487class ModLongIterator implements Iterator<ModLong> { 488 489 490 /** 491 * data structure. 492 */ 493 long curr; 494 495 496 final ModLongRing ring; 497 498 499 /** 500 * ModLong iterator constructor. 501 * @param fac modular integer factory; 502 */ 503 public ModLongIterator(ModLongRing fac) { 504 curr = 0L; 505 ring = fac; 506 } 507 508 509 /** 510 * Test for availability of a next element. 511 * @return true if the iteration has more elements, else false. 512 */ 513 public synchronized boolean hasNext() { 514 return curr < ring.modul; 515 } 516 517 518 /** 519 * Get next integer. 520 * @return next integer. 521 */ 522 public synchronized ModLong next() { 523 ModLong i = new ModLong(ring, curr); 524 curr++; 525 return i; 526 } 527 528 529 /** 530 * Remove an element if allowed. 531 */ 532 public void remove() { 533 throw new UnsupportedOperationException("cannnot remove elements"); 534 } 535}