//
// Real.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad;
import java.rmi.*;
/**
* Real is the class of VisAD scalar data for real numbers represented
* as double precision floating point values. Double.NaN is used to
* indicate missing values, because it has the appropriate arithmetic
* semantics. Real objects are immutable.<P>
*/
public class Real
extends Scalar
implements RealIface
{
private final double Value;
private final Unit unit;
private final ErrorEstimate Error;
/**
* Constructs a Real object. This is the most general constructor.
* @param type The type of the Real.
* @param value The value of the Real. May be
* <code>Double.NaN</code>.
* @param u The unit of the Real. May be <code>null</code>.
* If non-<code>null</code> and
* <code>type.isInterval()</code> returns true,
* then the unit will actually be
* <code>u.getAbsoluteUnit()</code>.
* @param error Error estimate of the Real. May be
* <code>null</code>.
* @throws UnitException if the default unit of the type is inconvertible
* with the unit argument (i.e. if <code>
* Unit.canConvert(u, type.getDefaultUnit())</code>
* returns false).
* @throws VisADException Couldn't create necessary VisAD object.
*/
public Real(RealType type, double value, Unit u, ErrorEstimate error)
throws VisADException {
super(type);
if (!Unit.canConvert(u, type.getDefaultUnit())) {
throw new UnitException("Real: Unit \"" + u +
"\" must be convertable" +
" with Type default Unit \"" +
type.getDefaultUnit() + "\"");
}
unit = u != null && type.isInterval() ? u.getAbsoluteUnit() : u;
Value = value;
Error = Double.isNaN(value) ? null : error;
}
/**
* Constructs a Real object. The error estimate will be based on a numeric
* value.
* @param type The type of the Real.
* @param value The value of the Real. May be
* <code>Double.NaN</code>.
* @param u The unit of the Real. May be <code>null</code>.
* If non-<code>null</code> and
* <code>type.isInterval()</code> returns true,
* then the unit will actually be
* <code>u.getAbsoluteUnit()</code>.
* @param error Value for constructing an error estimate for the
* Real in units of <code>u != null &&
* type.isInterval() ? u.getAbsoluteUnit() :
* u</code>.
* @throws VisADException Couldn't create necessary VisAD object.
*/
public Real(RealType type, double value, Unit u, double error)
throws VisADException {
this(type, value, u,
new ErrorEstimate(value, Math.abs(error),
u != null && type.isInterval() ? u.getAbsoluteUnit() : u));
}
/**
* Constructs a Real object. The error estimate will be <code>null</code>.
* @param type The type of the Real.
* @param value The value of the Real. May be
* <code>Double.NaN</code>.
* @param u The unit of the Real. May be <code>null</code>.
* If non-<code>null</code> and
* <code>type.isInterval()</code> returns true,
* then the unit will actually be
* <code>u.getAbsoluteUnit()</code>.
* @throws VisADException Couldn't create necessary VisAD object.
*/
public Real(RealType type, double value, Unit u)
throws VisADException {
this(type, value, u, null);
}
/**
* Constructs a Real object. The unit of the Real will be the default unit of
* the RealType and the error estimate will be <code>null</code>.
* @param type The type of the Real.
* @param value The value of the Real in units of
* <code>type.getDefaultUnit()</code>. May be
* <code>Double.NaN</code>.
*/
public Real(RealType type, double value) {
this(type, value, type.getDefaultUnit(), null, false);
}
/**
* Constructs a Real object. The value will be missing, the unit of the
* Real will be the default unit of the RealType, and the error estimate
* will be <code>null</code>.
* @param type The type of the Real.
*/
public Real(RealType type) {
this(type, Double.NaN, type.getDefaultUnit(), null, false);
}
/**
* Constructs a generic Real object. The RealType of the Real will be
* <code>RealType.Generic</code>, the unit of the Real will be
* <code>RealType.Generic.getDefaultUnit()</code>, and the error estimate
* will be based on a numeric value.
* @param value The value of the Real. May be
* <code>Double.NaN</code>.
* @param error Value for constructing an error estimate for the
* Real in units of
* <code>RealType.Generic.getDefaultUnit()</code>.
*/
public Real(double value, double error) {
this(RealType.Generic, value, RealType.Generic.getDefaultUnit(),
new ErrorEstimate(value, Math.abs(error), RealType.Generic.getDefaultUnit()),
false);
}
/**
* Constructs a generic Real object. The RealType of the Real will be
* <code>RealType.Generic</code>, the unit of the Real will be
* <code>RealType.Generic.getDefaultUnit()</code>, and the error estimate
* will be 0.0.
* @param value The value of the Real. May be
* <code>Double.NaN</code>.
*/
public Real(double value) {
this(RealType.Generic, value, RealType.Generic.getDefaultUnit(),
new ErrorEstimate(value, 0.0, RealType.Generic.getDefaultUnit()), false);
}
/** trusted constructor for other constructors */
protected Real(RealType type, double value, Unit u, ErrorEstimate error,
boolean checkUnit) {
super(type);
if(u !=null && checkUnit && !Unit.canConvert(u, type.getDefaultUnit())) {
throw new IllegalArgumentException("Real: Unit \"" + u +
"\" must be convertable" +
" with Type default Unit \"" +
type.getDefaultUnit() + "\"");
}
unit = u != null && type.isInterval() ? u.getAbsoluteUnit() : u;
Value = value;
Error = Double.isNaN(value) ? null : error;
}
/**
* Get the value for this Real in the units of the data.
* @return value as a double.
*/
public final double getValue() {
return Value;
}
/**
* Methods for Jython comparisons with doubles and other Reals
*
* @return =0 for false, =1 for true
*/
public int __gt__(double other) {
if (Value > other) return 1;
return 0;
}
public int __lt__(double other) {
if (Value < other) return 1;
return 0;
}
public int __ge__(double other) {
if (Value >= other) return 1;
return 0;
}
public int __le__(double other) {
if (Value <= other) return 1;
return 0;
}
public int __ne__(double other) {
if (Value != other) return 1;
return 0;
}
public int __eq__(double other) {
if (Value == other) return 1;
return 0;
}
public int __gt__(Real other) throws VisADException, RemoteException {
if (other == null) return 0;
double d = ((Real) subtract(other)).getValue();
if (d > 0.0) return 1;
return 0;
}
public int __lt__(Real other) throws VisADException, RemoteException {
if (other == null) return 0;
double d = ((Real) subtract(other)).getValue();
if (d < 0.0) return 1;
return 0;
}
public int __ge__(Real other) throws VisADException, RemoteException {
if (other == null) return 0;
double d = ((Real) subtract(other)).getValue();
if (d >= 0.0) return 1;
return 0;
}
public int __le__(Real other) throws VisADException, RemoteException {
if (other == null) return 0;
double d = ((Real) subtract(other)).getValue();
if (d <= 0.0) return 1;
return 0;
}
public int __eq__(Real other) throws VisADException, RemoteException {
if (other == null) return 0;
double d = ((Real) subtract(other)).getValue();
if (d == 0.0) return 1;
return 0;
}
public int __ne__(Real other) throws VisADException, RemoteException {
if (other == null) return 1;
double d = ((Real) subtract(other)).getValue();
if (d != 0.0) return 1;
return 0;
}
// The following methods were removed to allow use of Jython
// versions beyond 2.2. The issue was that for overloaded methods
// the newer Jython interpreters might select the wrong method
// if another one passed in a Class that had a __float__() or
// other "casting" signature.
/**
* Methods to convert types for Jython
*
* @return this Real as a float, long, or int
*
*/
/*
public double __float__() {
return Value;
}
public long __long__() {
return (long) Value;
}
public int __int__() {
return (int) Value;
}
*/
/** get double value converted to unit_out */
/**
* Get the value for this Real converted to unit_out.
* @param unit_out unit for return value
* @return value in unit_out units.
* @throws VisADException if either the Real's Unit or the unit_out
* is null (but not both).
*/
public final double getValue(Unit unit_out) throws VisADException {
if (unit_out == null) {
if (unit != null) { // can't convert to null unit
throw new UnitException("Real.getValue: illegal Unit conversion");
}
return Value;
}
else {
if (unit == null) { // unit_out not null, but unit is
throw new UnitException("Real.getValue: illegal Unit conversion");
}
if (((RealType)getType()).isInterval())
unit_out = unit_out.getAbsoluteUnit();
return unit_out.toThis(Value, unit);
}
}
/**
* Check to see if the value of this Real is a NaN.
* @return true if a NaN.
*/
public boolean isMissing() {
// note inf and -inf have proper semantics and are not missing
return (Double.isNaN(Value));
}
/*- TDR May 1998
public Data binary(Data data, int op, int sampling_mode, int error_mode)
throws VisADException, RemoteException {
*/
public Data binary(Data data, int op, MathType new_type,
int sampling_mode, int error_mode )
throws VisADException, RemoteException {
/*- TDR May 1998 */
if ( new_type == null ) {
throw new TypeException("binary: new_type may not be null");
}
/*- end */
if (data instanceof Real) {
Real that = (Real)data;
/*- TDR May 28 1998 */
if ( !(new_type instanceof RealType) ) {
throw new TypeException("binary: new_type doesn't match return type");
}
/*- end */
Unit thisUnit = getUnit();
Unit thatUnit = that.getUnit();
double thisValue = getValue();
double thatValue = that.getValue();
ErrorEstimate thisErr = getError();
ErrorEstimate thatErr = that.getError();
Unit outUnit = null; // default; the following switch might set
double outValue = Double.NaN;
/*
* Set the output value. If possible, he output unit is first determined
* and then the output numeric value.
*/
switch (op) {
case ADD:
case SUBTRACT:
case INV_SUBTRACT:
case MAX:
case MIN:
if (thisUnit == null || thatUnit == null) {
outUnit = null;
}
else if (thisUnit == CommonUnit.promiscuous) {
outUnit = thatUnit.getAbsoluteUnit();
}
else if (thatUnit == CommonUnit.promiscuous) {
outUnit = thisUnit.getAbsoluteUnit();
}
else {
try {
outUnit = thisUnit.getAbsoluteUnit();
thisValue = outUnit.toThis(thisValue, thisUnit);
thatValue = outUnit.toThis(thatValue, thatUnit);
if (error_mode != NO_ERRORS
&& thisErr != null && thatErr != null) {
if (!outUnit.equals(thisUnit)) {
Unit errUnit = thisErr.getUnit();
if (errUnit == null)
errUnit = thisUnit;
double newErr =
outUnit.toThis(thisErr.getErrorValue(), errUnit);
thisErr = new ErrorEstimate(thisValue, newErr, outUnit);
}
if (!outUnit.equals(thatUnit)) {
Unit errUnit = thatErr.getUnit();
if (errUnit == null)
errUnit = thatUnit;
double newErr =
outUnit.toThis(thatErr.getErrorValue(), errUnit);
thatErr = new ErrorEstimate(thatValue, newErr, outUnit);
}
}
}
catch (UnitException e) { // inconvertible units
outUnit = null;
}
}
switch (op) {
case ADD:
outValue = thisValue + thatValue;
break;
case SUBTRACT:
outValue = thisValue - thatValue;
break;
case INV_SUBTRACT:
outValue = thatValue - thisValue;
break;
case MAX:
outValue = Math.max(thisValue, thatValue);
break;
case MIN:
outValue = Math.min(thisValue, thatValue);
break;
}
break;
case MULTIPLY:
case DIVIDE:
case INV_DIVIDE:
if (thisUnit != null) {
Unit absUnit = thisUnit.getAbsoluteUnit();
thisValue = absUnit.toThis(thisValue, thisUnit);
thisUnit = absUnit;
}
if (thatUnit != null) {
Unit absUnit = thatUnit.getAbsoluteUnit();
thatValue = absUnit.toThis(thatValue, thatUnit);
thatUnit = absUnit;
}
if (thisUnit == null || thatUnit == null) {
outUnit = null;
}
else {
switch(op) {
case MULTIPLY:
outUnit =
thisUnit.equals(CommonUnit.promiscuous)
? thatUnit
: thatUnit.equals(CommonUnit.promiscuous)
? thisUnit
: thisUnit.multiply(thatUnit);
break;
case DIVIDE:
outUnit =
thatUnit.equals(CommonUnit.promiscuous)
? thisUnit
: thisUnit.divide(thatUnit);
break;
case INV_DIVIDE:
outUnit =
thisUnit.equals(CommonUnit.promiscuous)
? thatUnit
: thatUnit.divide(thisUnit);
break;
}
}
switch(op) {
case MULTIPLY:
outValue = thisValue * thatValue;
break;
case DIVIDE:
outValue = thisValue / thatValue;
break;
case INV_DIVIDE:
outValue = thatValue / thisValue;
break;
}
break;
case POW:
if (thisUnit != null) {
Unit absUnit = thisUnit.getAbsoluteUnit();
thisValue = absUnit.toThis(thisValue, thisUnit);
thisUnit = absUnit;
}
if (thatUnit != null && !CommonUnit.promiscuous.equals(unit)) {
Unit absUnit = thatUnit.getAbsoluteUnit();
thatValue = absUnit.toThis(thatValue, thatUnit);
thatUnit = absUnit;
}
if (thisUnit != null && (
thisUnit.equals(CommonUnit.promiscuous) ||
thisUnit.equals(CommonUnit.dimensionless))) {
outUnit = thisUnit;
}
else {
outUnit = null;
}
outValue = Math.pow(thisValue, thatValue);
break;
case INV_POW:
if (thatUnit != null) {
Unit absUnit = thatUnit.getAbsoluteUnit();
thatValue = absUnit.toThis(thatValue, thatUnit);
thatUnit = absUnit;
}
if (thisUnit != null && !CommonUnit.promiscuous.equals(unit)) {
Unit absUnit = thisUnit.getAbsoluteUnit();
thisValue = absUnit.toThis(thisValue, thisUnit);
thisUnit = absUnit;
}
if (thatUnit != null && (
thatUnit.equals(CommonUnit.promiscuous) ||
thatUnit.equals(CommonUnit.dimensionless))) {
outUnit = thatUnit;
}
else {
outUnit = null;
}
outValue = Math.pow(thatValue, thisValue);
break;
case ATAN2:
case ATAN2_DEGREES:
case INV_ATAN2:
case INV_ATAN2_DEGREES:
case REMAINDER:
case INV_REMAINDER:
if (thisUnit != null && thatUnit != null) {
Unit absUnit = thisUnit.getAbsoluteUnit();
thisValue = absUnit.toThis(thisValue, thisUnit);
thatValue = absUnit.toThis(thatValue, thatUnit);
thisUnit = absUnit;
thatUnit = absUnit;
}
switch(op) {
case ATAN2:
outValue = Math.atan2(thisValue, thatValue);
outUnit = CommonUnit.radian;
break;
case ATAN2_DEGREES:
outValue =
Data.RADIANS_TO_DEGREES * Math.atan2(thisValue, thatValue);
outUnit = CommonUnit.degree;
break;
case INV_ATAN2:
outValue = Math.atan2(thatValue, thisValue);
outUnit = CommonUnit.radian;
break;
case INV_ATAN2_DEGREES:
outValue =
Data.RADIANS_TO_DEGREES * Math.atan2(thatValue, thisValue);
outUnit = CommonUnit.degree;
break;
case REMAINDER:
outValue = thisValue % thatValue;
outUnit = thisUnit;
break;
case INV_REMAINDER:
outValue = thatValue % thisValue;
outUnit = thatUnit;
break;
}
break;
default:
throw new ArithmeticException("Real.binary: illegal operation");
}
if (error_mode == NO_ERRORS || thisErr == null || thatErr == null) {
return new Real(((RealType) new_type), outValue, outUnit, null);
}
else {
return new Real(((RealType) new_type), outValue, outUnit,
new ErrorEstimate(outValue, outUnit, op, thisErr, thatErr,
error_mode));
}
}
else if (data instanceof Text) {
throw new TypeException("Real.binary: types don't match");
}
else if (data instanceof TupleIface) {
/* BINARY - TDR May 28, 1998
return data.binary(this, invertOp(op), sampling_mode, error_mode);
*/
/* BINARY - TDR June 5, 1998 */
if ( !(data.getType()).equalsExceptName(new_type) ) {
throw new TypeException();
}
return data.binary(this, invertOp(op), new_type, sampling_mode, error_mode);
/* BINARY - end */
}
else if (data instanceof Field) {
/* BINARY - TDR May 28, 1998
return data.binary(this, invertOp(op), sampling_mode, error_mode);
*/
/* BINARY - TDR June 5, 1998 */
if ( !(data.getType()).equalsExceptName(new_type) ) {
throw new TypeException();
}
return data.binary(this, invertOp(op), new_type, sampling_mode, error_mode);
/* BINARY - end */
}
else {
throw new TypeException("Real.binary");
}
}
/** unary function on a Real; override some trig functions based
on Unit; transcental functions destroy dimensionfull Unit */
public Data unary(int op, MathType new_type, int sampling_mode, int error_mode)
throws VisADException {
Unit thisUnit; // input unit
double thisValue; // input value
if (unit == null) {
thisUnit = null;
thisValue = Value;
}
else {
/*
* Condition input numeric value and unit. If the input unit is
* dimensionless, then the input numeric value is converted to be in units
* of the dimensionless unit 1; otherwise, the input numeric value is
* converted to be in units of the absolute unit of the input unit.
*/
thisUnit = Unit.canConvert(CommonUnit.dimensionless, unit)
? CommonUnit.dimensionless : unit.getAbsoluteUnit();
thisValue = thisUnit.toThis(Value, unit);
}
double value; // output value
Unit u; // output unit
/*- TDR June 1998 */
if ( new_type == null ) {
throw new TypeException("unary: new_type may not be null");
}
switch (op) {
case ABS:
value = Math.abs(thisValue);
u = thisUnit;
break;
case ACOS:
value = Math.acos(thisValue);
u = CommonUnit.radian;
break;
case ACOS_DEGREES:
value = Data.RADIANS_TO_DEGREES * Math.acos(thisValue);
u = CommonUnit.degree;
break;
case ASIN:
value = Math.asin(thisValue);
u = CommonUnit.radian;
break;
case ASIN_DEGREES:
value = Data.RADIANS_TO_DEGREES * Math.asin(thisValue);
u = CommonUnit.degree;
break;
case ATAN:
value = Math.atan(thisValue);
u = CommonUnit.radian;
break;
case ATAN_DEGREES:
value = Data.RADIANS_TO_DEGREES * Math.atan(thisValue);
u = CommonUnit.degree;
break;
case CEIL:
value = Math.ceil(thisValue);
u = thisUnit;
break;
case COS:
// do cos in radians, unless unit is degrees
value = CommonUnit.degree.equals(thisUnit) ?
Math.cos(Data.DEGREES_TO_RADIANS * thisValue) : Math.cos(thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case COS_DEGREES:
// do cos in degrees, unless unit is radians
value = CommonUnit.radian.equals(thisUnit) ?
Math.cos(thisValue) : Math.cos(Data.DEGREES_TO_RADIANS * thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case EXP:
value = Math.exp(thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case FLOOR:
value = Math.floor(thisValue);
u = thisUnit;
break;
case LOG:
value = Math.log(thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case RINT:
value = Math.rint(thisValue);
u = thisUnit;
break;
case ROUND:
value = Math.round(thisValue);
u = thisUnit;
break;
case SIN:
// do sin in radians, unless unit is degrees
value = CommonUnit.degree.equals(thisUnit) ?
Math.sin(Data.DEGREES_TO_RADIANS * thisValue) : Math.sin(thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case SIN_DEGREES:
// do sin in degrees, unless unit is radians
value = CommonUnit.radian.equals(thisUnit) ?
Math.sin(thisValue) : Math.sin(Data.DEGREES_TO_RADIANS * thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case SQRT:
value = Math.sqrt(thisValue);
// WLH 26 Nov 2001
// u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
if (thisUnit == null) {
u = null;
}
else {
try {
u = thisUnit.sqrt();
}
catch (IllegalArgumentException e) {
u = null;
}
catch (UnitException e) {
u = null;
}
}
break;
case TAN:
// do tan in radians, unless unit is degrees
value = CommonUnit.degree.equals(thisUnit) ?
Math.tan(Data.DEGREES_TO_RADIANS * thisValue) : Math.tan(thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case TAN_DEGREES:
// do tan in degrees, unless unit is radians
value = CommonUnit.radian.equals(thisUnit) ?
Math.tan(thisValue) : Math.tan(Data.DEGREES_TO_RADIANS * thisValue);
u = CommonUnit.dimensionless.equals(thisUnit) ? thisUnit : null;
break;
case NEGATE:
value = -thisValue;
u = thisUnit;
break;
case NOP:
value = thisValue;
u = thisUnit;
break;
default:
throw new ArithmeticException("Real.unary: illegal operation");
}
if (error_mode == NO_ERRORS || Error == null) {
/*- TDR June 1998
return new Real(((RealType) Type), value, u, null);
*/
return new Real((RealType) new_type, value, u, null);
}
else {
/*- TDR June 1998
return new Real(((RealType) Type), value, u,
new ErrorEstimate(value, u, op, Error, error_mode));
*/
return new Real((RealType) new_type, value, u,
new ErrorEstimate(value, u, op, Error, error_mode));
}
}
public DataShadow computeRanges(ShadowType type, DataShadow shadow)
throws VisADException, RemoteException {
if (Double.isNaN(Value)) return shadow;
int i = ((ShadowRealType) type).getIndex();
if (i >= 0) {
double value;
Unit dunit = ((RealType) Type).getDefaultUnit();
if (dunit != null && !dunit.equals(unit)) {
value = dunit.toThis(Value, unit);
}
else {
value = Value;
}
if (value == value) {
shadow.ranges[0][i] = Math.min(shadow.ranges[0][i], value);
shadow.ranges[1][i] = Math.max(shadow.ranges[1][i], value);
}
}
return shadow;
}
public Unit getUnit() {
return unit;
}
public ErrorEstimate getError() {
return Error;
}
/** return a Real that clones this, except its ErrorEstimate
is adjusted for the sampling error in error */
public Data adjustSamplingError(Data error, int error_mode)
throws VisADException, RemoteException {
if (isMissing() || Error == null ||
error == null || error.isMissing()) return this;
double a = ((Real) error).getValue();
double b = Error.getErrorValue();
double e = (error_mode == INDEPENDENT) ? Math.sqrt(a * a + b * b) :
Math.abs(a) + Math.abs(b);
return new Real((RealType) Type, Value, unit,
new ErrorEstimate(Value, e, unit));
}
/** clone this, but with a new value */
public Real cloneButValue(double value) throws VisADException {
return new Real((RealType) Type, value, unit, Error, true);
}
/** clone this, but with a new Unit */
public Real cloneButUnit(Unit u) throws VisADException {
return new Real((RealType) Type, Value, u, Error);
}
public String toString() {
try {
if (Double.isNaN(Value)) {
return "missing";
}
else {
return
(Unit.canConvert(getUnit(), CommonUnit.secondsSinceTheEpoch) &&
!getUnit().getAbsoluteUnit().equals(getUnit()))
? new DateTime(this).toString()
: Double.toString(Value);
}
}
catch (VisADException e) {
return e.toString();
}
}
/**
* Gets a string that represents just the value portion of this Real -- but
* with full semantics (e.g. numeric value and unit).
* @return A string representation of just the value
* portion of this Real.
*/
public String toValueString() {
String result;
try {
if (Double.isNaN(Value)) {
result = "missing";
}
else {
if (Unit.canConvert(getUnit(), CommonUnit.secondsSinceTheEpoch) &&
!getUnit().getAbsoluteUnit().equals(getUnit())) {
result = new DateTime(this).toValueString();
}
else {
Unit u =
unit != null ? unit : ((RealType)getType()).getDefaultUnit();
result = Float.toString((float)Value) + (u == null ? "" : " " + u);
}
}
}
catch (VisADException e) {
result = e.toString();
}
return result;
}
public String longString(String pre) throws VisADException {
if (Double.isNaN(Value)) {
return pre + "missing\n";
}
else if (Unit.canConvert(getUnit(), CommonUnit.secondsSinceTheEpoch) &&
!getUnit().getAbsoluteUnit().equals(getUnit())) {
return pre + "Real.Time: Value = " +
new DateTime(this).toString() + "\n";
}
else {
return pre + "Real: Value = " + Value +
" (TypeName: " + ((RealType) Type).getName() + ")\n";
}
}
/**
* Compares this Real to another.
* @param object The other Real to compare against. It shall be
* a Real with a compatible (i.e. convertible)
* unit.
* @return A negative integer, zero, or a positive integer
* depending on whether this Real is considered
* less than, equal to, or greater than the other
* Real, respectively. If the values of the Real-s
* in the default unit are equal, then the <code>
* ErrorEstimate.compareTo()</code> method is used
* to break the tie.
*/
public int compareTo(Object object)
{
Real that = (Real)object;
int comp;
try
{
Unit defaultUnit = ((RealType)getType()).getDefaultUnit();
comp = new Double(getValue(defaultUnit)).compareTo(
new Double(that.getValue(defaultUnit)));
if (comp == 0) {
if (Error == null) {
comp = that.Error == null ? 0 : -1;
}
else if (that.Error == null) {
comp = 1;
}
else {
comp = Error.compareTo(that.Error);
}
}
}
catch (VisADException e)
{
comp = 1; // make problem Real-s greater than anything
}
return comp;
}
/**
* Indicates if this Real is semantically identical to an object.
* @param obj The object.
* @return <code>true</code> if and only if this Real
* is semantically identical to the object.
*/
public boolean equals(Object obj) {
return obj != null && obj instanceof Real &&
getType().equals(((Real)obj).getType()) && compareTo(obj) == 0;
}
/**
* Returns the hash code of this Real.
* @return The hash code of this Real. If two Real-s are
* semantically identical, then their hash codes
* are equal.
*/
public int hashCode() {
RealType realType = (RealType)getType();
int hashCode = realType.hashCode();
try
{
hashCode ^= new Double(getValue(realType.getDefaultUnit())).hashCode();
}
catch (VisADException e)
{} // ignore because can't happen
if (Error != null)
hashCode ^= Error.hashCode();
return hashCode;
}
/** run 'java visad.Real' to test the Real class */
public static void main(String args[])
throws VisADException, RemoteException {
byte b = 10;
Real w = new Real(b);
int ii = 14;
short s = 12;
Real t = new Real(1.0);
Real x = new Real(12);
Real y = new Real(12L);
Real u = new Real(ii);
Real v = new Real(s);
System.out.println("x = " + x + "\nw = " + w);
System.out.println("x + w = " + x.add(w));
System.out.println("x - w = " + x.subtract(w));
System.out.println("x * w = " + x.multiply(w));
System.out.println("x / w = " + x.divide(w));
System.out.println("sqrt(x) = " + x.sqrt());
System.out.println("");
Real fahrenheit =
new Real(
RealType.getRealType(
"FahrenheitTemperature",
new OffsetUnit(459.67,
new ScaledUnit(1/1.8, SI.kelvin, "degR"),
"degF"),
null),
32.0);
Real kelvin = new Real(RealType.getRealType("Temperature", SI.kelvin, null), 300);
System.out.println("300 kelvin + 32 fahrenheit = " +
((Real)kelvin.add(fahrenheit)).toValueString());
System.out.println("300 kelvin - 32 fahrenheit = " +
((Real)kelvin.subtract(fahrenheit)).toValueString());
System.out.println("max(300 kelvin, 32 fahrenheit) = " +
((Real)kelvin.max(fahrenheit)).toValueString());
System.out.println("min(300 kelvin, 32 fahrenheit) = " +
((Real)kelvin.min(fahrenheit)).toValueString());
System.out.println("");
System.out.println("32 fahrenheit + 300 kelvin = " +
((Real)fahrenheit.add(kelvin)).toValueString());
System.out.println("32 fahrenheit - 300 kelvin = " +
((Real)fahrenheit.subtract(kelvin)).toValueString());
System.out.println("max(32 fahrenheit, 300 kelvin) = " +
((Real)fahrenheit.max(kelvin)).toValueString());
System.out.println("min(32 fahrenheit, 300 kelvin) = " +
((Real)fahrenheit.min(kelvin)).toValueString());
System.out.println("");
Real deltaF =
new Real(
RealType.getRealType(
"DeltaFahrenheitTemperature",
new OffsetUnit(459.67,
new ScaledUnit(1/1.8, SI.kelvin, "degR"),
"degF"),
null,
RealType.INTERVAL),
32.0);
System.out.println("300 kelvin + 32 deltaF = " +
((Real)kelvin.add(deltaF)).toValueString());
System.out.println("300 kelvin - 32 deltaF = " +
((Real)kelvin.subtract(deltaF)).toValueString());
System.out.println("max(300 kelvin, 32 deltaF) = " +
((Real)kelvin.max(deltaF)).toValueString());
System.out.println("min(300 kelvin, 32 deltaF) = " +
((Real)kelvin.min(deltaF)).toValueString());
System.out.println("");
System.out.println("32 deltaF + 300 kelvin = " +
((Real)deltaF.add(kelvin)).toValueString());
System.out.println("32 deltaF - 300 kelvin = " +
((Real)deltaF.subtract(kelvin)).toValueString());
System.out.println("max(32 deltaF, 300 kelvin) = " +
((Real)deltaF.max(kelvin)).toValueString());
System.out.println("min(32 deltaF, 300 kelvin) = " +
((Real)deltaF.min(kelvin)).toValueString());
System.out.println("");
Real deltaK =
new Real(
RealType.getRealType( "DeltaTemperature", SI.kelvin, null, RealType.INTERVAL),
100.0);
System.out.println("300 kelvin + 100 deltaK = " +
((Real)kelvin.add(deltaK)).toValueString());
System.out.println("300 kelvin - 100 deltaK = " +
((Real)kelvin.subtract(deltaK)).toValueString());
System.out.println("max(300 kelvin, 100 deltaK) = " +
((Real)kelvin.max(deltaK)).toValueString());
System.out.println("min(300 kelvin, 100 deltaK) = " +
((Real)kelvin.min(deltaK)).toValueString());
System.out.println("");
System.out.println("100 deltaK + 300 kelvin = " +
((Real)deltaK.add(kelvin)).toValueString());
System.out.println("100 deltaK - 300 kelvin = " +
((Real)deltaK.subtract(kelvin)).toValueString());
System.out.println("max(100 deltaK, 300 kelvin) = " +
((Real)deltaK.max(kelvin)).toValueString());
System.out.println("min(100 deltaK, 300 kelvin) = " +
((Real)deltaK.min(kelvin)).toValueString());
System.out.println("");
System.out.println("100 deltaK + 32 deltaF = " +
((Real)deltaK.add(deltaF)).toValueString());
System.out.println("100 deltaK - 32 deltaF = " +
((Real)deltaK.subtract(deltaF)).toValueString());
System.out.println("max(100 deltaK, 32 deltaF) = " +
((Real)deltaK.max(deltaF)).toValueString());
System.out.println("min(100 deltaK, 32 deltaF) = " +
((Real)deltaK.min(deltaF)).toValueString());
System.out.println("");
System.out.println("32 deltaF + 100 deltaK = " +
((Real)deltaF.add(deltaK)).toValueString());
System.out.println("32 deltaF - 100 deltaK = " +
((Real)deltaF.subtract(deltaK)).toValueString());
System.out.println("max(32 deltaF, 100 deltaK) = " +
((Real)deltaF.max(deltaK)).toValueString());
System.out.println("min(32 deltaF, 100 deltaK) = " +
((Real)deltaF.min(deltaK)).toValueString());
System.out.println("");
System.out.println("300 kelvin + -(32 fahrenheit) = " +
((Real)kelvin.add(fahrenheit.negate())).toValueString());
System.out.println("32 fahrenheit + -(300 kelvin) = " +
((Real)fahrenheit.add(kelvin.negate())).toValueString());
System.out.println("");
Unit foot = new ScaledUnit(3.048, SI.meter);
Unit yard = new ScaledUnit(3, (ScaledUnit)foot);
System.out.println("log(1 yard / 3 feet) = " +
((Real)new Real(RealType.getRealType("OneYard", SI.meter, null), 1, yard)
.divide(new Real(RealType.getRealType("ThreeFeet", SI.meter, null), 3, foot))
.log()).toValueString());
}
/* Here's the output:
x = 12.0
w = 10.0
x + w = 22.0
x - w = 2.0
x * w = 120.0
x / w = 1.2
sqrt(x) = 3.4641016151377544
300 kelvin + 32 fahrenheit = 573.15 K
300 kelvin - 32 fahrenheit = 26.85 K
max(300 kelvin, 32 fahrenheit) = 300.0 K
min(300 kelvin, 32 fahrenheit) = 273.15 K
32 fahrenheit + 300 kelvin = 1031.67 degR
32 fahrenheit - 300 kelvin = -48.33 degR
max(32 fahrenheit, 300 kelvin) = 540.0 degR
min(32 fahrenheit, 300 kelvin) = 491.67 degR
300 kelvin + 32 deltaF = 317.77777 K
300 kelvin - 32 deltaF = 282.22223 K
max(300 kelvin, 32 deltaF) = 300.0 K
min(300 kelvin, 32 deltaF) = 17.777779 K
32 deltaF + 300 kelvin = 572.0 degR
32 deltaF - 300 kelvin = -508.0 degR
max(32 deltaF, 300 kelvin) = 540.0 degR
min(32 deltaF, 300 kelvin) = 32.0 degR
300 kelvin + 100 deltaK = 400.0 K
300 kelvin - 100 deltaK = 200.0 K
max(300 kelvin, 100 deltaK) = 300.0 K
min(300 kelvin, 100 deltaK) = 100.0 K
100 deltaK + 300 kelvin = 400.0 K
100 deltaK - 300 kelvin = -200.0 K
max(100 deltaK, 300 kelvin) = 300.0 K
min(100 deltaK, 300 kelvin) = 100.0 K
100 deltaK + 32 deltaF = 117.77778 K
100 deltaK - 32 deltaF = 82.22222 K
max(100 deltaK, 32 deltaF) = 100.0 K
min(100 deltaK, 32 deltaF) = 17.777779 K
32 deltaF + 100 deltaK = 212.0 degR
32 deltaF - 100 deltaK = -148.0 degR
max(32 deltaF, 100 deltaK) = 180.0 degR
min(32 deltaF, 100 deltaK) = 32.0 degR
300 kelvin + -(32 fahrenheit) = 26.85 K
32 fahrenheit + -(300 kelvin) = -48.33 degR
log(1 yard / 3 feet) = 0.0
*/
}