001/* 002 * $Id: BigQuaternionInteger.java 5872 2018-07-20 16:01:46Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008import org.apache.logging.log4j.Logger; 009import org.apache.logging.log4j.LogManager; 010 011 012/** 013 * Integer BigQuaternion class based on BigRational implementing the RingElem 014 * interface and with the familiar MAS static method names. Objects of this 015 * class are immutable. The integer quaternion methods are implemented after 016 * https://de.wikipedia.org/wiki/Hurwitzquaternion see also 017 * https://en.wikipedia.org/wiki/Hurwitz_quaternion 018 * @author Heinz Kredel 019 */ 020 021public final class BigQuaternionInteger extends BigQuaternion 022// implements StarRingElem<BigQuaternion>, GcdRingElem<BigQuaternion> 023{ 024 025 026 private static final Logger logger = LogManager.getLogger(BigQuaternionInteger.class); 027 028 029 //private static final boolean debug = logger.isDebugEnabled(); 030 031 032 /** 033 * Constructor for a BigQuaternion from BigRationals. 034 * @param fac BigQuaternionRing. 035 * @param r BigRational. 036 * @param i BigRational. 037 * @param j BigRational. 038 * @param k BigRational. 039 */ 040 public BigQuaternionInteger(BigQuaternionRing fac, BigRational r, BigRational i, BigRational j, 041 BigRational k) { 042 super(fac, r, i, j, k); 043 } 044 045 046 /** 047 * Constructor for a BigQuaternion from BigRationals. 048 * @param fac BigQuaternionRing. 049 * @param r BigRational. 050 * @param i BigRational. 051 * @param j BigRational. 052 */ 053 public BigQuaternionInteger(BigQuaternionRing fac, BigRational r, BigRational i, BigRational j) { 054 this(fac, r, i, j, BigRational.ZERO); 055 } 056 057 058 /** 059 * Constructor for a BigQuaternion from BigRationals. 060 * @param fac BigQuaternionRing. 061 * @param r BigRational. 062 * @param i BigRational. 063 */ 064 public BigQuaternionInteger(BigQuaternionRing fac, BigRational r, BigRational i) { 065 this(fac, r, i, BigRational.ZERO); 066 } 067 068 069 /** 070 * Constructor for a BigQuaternion from BigRationals. 071 * @param fac BigQuaternionRing. 072 * @param r BigRational. 073 */ 074 public BigQuaternionInteger(BigQuaternionRing fac, BigRational r) { 075 this(fac, r, BigRational.ZERO); 076 } 077 078 079 /** 080 * Constructor for a BigQuaternion from BigComplex. 081 * @param fac BigQuaternionRing. 082 * @param r BigComplex. 083 */ 084 public BigQuaternionInteger(BigQuaternionRing fac, BigComplex r) { 085 this(fac, r.re, r.im); 086 } 087 088 089 /** 090 * Constructor for a BigQuaternionInteger from BigQuaternion. 091 * @param fac BigQuaternionRing. 092 * @param q BigQuaternion. 093 */ 094 public BigQuaternionInteger(BigQuaternionRing fac, BigQuaternion q) { 095 this(fac, q.re, q.im, q.jm, q.km); 096 } 097 098 099 /** 100 * Constructor for a BigQuaternion from long. 101 * @param fac BigQuaternionRing. 102 * @param r long. 103 */ 104 public BigQuaternionInteger(BigQuaternionRing fac, long r) { 105 this(fac, new BigRational(r), BigRational.ZERO); 106 } 107 108 109 /** 110 * Constructor for a BigQuaternion with no arguments. 111 * @param fac BigQuaternionRing. 112 */ 113 public BigQuaternionInteger(BigQuaternionRing fac) { 114 this(fac, BigRational.ZERO); 115 } 116 117 118 /** 119 * The BigQuaternion string constructor accepts the following formats: empty 120 * string, "rational", or "rat i rat j rat k rat" with no blanks around i, j 121 * or k if used as polynoial coefficient. 122 * @param fac BigQuaternionRing. 123 * @param s String. 124 * @throws NumberFormatException 125 */ 126 public BigQuaternionInteger(BigQuaternionRing fac, String s) throws NumberFormatException { 127 super(fac, s); 128 } 129 130 131 /** 132 * Get the corresponding element factory. 133 * @return factory for this Element. 134 * @see edu.jas.structure.Element#factory() 135 */ 136 @Override 137 public BigQuaternionRing factory() { 138 return ring; 139 } 140 141 142 /** 143 * Clone this. 144 * @see java.lang.Object#clone() 145 */ 146 @Override 147 public BigQuaternionInteger copy() { 148 return new BigQuaternionInteger(ring, re, im, jm, km); 149 } 150 151 152 /* arithmetic operations: +, -, - 153 */ 154 155 156 /* arithmetic operations: *, inverse, / 157 */ 158 159 160 /** 161 * Quaternion number inverse. 162 * @param A is a non-zero quaternion number. 163 * @return S with S * A = A * S = 1. 164 */ 165 public static BigQuaternion QINV(BigQuaternion A) { 166 if (A == null) 167 return null; 168 return A.inverse(); 169 } 170 171 172 /** 173 * BigQuaternion inverse. 174 * @return S with S * this = this * S = 1. 175 * @see edu.jas.structure.RingElem#inverse() 176 */ 177 @Override 178 public BigQuaternion inverse() { 179 if (!isUnit()) { 180 logger.info("ring = " + ring); 181 throw new ArithmeticException("not invertible: " + this); 182 } 183 return super.inverse(); 184 } 185 186 187 /** 188 * BigQuaternion remainder. 189 * @param S BigQuaternion. 190 * @return this - this * b**(-1). 191 */ 192 @Override 193 public BigQuaternion remainder(BigQuaternion S) { 194 return rightRemainder(S); 195 } 196 197 198 /** 199 * Quaternion number quotient. 200 * @param A BigQuaternion. 201 * @param B BigQuaternion. 202 * @return R * B**(-1). 203 */ 204 public static BigQuaternion QQ(BigQuaternion A, BigQuaternion B) { 205 if (A == null) 206 return null; 207 return A.divide(B); 208 } 209 210 211 /** 212 * BigQuaternion right divide. 213 * @param b BigQuaternion. 214 * @return this * b**(-1). 215 */ 216 @Override 217 public BigQuaternion divide(BigQuaternion b) { 218 return rightDivide(b); 219 } 220 221 222 /** 223 * BigQuaternion right divide. 224 * @param b BigQuaternion. 225 * @return this * b**(-1). 226 */ 227 @Override 228 public BigQuaternion rightDivide(BigQuaternion b) { 229 return rightQuotientAndRemainder(b)[0]; 230 } 231 232 233 /** 234 * BigQuaternion left divide. 235 * @param b BigQuaternion. 236 * @return b**(-1) * this. 237 */ 238 @Override 239 public BigQuaternion leftDivide(BigQuaternion b) { 240 return leftQuotientAndRemainder(b)[0]; 241 } 242 243 244 /** 245 * BigQuaternion divide. 246 * @param b BigRational. 247 * @return this/b. 248 */ 249 @Override 250 public BigQuaternion divide(BigRational b) { 251 BigQuaternion d = super.divide(b); 252 if (!d.isEntier()) { 253 throw new ArithmeticException("not divisible: " + this + " / " + b); 254 } 255 return d; 256 } 257 258 259 /** 260 * Quotient and remainder by division of this by S. 261 * @param S a quaternion number 262 * @return [this*S**(-1), this - (this*S**(-1))*S]. 263 */ 264 @Override 265 public BigQuaternion[] quotientRemainder(BigQuaternion S) { 266 return new BigQuaternion[] { divide(S), remainder(S) }; 267 } 268 269 270 /** 271 * Quaternion number greatest common divisor. 272 * @param S BigQuaternion. 273 * @return gcd(this,S). 274 */ 275 @Override 276 public BigQuaternion gcd(BigQuaternion S) { 277 return rightGcd(S); 278 } 279 280 281 /** 282 * BigQuaternion extended greatest common divisor. 283 * @param S BigQuaternion. 284 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 285 */ 286 @Override 287 public BigQuaternion[] egcd(BigQuaternion S) { 288 throw new UnsupportedOperationException("not implemented: egcd"); 289 /* 290 BigQuaternion[] ret = new BigQuaternion[3]; 291 ret[0] = null; 292 ret[1] = null; 293 ret[2] = null; 294 if (S == null || S.isZERO()) { 295 ret[0] = this; 296 return ret; 297 } 298 if (this.isZERO()) { 299 ret[0] = S; 300 return ret; 301 } 302 BigQuaternion half = new BigQuaternion(ring, new BigRational(1, 2)); 303 ret[0] = ring.getONE(); 304 ret[1] = this.inverse().multiply(half); 305 ret[2] = S.inverse().multiply(half); 306 return ret; 307 */ 308 } 309 310 311 /** 312 * Integral quotient and remainder by left division of this by S. This must 313 * be also an integral (Hurwitz) quaternion number. 314 * @param b an integral (Hurwitz) quaternion number 315 * @return [round(b**(-1)) this, this - b * (round(b**(-1)) this)]. 316 */ 317 public BigQuaternion[] leftQuotientAndRemainder(BigQuaternion b) { 318 //System.out.println("left QR = " + this + ", " + b); 319 if (!this.isEntier() || !b.isEntier()) { 320 throw new IllegalArgumentException("entier elements required"); 321 } 322 BigQuaternion bi = b.inverse(); 323 BigQuaternion m = bi.multiply(this); // left divide 324 //System.out.println("m = " + m.toScript()); 325 BigQuaternionInteger mh = m.roundToHurwitzian(); 326 //System.out.println("mh = " + mh.toScript()); 327 BigQuaternion n = this.subtract(b.multiply(mh)); 328 BigQuaternion[] ret = new BigQuaternion[2]; 329 ret[0] = mh; 330 ret[1] = n; 331 return ret; 332 } 333 334 335 /** 336 * Integral quotient and remainder by right division of this by S. This must 337 * be also an integral (Hurwitz) quaternion number. 338 * @param b an integral (Hurwitz) quaternion number 339 * @return [this round(b**(-1)), this - this (round(b**(-1)) b)]. 340 */ 341 public BigQuaternion[] rightQuotientAndRemainder(BigQuaternion b) { 342 //System.out.println("right QR = " + this + ", " + b); 343 if (!this.isEntier() || !b.isEntier()) { 344 throw new IllegalArgumentException("entier elements required"); 345 } 346 BigQuaternion bi = b.inverse(); 347 BigQuaternion m = this.multiply(bi); // right divide 348 //System.out.println("m = " + m.toScript()); 349 BigQuaternionInteger mh = m.roundToHurwitzian(); 350 //System.out.println("mh = " + mh.toScript()); 351 BigQuaternion n = this.subtract(mh.multiply(b)); 352 BigQuaternion[] ret = new BigQuaternion[2]; 353 ret[0] = mh; 354 ret[1] = n; 355 return ret; 356 } 357 358 359 /** 360 * Left remainder. 361 * @param a element. 362 * @return r = this - (a/left) * a, where left * a = this. 363 */ 364 @Override 365 public BigQuaternion leftRemainder(BigQuaternion a) { 366 return leftQuotientAndRemainder(a)[1]; 367 } 368 369 370 /** 371 * Right remainder. 372 * @param a element. 373 * @return r = this - a * (a/right), where a * right = this. 374 */ 375 @Override 376 public BigQuaternion rightRemainder(BigQuaternion a) { 377 return rightQuotientAndRemainder(a)[1]; 378 } 379 380 381 /** 382 * Integer quaternion number left greatest common divisor. 383 * @param S integer BigQuaternion. 384 * @return leftGcd(this,S). 385 */ 386 @Override 387 public BigQuaternion leftGcd(BigQuaternion S) { 388 if (S == null || S.isZERO()) { 389 return this; 390 } 391 if (this.isZERO()) { 392 return S; 393 } 394 BigQuaternionInteger q; 395 BigQuaternion r; 396 q = this; 397 r = S; 398 while (!r.isZERO()) { 399 BigQuaternion u = q.leftQuotientAndRemainder(r)[1]; 400 //System.out.println("u = " + u.toScript()); 401 q = new BigQuaternionInteger(ring, r); 402 r = u; 403 } 404 return q; 405 } 406 407 408 /** 409 * Integer quaternion number right greatest common divisor. 410 * @param S integer BigQuaternion. 411 * @return rightGcd(this,S). 412 */ 413 @Override 414 public BigQuaternion rightGcd(BigQuaternion S) { 415 if (S == null || S.isZERO()) { 416 return this; 417 } 418 if (this.isZERO()) { 419 return S; 420 } 421 BigQuaternionInteger q; 422 BigQuaternion r; 423 q = this; 424 r = S; 425 while (!r.isZERO()) { 426 BigQuaternion u = q.rightQuotientAndRemainder(r)[1]; 427 //System.out.println("u = " + u.toScript()); 428 q = new BigQuaternionInteger(ring, r); 429 r = u; 430 } 431 return q; 432 } 433 434}