/* --------------------------------------------------------- *
* __________ D E L T A S C R I P T *
* (_________() *
* / === / - A fast, dynamic scripting language *
* | == | - Version 4.13.11.0 *
* / === / - Developed by Adam R. Nelson *
* | = = | - 2011-2013 *
* / === / - Distributed under GNU LGPL v3 *
* (________() - http://github.com/ar-nelson/deltascript *
* *
* --------------------------------------------------------- */
package com.sector91.delta.script.objects;
import static com.sector91.delta.script.NumberTypes.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import com.sector91.delta.script.DScriptContext;
public final class ScalarFactory
{
private ScalarFactory() {}
public static DS_Scalar fromString(String str, DScriptContext context)
{
if ("true".equals(str) || "false".equals(str)) // Boolean
return DS_Boolean.box(Boolean.parseBoolean(str));
else if (str.indexOf('.')>-1 || str.indexOf('E')>-1) // Floating-point
{
switch (context.getDefaultFloatType())
{
case SHORT_FLOAT:
final float fval = Float.parseFloat(str);
if (!Float.isInfinite(fval))
return new DS_ShortFloatScalar(fval);
case LONG_FLOAT:
final double dval = Double.parseDouble(str);
if (!Double.isInfinite(dval))
return new DS_LongFloatScalar(dval);
case REAL_DECIMAL:
return new DS_RealDecimalScalar(new BigDecimal(str));
default:
throw new IllegalStateException(context.getDefaultFloatType() +
" is not a valid floating-point number type.");
}
}
else // Integer
{
switch (context.getDefaultIntType())
{
case SHORT_INT:
try
{return new DS_ShortIntScalar(Integer.parseInt(str));}
catch (NumberFormatException ex)
{/* Pass it on... */}
case LONG_INT:
try
{return new DS_LongIntScalar(Long.parseLong(str));}
catch (NumberFormatException ex)
{/* Pass it on... */}
case REAL_INT:
return new DS_RealIntScalar(new BigInteger(str));
default:
throw new IllegalStateException(context.getDefaultIntType() +
" is not a valid integral number type.");
}
}
}
public static DS_Scalar fromString(String str, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(Boolean.parseBoolean(str));
case SHORT_INT:
return new DS_ShortIntScalar(Integer.parseInt(str));
case LONG_INT:
return new DS_LongIntScalar(Long.parseLong(str));
case SHORT_FLOAT:
return new DS_ShortFloatScalar(Float.parseFloat(str));
case LONG_FLOAT:
return new DS_LongFloatScalar(Double.parseDouble(str));
case REAL_INT:
return new DS_RealIntScalar(new BigInteger(str));
case REAL_DECIMAL:
return new DS_RealDecimalScalar(new BigDecimal(str));
default:
return null;
}
}
public static DS_Integer fromInt(int n)
{return new DS_ShortIntScalar(n);}
public static DS_Integer fromLong(long n)
{return new DS_LongIntScalar(n);}
public static DS_Integer fromBigInteger(BigInteger n)
{return new DS_RealIntScalar(n);}
public static DS_Decimal fromFloat(float n)
{return new DS_ShortFloatScalar(n);}
public static DS_Decimal fromDouble(double n)
{return new DS_LongFloatScalar(n);}
public static DS_Decimal fromBigDecimal(BigDecimal n)
{return new DS_RealDecimalScalar(n);}
public static DS_Scalar fromNumber(int n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(n != 0);
case SHORT_INT:
return new DS_ShortIntScalar(n);
case LONG_INT:
return new DS_LongIntScalar(n);
case SHORT_FLOAT:
return new DS_ShortFloatScalar(n);
case LONG_FLOAT:
return new DS_LongFloatScalar(n);
case REAL_INT:
return new DS_RealIntScalar(BigInteger.valueOf(n));
case REAL_DECIMAL:
return new DS_RealDecimalScalar(BigDecimal.valueOf(n));
default:
return null;
}
}
public static DS_Scalar fromNumber(float n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(n != 0);
case SHORT_INT:
return new DS_ShortIntScalar((int)n);
case LONG_INT:
return new DS_LongIntScalar((long)n);
case SHORT_FLOAT:
return new DS_ShortFloatScalar(n);
case LONG_FLOAT:
return new DS_LongFloatScalar(n);
case REAL_INT:
return new DS_RealIntScalar(BigInteger.valueOf((long)n));
case REAL_DECIMAL:
return new DS_RealDecimalScalar(BigDecimal.valueOf(n));
default:
return null;
}
}
public static DS_Scalar fromNumber(long n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(n != 0);
case SHORT_INT:
return new DS_ShortIntScalar((int)n);
case LONG_INT:
return new DS_LongIntScalar(n);
case SHORT_FLOAT:
return new DS_ShortFloatScalar(n);
case LONG_FLOAT:
return new DS_LongFloatScalar(n);
case REAL_INT:
return new DS_RealIntScalar(BigInteger.valueOf(n));
case REAL_DECIMAL:
try
{return new DS_RealDecimalScalar(BigDecimal.valueOf(n));}
catch (NumberFormatException ex)
{return new DS_LongFloatScalar(n);}
default:
return null;
}
}
public static DS_Scalar fromNumber(double n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(n != 0);
case SHORT_INT:
return new DS_ShortIntScalar((int)n);
case LONG_INT:
return new DS_LongIntScalar((long)n);
case SHORT_FLOAT:
return new DS_ShortFloatScalar((float)n);
case LONG_FLOAT:
return new DS_LongFloatScalar(n);
case REAL_INT:
return new DS_RealIntScalar(BigInteger.valueOf((long)n));
case REAL_DECIMAL:
try
{return new DS_RealDecimalScalar(BigDecimal.valueOf(n));}
catch (NumberFormatException ex)
{return new DS_LongFloatScalar(n);}
default:
return null;
}
}
public static DS_Scalar fromNumber(BigInteger n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(!n.equals(BigInteger.ZERO));
case SHORT_INT:
return new DS_ShortIntScalar(n.intValue());
case LONG_INT:
return new DS_LongIntScalar(n.longValue());
case SHORT_FLOAT:
return new DS_ShortFloatScalar(n.floatValue());
case LONG_FLOAT:
return new DS_LongFloatScalar(n.doubleValue());
case REAL_INT:
return new DS_RealIntScalar(n);
case REAL_DECIMAL:
return new DS_RealDecimalScalar(new BigDecimal(n));
default:
return null;
}
}
public static DS_Scalar fromNumber(BigDecimal n, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(!n.equals(BigDecimal.ZERO));
case SHORT_INT:
return new DS_ShortIntScalar(n.intValue());
case LONG_INT:
return new DS_LongIntScalar(n.longValue());
case SHORT_FLOAT:
return new DS_ShortFloatScalar(n.floatValue());
case LONG_FLOAT:
return new DS_LongFloatScalar(n.doubleValue());
case REAL_INT:
return new DS_RealIntScalar(n.toBigInteger());
case REAL_DECIMAL:
return new DS_RealDecimalScalar(n);
default:
return null;
}
}
public static DS_Scalar fromBoolean(boolean b, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(b);
case SHORT_INT:
return new DS_ShortIntScalar(b?1:0);
case LONG_INT:
return new DS_LongIntScalar(b?1:0);
case SHORT_FLOAT:
return new DS_ShortFloatScalar(b?1f:0f);
case LONG_FLOAT:
return new DS_LongFloatScalar(b?1d:0d);
case REAL_INT:
return new DS_RealIntScalar(b?BigInteger.ONE:BigInteger.ZERO);
case REAL_DECIMAL:
return new DS_RealDecimalScalar(b?BigDecimal.ONE:BigDecimal.ZERO);
default:
return null;
}
}
public static DS_Scalar add(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(s1.intValue()+s2.intValue() != 0);
case SHORT_INT:
return fromNumber(s1.intValue()+s2.intValue(), nType);
case LONG_INT:
return fromNumber(s1.longValue()+s2.longValue(), nType);
case SHORT_FLOAT:
return fromNumber(s1.floatValue()+s2.floatValue(), nType);
case LONG_FLOAT:
return fromNumber(s1.doubleValue()+s2.doubleValue(), nType);
case REAL_INT:
return fromNumber(s1.bigIntegerValue().add(s2.bigIntegerValue()),
nType);
case REAL_DECIMAL:
try
{
return fromNumber(s1.bigDecimalValue().add(
s2.bigDecimalValue()), nType);
}
catch (NumberFormatException ex) // If Infinity/NaN encountered...
{
// ... then revert to double, which can represent these values.
return fromNumber(s1.doubleValue()+s2.doubleValue(),LONG_FLOAT);
}
default:
return null;
}
}
public static DS_Scalar sub(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(s1.intValue()-s2.intValue() != 0);
case SHORT_INT:
return fromNumber(s1.intValue()-s2.intValue(), nType);
case LONG_INT:
return fromNumber(s1.longValue()-s2.longValue(), nType);
case SHORT_FLOAT:
return fromNumber(s1.floatValue()-s2.floatValue(), nType);
case LONG_FLOAT:
return fromNumber(s1.doubleValue()-s2.doubleValue(), nType);
case REAL_INT:
return fromNumber(s1.bigIntegerValue().subtract(
s2.bigIntegerValue()), nType);
case REAL_DECIMAL:
try
{
return fromNumber(s1.bigDecimalValue().subtract(
s2.bigDecimalValue()), nType);
}
catch (NumberFormatException ex) // If Infinity/NaN encountered...
{
// ... then revert to double, which can represent these values.
return fromNumber(s1.doubleValue()-s2.doubleValue(),LONG_FLOAT);
}
default:
return null;
}
}
public static DS_Scalar mul(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(s1.intValue()*s2.intValue() != 0);
case SHORT_INT:
return fromNumber(s1.intValue()*s2.intValue(), nType);
case LONG_INT:
return fromNumber(s1.longValue()*s2.longValue(), nType);
case SHORT_FLOAT:
return fromNumber(s1.floatValue()*s2.floatValue(), nType);
case LONG_FLOAT:
return fromNumber(s1.doubleValue()*s2.doubleValue(), nType);
case REAL_INT:
return fromNumber(s1.bigIntegerValue().multiply(
s2.bigIntegerValue()), nType);
case REAL_DECIMAL:
try
{
return fromNumber(s1.bigDecimalValue().multiply(
s2.bigDecimalValue()), nType);
}
catch (NumberFormatException ex) // If Infinity/NaN encountered...
{
// ... then revert to double, which can represent these values.
return fromNumber(s1.doubleValue()*s2.doubleValue(),LONG_FLOAT);
}
default:
return null;
}
}
public static DS_Scalar div(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(s1.intValue()/s2.intValue() != 0);
case SHORT_INT:
return fromNumber(s1.intValue()/s2.intValue(), nType);
case LONG_INT:
return fromNumber(s1.longValue()/s2.longValue(), nType);
case SHORT_FLOAT:
return fromNumber(s1.floatValue()/s2.floatValue(), nType);
case LONG_FLOAT:
return fromNumber(s1.doubleValue()/s2.doubleValue(), nType);
case REAL_INT:
return fromNumber(s1.bigIntegerValue().divide(
s2.bigIntegerValue()), nType);
case REAL_DECIMAL:
try
{
return fromNumber(s1.bigDecimalValue().divide(
s2.bigDecimalValue()), nType);
}
catch (NumberFormatException ex) // If Infinity/NaN encountered...
{
// ... then revert to double, which can represent these values.
return fromNumber(s1.doubleValue()/s2.doubleValue(),LONG_FLOAT);
}
default:
return null;
}
}
public static DS_Scalar mod(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(s1.intValue()%s2.intValue() != 0);
case SHORT_INT:
return fromNumber(s1.intValue()%s2.intValue(), nType);
case LONG_INT:
return fromNumber(s1.longValue()%s2.longValue(), nType);
case SHORT_FLOAT:
return fromNumber(s1.floatValue()%s2.floatValue(), nType);
case LONG_FLOAT:
return fromNumber(s1.doubleValue()%s2.doubleValue(), nType);
// The remainder() operation has the same negative-number behavior as
// Java's % operator, even though it is not a "correct" mod operator.
case REAL_INT:
return fromNumber(s1.bigIntegerValue().remainder(
s2.bigIntegerValue()), nType);
case REAL_DECIMAL:
try
{
return fromNumber(s1.bigDecimalValue().remainder(
s2.bigDecimalValue()), nType);
}
catch (NumberFormatException ex) // If Infinity/NaN encountered...
{
// ... then revert to double, which can represent these values.
return fromNumber(s1.doubleValue()%s2.doubleValue(),LONG_FLOAT);
}
default:
return null;
}
}
public static DS_Scalar exp(DS_Scalar s1, DS_Scalar s2, int nType)
{
switch (nType)
{
case BOOL:
return DS_Boolean.box(Math.pow(
s1.doubleValue(), s2.doubleValue()) != 0);
case SHORT_INT:
return fromNumber((int)Math.pow(s1.intValue(), s2.intValue()),
nType);
case LONG_INT:
return fromNumber((long)Math.pow(s1.longValue(), s2.longValue()),
nType);
case SHORT_FLOAT:
return fromNumber((float)Math.pow(s1.floatValue(), s2.floatValue()),
nType);
case LONG_FLOAT:
return fromNumber(Math.pow(s1.doubleValue(), s2.doubleValue()),
nType);
case REAL_INT:
return fromNumber(s1.bigIntegerValue().pow(s2.intValue()), nType);
case REAL_DECIMAL:
try
{
// FIXME: Loss of precision; figure out how to exp BigDecimal.
final BigDecimal decimal = s2.bigDecimalValue();
if (decimal.equals(BigDecimal.valueOf(decimal.intValue())))
return fromNumber(s1.bigDecimalValue().pow(
decimal.intValue()), nType);
}
catch (NumberFormatException ex)
{/* Just give up and use doubles. */}
catch (ArithmeticException ex)
{/* Just give up and use doubles. */}
return fromNumber(Math.pow(s1.doubleValue(), s2.doubleValue()),
LONG_FLOAT);
default:
return null;
}
}
}