001/*
002 * $Id: BigQuaternionRing.java 5784 2017-12-09 18:52:37Z kredel $
003 */
004
005package edu.jas.arith;
006
007
008import java.io.Reader;
009// import java.math.BigInteger;
010import java.util.ArrayList;
011import java.util.List;
012import java.util.Random;
013
014import org.apache.log4j.Logger;
015
016import edu.jas.kern.StringUtil;
017import edu.jas.kern.Scripting;
018import edu.jas.structure.RingFactory;
019
020
021/**
022 * BigQuaternion ring class based on BigRational implementing the RingElem
023 * interface.
024 * @author Heinz Kredel
025 */
026
027public final class BigQuaternionRing implements RingFactory<BigQuaternion> {
028
029
030    /**
031     * List of all 24 integral units.
032     */
033    static List<BigQuaternion> entierUnits = null; //later: unitsOfHurwitzian();
034
035
036    /**
037     * Flag to signal if this ring is integral.
038     */
039    protected boolean integral = false;
040
041
042    protected final static Random random = new Random();
043
044
045    private static final Logger logger = Logger.getLogger(BigQuaternionRing.class);
046
047
048    //private static final boolean debug = logger.isDebugEnabled();
049
050
051    /**
052     * Constructor for a BigQuaternion ring.
053     */
054    public BigQuaternionRing() {
055        this(false);
056    }
057
058
059    /**
060     * Constructor for a BigQuaternion ring.
061     */
062    public BigQuaternionRing(boolean i) {
063        integral = i;
064        logger.info("integral = " + integral);
065    }
066
067
068    /**
069     * Get a list of the generating elements.
070     * @return list of generators for the algebraic structure.
071     * @see edu.jas.structure.ElemFactory#generators()
072     */
073    public List<BigQuaternion> generators() {
074        List<BigQuaternion> g = new ArrayList<BigQuaternion>(4);
075        g.add(getONE());
076        g.add(I);
077        g.add(J);
078        g.add(K);
079        return g;
080    }
081
082
083    /**
084     * Is this structure finite or infinite.
085     * @return true if this structure is finite, else false.
086     * @see edu.jas.structure.ElemFactory#isFinite()
087     */
088    public boolean isFinite() {
089        return false;
090    }
091
092
093    /**
094     * Copy BigQuaternion element c.
095     * @param c BigQuaternion.
096     * @return a copy of c.
097     */
098    public BigQuaternion copy(BigQuaternion c) {
099        return new BigQuaternion(this, c.re, c.im, c.jm, c.km);
100    }
101
102
103    /**
104     * Get the zero element.
105     * @return 0 as BigQuaternion.
106     */
107    public BigQuaternion getZERO() {
108        return ZERO;
109    }
110
111
112    /**
113     * Get the one element.
114     * @return q as BigQuaternion.
115     */
116    public BigQuaternion getONE() {
117        return ONE;
118    }
119
120
121    /**
122     * Query if this ring is commutative.
123     * @return false.
124     */
125    public boolean isCommutative() {
126        return false;
127    }
128
129
130    /**
131     * Query if this ring is associative.
132     * @return true.
133     */
134    public boolean isAssociative() {
135        return true;
136    }
137
138
139    /**
140     * Query if this ring is a field.
141     * @return true.
142     */
143    public boolean isField() {
144        return !integral;
145    }
146
147
148    /**
149     * Characteristic of this ring.
150     * @return characteristic of this ring.
151     */
152    public java.math.BigInteger characteristic() {
153        return java.math.BigInteger.ZERO;
154    }
155
156
157    /**
158     * Get a BigQuaternion element from a BigInteger.
159     * @param a BigInteger.
160     * @return a BigQuaternion.
161     */
162    public BigQuaternion fromInteger(java.math.BigInteger a) {
163        return new BigQuaternion(this, new BigRational(a));
164    }
165
166
167    /**
168     * Get a BigQuaternion element from a long.
169     * @param a long.
170     * @return a BigQuaternion.
171     */
172    public BigQuaternion fromInteger(long a) {
173        return new BigQuaternion(this, new BigRational(a));
174    }
175
176
177    /**
178     * Get a BigQuaternion element from a long vector.
179     * @param a long vector.
180     * @return a BigQuaternion.
181     */
182    public BigQuaternion fromInteger(long[] a) {
183        return new BigQuaternion(this, new BigRational(a[0]), new BigRational(a[1]), new BigRational(a[2]),
184                        new BigRational(a[3]));
185    }
186
187
188    /**
189     * The constant 0.
190     */
191    public final BigQuaternion ZERO = new BigQuaternion(this);
192
193
194    /**
195     * The constant 1.
196     */
197    public final BigQuaternion ONE = new BigQuaternion(this, BigRational.ONE);
198
199
200    /**
201     * The constant i.
202     */
203    public final BigQuaternion I = new BigQuaternion(this, BigRational.ZERO, BigRational.ONE);
204
205
206    /**
207     * The constant j.
208     */
209    public final BigQuaternion J = new BigQuaternion(this, BigRational.ZERO, BigRational.ZERO,
210                    BigRational.ONE);
211
212
213    /**
214     * The constant k.
215     */
216    public final BigQuaternion K = new BigQuaternion(this, BigRational.ZERO, BigRational.ZERO,
217                    BigRational.ZERO, BigRational.ONE);
218
219
220    /**
221     * Get the string representation. Is compatible with the string constructor.
222     * @see java.lang.Object#toString()
223     */
224    @Override
225    public String toString() {
226        String s = "BigQuaternionRing(" + integral + ")";
227        return s;
228    }
229
230
231    /**
232     * Get a scripting compatible string representation.
233     * @return script compatible representation for this Element.
234     * @see edu.jas.structure.Element#toScript()
235     */
236    @Override
237    public String toScript() {
238        StringBuffer s = new StringBuffer("BigQuaternionRing(");
239        switch (Scripting.getLang()) {
240        case Ruby:
241            s.append((integral ? ",true" : ",false"));
242            break;
243        case Python:
244        default:
245            s.append((integral ? ",True" : ",False"));
246        }
247        s.append(")");
248        return s.toString();
249    }
250
251
252    /**
253     * Comparison with any other object.
254     * @see java.lang.Object#equals(java.lang.Object)
255     */
256    @Override
257    public boolean equals(Object b) {
258        if (!(b instanceof BigQuaternionRing)) {
259            return false;
260        }
261        BigQuaternionRing B = (BigQuaternionRing) b;
262        return this.integral == B.integral;
263    }
264
265
266    /**
267     * Hash code for this BigQuaternionRing.
268     * @see java.lang.Object#hashCode()
269     */
270    @Override
271    public int hashCode() {
272        int h = 4711;
273        return h;
274    }
275
276
277    /**
278     * BigQuaternion units of the Hurwitzian integers. BigQuaternion units with
279     * all integer or all 1/2 times integer components.
280     * @return list of all 24 units.
281     */
282    public List<BigQuaternion> unitsOfHurwitzian() {
283        if (entierUnits != null) {
284            return entierUnits;
285        }
286        BigRational half = BigRational.HALF;
287        // Lipschitz integer units
288        List<BigQuaternion> units = generators();
289        List<BigQuaternion> u = new ArrayList<BigQuaternion>(units);
290        for (BigQuaternion ue : u) {
291            units.add(ue.negate());
292        }
293        // Hurwitz integer units
294        long[][] comb = new long[][] { { 1, 1, 1, 1 }, { -1, 1, 1, 1 }, { 1, -1, 1, 1 }, { -1, -1, 1, 1 },
295                { 1, 1, -1, 1 }, { -1, 1, -1, 1 }, { 1, -1, -1, 1 }, { -1, -1, -1, 1 }, { 1, 1, 1, -1 },
296                { -1, 1, 1, -1 }, { 1, -1, 1, -1 }, { -1, -1, 1, -1 }, { 1, 1, -1, -1 }, { -1, 1, -1, -1 },
297                { 1, -1, -1, -1 }, { -1, -1, -1, -1 } };
298        for (long[] row : comb) {
299            BigQuaternion ue = fromInteger(row);
300            ue = ue.multiply(half);
301            units.add(ue);
302        }
303        //System.out.println("units = " + units);
304        //for (BigQuaternion ue : units) {
305        //System.out.println("unit = " + ue + ", norm = " + ue.norm());
306        //}
307        entierUnits = units;
308        return units;
309    }
310
311
312    /**
313     * BigQuaternion random. Random rational numbers A, B, C and D are generated
314     * using random(n). Then R is the quaternion number with real part A and
315     * imaginary parts B, C and D.
316     * @param n such that 0 &le; A, B, C, D &le; (2<sup>n</sup>-1).
317     * @return R, a random BigQuaternion.
318     */
319    public BigQuaternion random(int n) {
320        return random(n, random);
321    }
322
323
324    /**
325     * BigQuaternion random. Random rational numbers A, B, C and D are generated
326     * using RNRAND(n). Then R is the quaternion number with real part A and
327     * imaginary parts B, C and D.
328     * @param n such that 0 &le; A, B, C, D &le; (2<sup>n</sup>-1).
329     * @param rnd is a source for random bits.
330     * @return R, a random BigQuaternion.
331     */
332    public BigQuaternion random(int n, Random rnd) {
333        BigRational r = BigRational.ONE.random(n, rnd);
334        BigRational i = BigRational.ONE.random(n, rnd);
335        BigRational j = BigRational.ONE.random(n, rnd);
336        BigRational k = BigRational.ONE.random(n, rnd);
337        BigQuaternion q = new BigQuaternion(this, r, i, j, k);
338        if (integral) {
339            q = q.roundToHurwitzian();
340        }
341        return q;
342    }
343
344
345    /*
346     * Quaternion number, random. Random rational numbers A, B, C and D are
347     * generated using RNRAND(n). Then R is the quaternion number with real part
348     * A and imaginary parts B, C and D.
349     * @param n such that 0 &le; A, B, C, D &le; (2<sup>n</sup>-1).
350     * @return R, a random BigQuaternion.
351    public static BigQuaternion QRAND(int n) {
352        return ONE.random(n, random);
353    }
354     */
355
356
357    /**
358     * Parse quaternion number from String.
359     * @param s String.
360     * @return BigQuaternion from s.
361     */
362    public BigQuaternion parse(String s) {
363        return new BigQuaternion(this, s);
364    }
365
366
367    /**
368     * Parse quaternion number from Reader.
369     * @param r Reader.
370     * @return next BigQuaternion from r.
371     */
372    public BigQuaternion parse(Reader r) {
373        return parse(StringUtil.nextString(r));
374    }
375
376}