001/* 002 * $Id: BigQuaternionInteger.java 5933 2018-09-28 19:28:41Z 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 absolute value. 162 * @see edu.jas.structure.RingElem#abs() 163 * @return |this|**2. Note: returns the norm(this). 164 */ 165 public BigQuaternion abs() { 166 BigQuaternion n = norm(); 167 //BigRational r = Roots.sqrt(n.re); 168 logger.error("abs() square root missing"); 169 return n; 170 } 171 172 173 /** 174 * Quaternion number inverse. 175 * @param A is a non-zero quaternion number. 176 * @return S with S * A = A * S = 1. 177 */ 178 public static BigQuaternion QINV(BigQuaternion A) { 179 if (A == null) 180 return null; 181 return A.inverse(); 182 } 183 184 185 /** 186 * BigQuaternion inverse. 187 * @return S with S * this = this * S = 1. 188 * @see edu.jas.structure.RingElem#inverse() 189 */ 190 @Override 191 public BigQuaternion inverse() { 192 if (!isUnit()) { 193 logger.info("ring = " + ring); 194 throw new ArithmeticException("not invertible: " + this); 195 } 196 return super.inverse(); 197 } 198 199 200 /** 201 * BigQuaternion remainder. 202 * @param S BigQuaternion. 203 * @return this - this * b**(-1). 204 */ 205 @Override 206 public BigQuaternion remainder(BigQuaternion S) { 207 return rightRemainder(S); 208 } 209 210 211 /** 212 * Quaternion number quotient. 213 * @param A BigQuaternion. 214 * @param B BigQuaternion. 215 * @return R * B**(-1). 216 */ 217 public static BigQuaternion QQ(BigQuaternion A, BigQuaternion B) { 218 if (A == null) 219 return null; 220 return A.divide(B); 221 } 222 223 224 /** 225 * BigQuaternion right divide. 226 * @param b BigQuaternion. 227 * @return this * b**(-1). 228 */ 229 @Override 230 public BigQuaternion divide(BigQuaternion b) { 231 return rightDivide(b); 232 } 233 234 235 /** 236 * BigQuaternion right divide. 237 * @param b BigQuaternion. 238 * @return this * b**(-1). 239 */ 240 @Override 241 public BigQuaternion rightDivide(BigQuaternion b) { 242 return rightQuotientAndRemainder(b)[0]; 243 } 244 245 246 /** 247 * BigQuaternion left divide. 248 * @param b BigQuaternion. 249 * @return b**(-1) * this. 250 */ 251 @Override 252 public BigQuaternion leftDivide(BigQuaternion b) { 253 return leftQuotientAndRemainder(b)[0]; 254 } 255 256 257 /** 258 * BigQuaternion divide. 259 * @param b BigRational. 260 * @return this/b. 261 */ 262 @Override 263 public BigQuaternion divide(BigRational b) { 264 BigQuaternion d = super.divide(b); 265 if (!d.isEntier()) { 266 throw new ArithmeticException("not divisible: " + this + " / " + b); 267 } 268 return d; 269 } 270 271 272 /** 273 * Quotient and remainder by division of this by S. 274 * @param S a quaternion number 275 * @return [this*S**(-1), this - (this*S**(-1))*S]. 276 */ 277 @Override 278 public BigQuaternion[] quotientRemainder(BigQuaternion S) { 279 return new BigQuaternion[] { divide(S), remainder(S) }; 280 } 281 282 283 /** 284 * Quaternion number greatest common divisor. 285 * @param S BigQuaternion. 286 * @return gcd(this,S). 287 */ 288 @Override 289 public BigQuaternion gcd(BigQuaternion S) { 290 return rightGcd(S); 291 } 292 293 294 /** 295 * BigQuaternion extended greatest common divisor. 296 * @param S BigQuaternion. 297 * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). 298 */ 299 @Override 300 public BigQuaternion[] egcd(BigQuaternion S) { 301 throw new UnsupportedOperationException("not implemented: egcd"); 302 /* 303 BigQuaternion[] ret = new BigQuaternion[3]; 304 ret[0] = null; 305 ret[1] = null; 306 ret[2] = null; 307 if (S == null || S.isZERO()) { 308 ret[0] = this; 309 return ret; 310 } 311 if (this.isZERO()) { 312 ret[0] = S; 313 return ret; 314 } 315 BigQuaternion half = new BigQuaternion(ring, new BigRational(1, 2)); 316 ret[0] = ring.getONE(); 317 ret[1] = this.inverse().multiply(half); 318 ret[2] = S.inverse().multiply(half); 319 return ret; 320 */ 321 } 322 323 324 /** 325 * Integral quotient and remainder by left division of this by S. This must 326 * be also an integral (Hurwitz) quaternion number. 327 * @param b an integral (Hurwitz) quaternion number 328 * @return [round(b**(-1)) this, this - b * (round(b**(-1)) this)]. 329 */ 330 public BigQuaternion[] leftQuotientAndRemainder(BigQuaternion b) { 331 //System.out.println("left QR = " + this + ", " + b); 332 if (!this.isEntier() || !b.isEntier()) { 333 throw new IllegalArgumentException("entier elements required"); 334 } 335 BigQuaternion bi = b.inverse(); 336 BigQuaternion m = bi.multiply(this); // left divide 337 //System.out.println("m = " + m.toScript()); 338 BigQuaternionInteger mh = m.roundToHurwitzian(); 339 //System.out.println("mh = " + mh.toScript()); 340 BigQuaternion n = this.subtract(b.multiply(mh)); 341 BigQuaternion[] ret = new BigQuaternion[2]; 342 ret[0] = mh; 343 ret[1] = n; 344 return ret; 345 } 346 347 348 /** 349 * Integral quotient and remainder by right division of this by S. This must 350 * be also an integral (Hurwitz) quaternion number. 351 * @param b an integral (Hurwitz) quaternion number 352 * @return [this round(b**(-1)), this - this (round(b**(-1)) b)]. 353 */ 354 public BigQuaternion[] rightQuotientAndRemainder(BigQuaternion b) { 355 //System.out.println("right QR = " + this + ", " + b); 356 if (!this.isEntier() || !b.isEntier()) { 357 throw new IllegalArgumentException("entier elements required"); 358 } 359 BigQuaternion bi = b.inverse(); 360 BigQuaternion m = this.multiply(bi); // right divide 361 //System.out.println("m = " + m.toScript()); 362 BigQuaternionInteger mh = m.roundToHurwitzian(); 363 //System.out.println("mh = " + mh.toScript()); 364 BigQuaternion n = this.subtract(mh.multiply(b)); 365 BigQuaternion[] ret = new BigQuaternion[2]; 366 ret[0] = mh; 367 ret[1] = n; 368 return ret; 369 } 370 371 372 /** 373 * Left remainder. 374 * @param a element. 375 * @return r = this - (a/left) * a, where left * a = this. 376 */ 377 @Override 378 public BigQuaternion leftRemainder(BigQuaternion a) { 379 return leftQuotientAndRemainder(a)[1]; 380 } 381 382 383 /** 384 * Right remainder. 385 * @param a element. 386 * @return r = this - a * (a/right), where a * right = this. 387 */ 388 @Override 389 public BigQuaternion rightRemainder(BigQuaternion a) { 390 return rightQuotientAndRemainder(a)[1]; 391 } 392 393 394 /** 395 * Integer quaternion number left greatest common divisor. 396 * @param S integer BigQuaternion. 397 * @return leftGcd(this,S). 398 */ 399 @Override 400 public BigQuaternion leftGcd(BigQuaternion S) { 401 if (S == null || S.isZERO()) { 402 return this; 403 } 404 if (this.isZERO()) { 405 return S; 406 } 407 BigQuaternionInteger q; 408 BigQuaternion r; 409 q = this; 410 r = S; 411 while (!r.isZERO()) { 412 BigQuaternion u = q.leftQuotientAndRemainder(r)[1]; 413 //System.out.println("u = " + u.toScript()); 414 q = new BigQuaternionInteger(ring, r); 415 r = u; 416 } 417 return q; 418 } 419 420 421 /** 422 * Integer quaternion number right greatest common divisor. 423 * @param S integer BigQuaternion. 424 * @return rightGcd(this,S). 425 */ 426 @Override 427 public BigQuaternion rightGcd(BigQuaternion S) { 428 if (S == null || S.isZERO()) { 429 return this; 430 } 431 if (this.isZERO()) { 432 return S; 433 } 434 BigQuaternionInteger q; 435 BigQuaternion r; 436 q = this; 437 r = S; 438 while (!r.isZERO()) { 439 BigQuaternion u = q.rightQuotientAndRemainder(r)[1]; 440 //System.out.println("u = " + u.toScript()); 441 q = new BigQuaternionInteger(ring, r); 442 r = u; 443 } 444 return q; 445 } 446 447}