001: /*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2006 - JScience (http://jscience.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package org.jscience.mathematics.number;
010:
011: import org.jscience.mathematics.structure.Field;
012:
013: import javolution.context.LocalContext;
014: import javolution.context.ObjectFactory;
015: import javolution.text.Text;
016: import javolution.xml.XMLFormat;
017: import javolution.xml.stream.XMLStreamException;
018:
019: /**
020: * <p> This class represents a modulo integer. It can be used in conjonction
021: * with the {@link org.jscience.mathematics.vector.Matrix Matrix}
022: * class to resolve modulo equations (ref. number theory).</p>
023: *
024: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
025: * @version 3.0, February 13, 2006
026: * @see <a href="http://en.wikipedia.org/wiki/Modular_arithmetic">
027: * Wikipedia: Modular Arithmetic</a>
028: */
029: public final class ModuloInteger extends Number<ModuloInteger>
030: implements Field<ModuloInteger> {
031:
032: /**
033: * The modulo integer representing the additive identity.
034: */
035: public static final ModuloInteger ZERO = new ModuloInteger();
036: static {
037: ZERO._value = LargeInteger.ZERO;
038: }
039:
040: /**
041: * The modulo integer representing the multiplicative identity.
042: */
043: public static final ModuloInteger ONE = new ModuloInteger();
044: static {
045: ONE._value = LargeInteger.ONE;
046: }
047:
048: /**
049: * Holds the default XML representation for modulo integers.
050: * This representation consists of a simple <code>value</code> attribute
051: * holding the {@link #toText() textual} representation.
052: */
053: static final XMLFormat<ModuloInteger> XML = new XMLFormat<ModuloInteger>(
054: ModuloInteger.class) {
055:
056: @Override
057: public ModuloInteger newInstance(Class<ModuloInteger> cls,
058: InputElement xml) throws XMLStreamException {
059: return ModuloInteger.valueOf(xml.getAttribute("value"));
060: }
061:
062: public void write(ModuloInteger mi, OutputElement xml)
063: throws XMLStreamException {
064: xml.setAttribute("value", mi._value.toText());
065: }
066:
067: public void read(InputElement xml, ModuloInteger mi) {
068: // Nothing to do, immutable.
069: }
070: };
071:
072: /**
073: * Holds the local modulus (for modular arithmetic).
074: */
075: private static final LocalContext.Reference<LargeInteger> MODULUS = new LocalContext.Reference<LargeInteger>();
076:
077: /**
078: * Holds the large integer value.
079: */
080: private LargeInteger _value;
081:
082: /**
083: * Returns the modulo integer having the specified value (independently of
084: * the current modulo).
085: *
086: * @param value the modulo integer intrinsic value.
087: * @return the corresponding modulo number.
088: */
089: public static ModuloInteger valueOf(LargeInteger value) {
090: return ModuloInteger.newInstance(value);
091: }
092:
093: /**
094: * Returns the modulo integer for the specified character sequence in
095: * decimal number.
096: *
097: * @param chars the character sequence.
098: * @return the corresponding modulo number.
099: */
100: public static ModuloInteger valueOf(CharSequence chars) {
101: return ModuloInteger.newInstance(LargeInteger.valueOf(chars));
102: }
103:
104: /**
105: * Returns the {@link javolution.context.LocalContext local} modulus
106: * for modular arithmetic or <code>null</code> if the arithmetic operations
107: * are non-modular (default).
108: *
109: * @return the local modulus or <code>null</code> if none.
110: * @see #setModulus
111: */
112: public static LargeInteger getModulus() {
113: return MODULUS.get();
114: }
115:
116: /**
117: * Sets the {@link javolution.context.LocalContext local} modulus
118: * for modular arithmetic.
119: *
120: * @param modulus the new modulus or <code>null</code> to unset the modulus.
121: * @throws IllegalArgumentException if <code>modulus <= 0</code>
122: */
123: public static void setModulus(LargeInteger modulus) {
124: if ((modulus != null) && (!modulus.isPositive()))
125: throw new IllegalArgumentException("modulus: " + modulus
126: + " has to be greater than 0");
127: MODULUS.set(modulus);
128: }
129:
130: /**
131: * Returns the current modulo value of this number. If the modulus
132: * is {@link #setModulus set} to <code>null</code> the intrinsic value
133: * (the creation value) is returned.
134: *
135: * @return the positive number equals to this number modulo modulus or
136: * this modulo creation value.
137: */
138: public LargeInteger moduloValue() {
139: LargeInteger modulus = MODULUS.get();
140: return (modulus == null) ? _value : _value.mod(modulus);
141: }
142:
143: /**
144: * Returns the text representation of the current modulo value of
145: * this number.
146: *
147: * @return the representation of its modulo value.
148: */
149: public Text toText() {
150: return moduloValue().toText();
151: }
152:
153: /**
154: * Compares this modulo integer against the specified object
155: * independently of the current modulus.
156: *
157: * @param that the object to compare with.
158: * @return <code>true</code> if that is a modulo number with the same
159: * intrinsic value; <code>false</code> otherwise.
160: */
161: public boolean equals(Object that) {
162: return (that instanceof ModuloInteger) ? _value
163: .equals(((ModuloInteger) that)._value) : false;
164: }
165:
166: /**
167: * Returns the hash code for this large integer number.
168: *
169: * @return the hash code value.
170: */
171: public int hashCode() {
172: return _value.hashCode();
173: }
174:
175: @Override
176: public boolean isLargerThan(ModuloInteger that) {
177: return _value.isLargerThan(that._value);
178: }
179:
180: @Override
181: public long longValue() {
182: return moduloValue().longValue();
183: }
184:
185: @Override
186: public double doubleValue() {
187: return moduloValue().doubleValue();
188: }
189:
190: @Override
191: public int compareTo(ModuloInteger that) {
192: return _value.compareTo(that._value);
193: }
194:
195: public ModuloInteger times(ModuloInteger that) {
196: LargeInteger value = moduloValue().times(that.moduloValue());
197: LargeInteger modulus = MODULUS.get();
198: return (modulus == null) ? ModuloInteger.valueOf(value)
199: : ModuloInteger.valueOf(value.mod(modulus));
200: }
201:
202: public ModuloInteger plus(ModuloInteger that) {
203: LargeInteger value = moduloValue().plus(that.moduloValue());
204: LargeInteger modulus = MODULUS.get();
205: return (modulus == null) ? ModuloInteger.valueOf(value)
206: : ModuloInteger.valueOf(value.mod(modulus));
207: }
208:
209: public ModuloInteger opposite() {
210: LargeInteger value = moduloValue().opposite();
211: LargeInteger modulus = MODULUS.get();
212: return (modulus == null) ? ModuloInteger.valueOf(value)
213: : ModuloInteger.valueOf(value.mod(modulus));
214: }
215:
216: public ModuloInteger inverse() {
217: LargeInteger modulus = MODULUS.get();
218: if (modulus == null)
219: throw new ArithmeticException("Modulus not set");
220: return ModuloInteger.valueOf(_value.modInverse(modulus));
221: }
222:
223: ///////////////////////
224: // Factory creation. //
225: ///////////////////////
226:
227: private static ModuloInteger newInstance(LargeInteger value) {
228: ModuloInteger m = FACTORY.object();
229: m._value = value;
230: return m;
231: }
232:
233: private static final ObjectFactory<ModuloInteger> FACTORY = new ObjectFactory<ModuloInteger>() {
234: protected ModuloInteger create() {
235: return new ModuloInteger();
236: }
237: };
238:
239: private ModuloInteger() {
240: }
241:
242: @Override
243: public ModuloInteger copy() {
244: return newInstance(_value.copy());
245: }
246:
247: private static final long serialVersionUID = 1L;
248:
249: }
|