Files
secondo/Algebras/Rose/RoseJava/twodsack/util/number/RationalFactory.java
2026-01-23 17:03:45 +08:00

424 lines
16 KiB
Java

/*
* RationalFactory.java 2005-05-13
*
* Dirk Ansorge, FernUniversitaet Hagen
*
*/
package twodsack.util.number;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.*;
/**
* The RationalFactory class is used for the construction of numeric values.
* Therefore, it conatins a set of methods with the name
* <tt>constRational()</tt> with different parameter types. This class supports the use of different implementations of the {@link Rational} class. Before
* a Rational instance can be constructed, the class that shall be used has to be defined using the {@link #setClass(Class)} method. After that,
* this class can be used.<p>
* Two extensions of the abstract Rational class are delivered with the 2DSACK package:<p>
* <ul>
* <li>{@link RationalDouble}
* <li>{@link RationalBigInteger}
* </ul>
* Another method of this class can be used to set the <tt>PRECISE</tt> field. It defines wether a more or less precise computation is used.
* The default value for <tt>PRECISE</tt> is <tt>true</tt>. If <tt>true</tt>,
* for equality checks between Rationals a number <tt>deviation</tt> is used. Two Rationals <tt>r,s</tt> are supposed to be equal, if
* <tt>-deviation < r - s < deviation</tt>. <tt>deviation</tt> must be a field of the Rational class.<p>
* If <tt>PRESICE = false</tt> the same mechanism is used, but the computation is done by using doubles, which is faster but less precise.
* The two fields <tt>DEVIATION_DOUBLE</tt> and <tt>DEVIATIION_DOUBLE_NEG</tt> are implemented in the Rational class, too. All three deviation values are
* read from the actual Rational implemention and can be read from this class, then.
*/
public class RationalFactory {
/*
* fields
*/
static private Class RATIONAL_CLASS = null;
static private Boolean PRECISE = null;
static private Constructor INTEGER_CONSTRUCTOR = null;
static private Constructor DOUBLE_CONSTRUCTOR = null;
static private Constructor RATIONAL_CONSTRUCTOR = null;
static private Constructor NUM_DEN_CONSTRUCTOR = null;
static private Object[] PARAM_VALUE_LIST_1 = new Object[1];
static private Object[] PARAM_VALUE_LIST_2 = new Object[2];
/**
* A deviation value used for precise computations.
*/
static public Rational deviation;
/**
* A deviation value used for non-precise computations.
*/
static public double DEVIATION_DOUBLE;
/**
* A deviation value used for non-precise computations. Should be set to <tt>-1*DEVIATION_DOUBLE</tt>.
*/
static public double DEVIATION_DOUBLE_NEG;
/*
* constructors
*/
/**
* Don't use this constructor.
*/
private RationalFactory(){}
/*
* methods
*/
/**
* Defines the Rational extension class.
*
* @param ratClass the Rational implementation that shall be used
*/
static public void setClass(Class ratClass) {
RATIONAL_CLASS = ratClass;
}//end method setClass
/**
* Sets the <tt>PRECISE</tt> value.
*
* @param prec the value for <tt>PRECISE</tt>
*/
static public void setPrecision(boolean prec) {
PRECISE = new Boolean(prec);
Class [] classParam = { PRECISE.getClass() };
Rational r = constRational(0);
Object[] methParam = { PRECISE };
try {
Method m = RATIONAL_CLASS.getMethod("setPrecision", classParam);
m.invoke(r,methParam);
}//try
catch (Exception e) {
System.out.println("RationalFactory.setPrecision: Problems with method setPrecise.");
e.printStackTrace();
}//catch
}//end method setPrecision
/**
* Defines the Rational extension class.
*
* @param ratClass the name of the Rational class
* @throws RationalClassNotExistentException if the class doesn't exist
*/
static public void setClass(String ratClass) throws RationalClassNotExistentException {
try {
RATIONAL_CLASS = Class.forName(ratClass);
}//try
catch (Exception e) { throw new RationalClassNotExistentException("Error in RationalFactory: Class file "+ratClass+" was not found.");
}//catch
}//end method setClass
/**
* Returns the class of the currently used Rational implemention.
*
* @return the currently used Rational class
*/
static public Class readClass() {
return RATIONAL_CLASS;
}//end method getClass
/**
* Returns the actual <tt>deviation</tt> value.<p>
* Note: If <tt>PRECISE == true</tt>, the deviation value is returned, otherwise <tt>NULL</tt> is returned.
*
* @return the <tt>deviation</tt> value as Rational
* @throws NoDeviationValueFoundException if the deviation value was not implemented in the Rational class extension
*/
static public Rational readDeviation() throws NoDeviationValueFoundException {
if (PRECISE == null) {
System.out.println("WARNING: PRECISE should be set using RationalFactory.setPrecision()!\n...automatic definition to prevent program termination: PRECISE = TRUE");
PRECISE = new Boolean(true);
}//if
if (PRECISE.booleanValue()) {
Object res;
Rational obj = constRational(0);
try {
Field fi = RATIONAL_CLASS.getDeclaredField("deviation");
res = fi.get(obj);
return (Rational)res;
}//try
catch (Exception e) { throw new NoDeviationValueFoundException("Error in RationalFactory: No deviation value was found. It must be implemented in chosen Rational class.");
}//catch
}//if
else { return null; }
}//end method readDeviation
/**
* Returns the <tt>DEVIATION_DOUBLE</tt> value.<p>
* Additionally to the <tt>deviation</tt> value, <tt>DEVIATION_DOUBLE</tt> is defined which is a <tt>double</tt> value. Computations using this value
* instead of
* <tt>deviation</tt> are faster. Note, that this method needs a field <tt>DEVIATION_DOUBLE</tt> implemented in the Rational class extension.
*
* @return <tt>DEVIATION_DOUBLE</tt> as <tt>double</tt>
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws NoDeviationValueFoundException if <tt>DEVIATION_DOUBLE</tt> was not implemented
*/
static public double readDeviationDouble() throws RationalClassUndefinedException, NoDeviationValueFoundException {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be set using setClass().");
}//if
try {
Field fi = RATIONAL_CLASS.getDeclaredField("DEVIATION_DOUBLE");
Double obj = null;
DEVIATION_DOUBLE = ((Double)fi.get(obj)).doubleValue();
} catch (Exception e) { throw new NoDeviationValueFoundException("Error in RationalFactory: No DEVIATION_DOUBLE value was found in RATIONAL_CLASS ("+RATIONAL_CLASS+")."); }
return DEVIATION_DOUBLE;
}//end method readDeviationDouble
/**
* Returns the <tt>DEVIATION_DOUBLE_NEG</tt> value.<p>
* Additionally to the <tt>deviation</tt> value, <tt>DEVIATION_DOUBLE_NEG</tt> is defined which is a negative <tt>double</tt> value.
* Computations using a <tt>double</tt>
* value instead of a Rational value are faster. Note, that this method needs a field <tt>DEVIATION_DOUBLE_NEG</tt> implemented in the
* Rational class extension.
*
* @return <tt>DEVIATION_DOUBLE_NEG</tt> as <tt>double</tt>
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws NoDeviationValuefoundException if <tt>DEVIATION_DOUBLE_NEG</tt> was not implemented
*/
static public double readDeviationDoubleNeg() {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be seut using setClass().");
}//if
try {
Field fi = RATIONAL_CLASS.getDeclaredField("DEVIATION_DOUBLE_NEG");
Double obj = null;
DEVIATION_DOUBLE_NEG = ((Double)fi.get(obj)).doubleValue();
} catch (Exception e) { throw new NoDeviationValueFoundException("Error in RationalFactory: No DEVIATION_DOUBLE_NEG value was found in RATIONAL_CLASS ("+RATIONAL_CLASS+")."); }
return DEVIATION_DOUBLE_NEG;
}//end method readDeviationDoubleNeg
/**
* Returns the <tt>PRECISE</tt> value.
*
* @return the <tt>PRECISE</tt> value
*/
static public boolean readPrecise() {
if (PRECISE == null) {
System.out.println("WARNING: PRECISE should be set using RationalFactory.setPrecision()!\n...automatic definition to prevent program termination: PRECISE = TRUE");
PRECISE = new Boolean(true);
}//if
return PRECISE.booleanValue();
}//end method readPrecise
/**
* Constructs a new Rational instance with an <tt>int</tt>.
*
* @param i the <tt>int</tt> value
* @return the new Rational instance
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws RationalClassConstructorNotFoundException if the constructor for <tt>int</tt> values was not implemented
*/
static public Rational constRational(int i) throws RationalClassUndefinedException, RationalClassConstructorNotFoundException {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be set using setClass()");
}//if
else if (INTEGER_CONSTRUCTOR != null) {
PARAM_VALUE_LIST_1[0] = new Integer(i);
Rational rat = null;
try {
rat = (Rational)INTEGER_CONSTRUCTOR.newInstance(PARAM_VALUE_LIST_1);
}//try
catch (Exception e) {
System.out.println("Error in RationalFactory.constRational(integer): Couldn't create a new instance for integer["+i+"].");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}//catch
return rat;
}//else if
else {
Class[] paramClassList = { int.class };
Object[] paramValueList = { new Integer(i) };
Rational rat = null;
try {
INTEGER_CONSTRUCTOR = RATIONAL_CLASS.getConstructor(paramClassList);
rat = (Rational)INTEGER_CONSTRUCTOR.newInstance(paramValueList);
}//try
catch (Exception e) { throw new RationalClassConstructorNotFoundException("Error in RationalFactory: constructor "+RATIONAL_CLASS+"(int) not found"); }
return rat;
}//else
}//end method constRational
/**
* Constructs a new Rational instance with a <tt>double</tt>.
*
* @param d the <tt>double</tt> value
* @return the new Rational instance
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws RationalClassConstructorNotFoundException if the constructor for <tt>double</tt> values was not implemented
*/
static public Rational constRational(double d) throws RationalClassUndefinedException, RationalClassConstructorNotFoundException {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be set using setClass()");
}//if
else if (DOUBLE_CONSTRUCTOR != null) {
PARAM_VALUE_LIST_1[0] = new Double(d);
Rational rat = null;
try {
rat = (Rational)DOUBLE_CONSTRUCTOR.newInstance(PARAM_VALUE_LIST_1);
}//try
catch (Exception e) {
System.out.println("Error in RationalFactory.constRational(double): Couldn't create a new instance for double["+d+"].");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}//catch
return rat;
}//else if
else {
Class[] paramClassList = { double.class };
Object[] paramValueList = { new Double(d) };
Rational rat = null;
try {
DOUBLE_CONSTRUCTOR = RATIONAL_CLASS.getConstructor(paramClassList);
rat = (Rational)DOUBLE_CONSTRUCTOR.newInstance(paramValueList);
}//try
catch (Exception e) { throw new RationalClassConstructorNotFoundException("Error in RationalFactory: constructor "+RATIONAL_CLASS+"(double) not found"); }
return rat;
}//else
}//end method constRational
/**
* Constructs a new Rational instance with a Rational.
*
* @param r the Rational value
* @return the new Rational instance
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws RationalClassConstructorNotFoundException if the constructor for Rational values was not implemented
*/
static public Rational constRational(Rational r) throws RationalClassUndefinedException, RationalClassConstructorNotFoundException {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be set using setClass()");
}//if
else if (RATIONAL_CONSTRUCTOR != null) {
PARAM_VALUE_LIST_1[0]= r;
Rational rat = null;
try {
rat = (Rational)RATIONAL_CONSTRUCTOR.newInstance(PARAM_VALUE_LIST_1);
}//try
catch (Exception e) {
System.out.println("Error in RationalFactory.constRational(Rational): Couldn't create a new instance for Rational["+r+"].");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}//catch
return rat;
}//else if
else {
Class[] paramClassList = { Rational.class };
Object[] paramValueList = { r };
Rational rat;
try {
RATIONAL_CONSTRUCTOR = RATIONAL_CLASS.getConstructor(paramClassList);
rat = (Rational)RATIONAL_CONSTRUCTOR.newInstance(paramValueList);
}//try
catch (Exception e) { throw new RationalClassConstructorNotFoundException("Error in RationalFactory: constructor "+RATIONAL_CLASS+"(Rational) not found"); }
return rat;
}//else
}//end method constRational
/**
* Constructs a new Rational instance with two <tt>int</tt> values.
*
* @param num the numerator
* @param den the denominator
* @return the new Rational instance
* @throws RationalClassUndefinedException if the Rational class extension was not defined
* @throws RationalClassConstructorNotFoundException if the constructor for two <tt>int</tt> values was not implemented
*/
static public Rational constRational(int num, int den) throws RationalClassUndefinedException, RationalClassConstructorNotFoundException {
if (RATIONAL_CLASS == null) {
throw new RationalClassUndefinedException("Error in RationalFactory: RATIONAL_CLASS must be set using setClass()");
}//if
else if (NUM_DEN_CONSTRUCTOR != null) {
PARAM_VALUE_LIST_2[0] = new Integer(num);
PARAM_VALUE_LIST_2[1] = new Integer(den);
Rational rat = null;
try {
rat = (Rational)NUM_DEN_CONSTRUCTOR.newInstance(PARAM_VALUE_LIST_2);
}//try
catch (Exception e) {
System.out.println("Error in RationalFactory.constRational(int,int): Couldn't create a new instance for int x int ["+num+", "+den+"].");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}//catch
return rat;
}//else if
else {
Class[] paramClassList = { int.class, int.class };
Object[] paramValueList = { new Integer(num), new Integer(den) };
Rational rat;
try {
NUM_DEN_CONSTRUCTOR = RATIONAL_CLASS.getConstructor(paramClassList);
rat = (Rational)NUM_DEN_CONSTRUCTOR.newInstance(paramValueList);
}//try
catch (Exception e) { throw new RationalClassConstructorNotFoundException("Error in RationalFactory: constructor "+RATIONAL_CLASS+"(int int) not found"); }
return rat;
}//else
}//end method constRational
/**
* Sets the <tt>deviation</tt> field of the actual Rational class.
*
* @param r the new deviation value
*/
public static void setDeviation(Rational r) {
Class[] classParam = { RATIONAL_CLASS };
Object[] methParam = { r };
try {
Method m = RATIONAL_CLASS.getMethod("setDeviation", classParam);
m.invoke(r,methParam);
} catch (Exception e) {
System.out.println("RationalFactory.setDeviation: Problems with method setDeviation.");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}//catch
}//end method setDeviation
/**
* Sets the <tt>DEVIATION_DOUBLE</tt> and <tt>DEVIATION_DOUBLE_NEG</tt> fields of the actual Rational class.
*
* @param d the new deviation value
*/
public static void setDeviationDouble(double d){
Double dd = new Double(d);
Class[] classParam = { dd.getClass() };
Object[] methParam = { dd };
Rational r = constRational(0);
try {
Method m = RATIONAL_CLASS.getMethod("setDeviationDouble", classParam);
m.invoke(r,methParam);
} catch (Exception e) {
System.out.println("RationalFactory.setDeviationDouble: Problems with method setDeviationDouble.");
e.printStackTrace();
throw new RuntimeException("An error occurred in the ROSEAlgebra.");
}
}//end method setDeviationDouble
}//end class RationalFactory