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