
edu.uvm.ccts.arden.model.ANumber Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arden-model Show documentation
Show all versions of arden-model Show documentation
The Java model used to represent Arden objects
/*
* Copyright 2015 The University of Vermont and State
* Agricultural College, Vermont Oxford Network, and The University
* of Vermont Medical Center. All rights reserved.
*
* Written by Matthew B. Storer
*
* This file is part of Arden Model.
*
* Arden Model is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Arden Model 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Arden Model. If not, see .
*/
package edu.uvm.ccts.arden.model;
import edu.uvm.ccts.arden.util.NumberUtil;
import edu.uvm.ccts.arden.util.PrimaryTimeUtil;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
/**
* An Arden-number object
*
* There is a single number type, so there is no distinction between integer and floating point numbers. Number
* constants (for example, 3.4E-12) are defined in Section 7.1.4. Internally, all arithmetic is done in floating
* point. For example, 1/2 evaluates to 0.5.
*/
public class ANumber extends PrimaryTimeDataType implements Comparable {
private final Number value;
public ANumber(ANumber an) {
primaryTime = an.primaryTime;
value = an.value;
}
public ANumber(Number value) {
if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
this.value = value.longValue();
} else if (NumberUtil.isWholeNumber(value)) {
this.value = value.longValue();
} else {
this.value = value.doubleValue();
}
}
public Number value() {
return value;
}
public int intValue() {
return value.intValue();
}
public long longValue() {
return value.longValue();
}
public float floatValue() {
return value.floatValue();
}
public double doubleValue() {
return value.doubleValue();
}
public boolean isWholeNumber() {
return value instanceof Long;
}
public long asWholeNumber() {
return value.longValue();
}
public boolean isFractionalNumber() {
return value instanceof Double;
}
public double asFractionalNumber() {
return value.doubleValue();
}
@Override
public String toString() {
return value.toString();
}
/**
* Compares this object to another as an identity comparison, in which the primary time of the objects are
* considered.
* @param o
* @return {@code true} if {@code this} and {@code o} have the same value and the same primary
* time.
*/
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (o.getClass() != getClass()) return false;
ANumber an = (ANumber) o;
return new EqualsBuilder()
.append(primaryTime, an.primaryTime)
.append(value, an.value)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(67, 31)
.append(primaryTime)
.append(value)
.toHashCode();
}
/**
* Compares this object to another, considering only the value of the object, and not the primary time.
* @param o
* @return {@code true} if {@code this} and {@code o} have the same value.
*/
@Override
public boolean hasValue(ADataType o) {
if (o == null) return false;
if (o == this) return true;
if (o.getClass() != getClass()) return false;
if (value == null) return ((ANumber) o).value == null;
return value.equals(((ANumber) o).value);
}
@Override
public int compareTo(ANumber an) {
if (this == an) return 0;
if (this.isLessThan(an).asBoolean()) return -1;
else if (this.isGreaterThan(an).asBoolean()) return 1;
// todo : incorporate primaryTime into sorting here
assert this.equals(an) : "compareTo inconsistent with equals.";
return 0;
}
@Override
public ANumber copy() {
return new ANumber(this);
}
@Override
public Object toJavaObject() {
return value;
}
public boolean isPositive() {
if (isWholeNumber()) {
return asWholeNumber() >= 0;
} else {
return asFractionalNumber() >= 0;
}
}
public boolean isNegative() {
return ! isPositive();
}
public ABoolean isLessThan(Number n) {
return isLessThan(new ANumber(n));
}
public ABoolean isLessThan(ANumber an) {
boolean b;
if (isWholeNumber()) {
b = asWholeNumber() < (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
b = asFractionalNumber() < (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ABoolean rval = new ABoolean(b);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ABoolean isLessThanOrEqualTo(Number n) {
return isLessThanOrEqualTo(new ANumber(n));
}
public ABoolean isLessThanOrEqualTo(ANumber an) {
boolean b;
if (isWholeNumber()) {
b = asWholeNumber() <= (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
b = asFractionalNumber() <= (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ABoolean rval = new ABoolean(b);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ABoolean isGreaterThan(Number n) {
return isGreaterThan(new ANumber(n));
}
public ABoolean isGreaterThan(ANumber an) {
boolean b;
if (isWholeNumber()) {
b = asWholeNumber() > (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
b = asFractionalNumber() > (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ABoolean rval = new ABoolean(b);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ABoolean isGreaterThanOrEqualTo(Number n) {
return isGreaterThanOrEqualTo(new ANumber(n));
}
public ABoolean isGreaterThanOrEqualTo(ANumber an) {
boolean b;
if (isWholeNumber()) {
b = asWholeNumber() >= (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
b = asFractionalNumber() >= (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ABoolean rval = new ABoolean(b);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber add(Number n) {
return add(new ANumber(n));
}
public ANumber add(ANumber an) {
Number n;
if (isWholeNumber()) {
n = asWholeNumber() + (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
n = asFractionalNumber() + (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ANumber rval = new ANumber(n);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber subtract(Number n) {
return subtract(new ANumber(n));
}
public ANumber subtract(ANumber an) {
Number n;
if (isWholeNumber()) {
n = asWholeNumber() - (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
n = asFractionalNumber() - (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ANumber rval = new ANumber(n);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber multiply(Number n) {
return multiply(new ANumber(n));
}
public ANumber multiply(ANumber an) {
Number n;
if (isWholeNumber()) {
n = asWholeNumber() * (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
} else {
n = asFractionalNumber() * (an.isWholeNumber() ? an.asWholeNumber() : an.asFractionalNumber());
}
ANumber rval = new ANumber(n);
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber divide(Number n) {
return divide(new ANumber(n));
}
public ANumber divide(ANumber an) {
ANumber rval = new ANumber(asFractionalNumber() / an.asFractionalNumber());
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber raiseToPower(Number n) {
return raiseToPower(new ANumber(n));
}
public ANumber raiseToPower(ANumber an) {
ANumber rval = new ANumber(Math.pow(doubleValue(), an.doubleValue()));
rval.setPrimaryTime(PrimaryTimeUtil.getPrimaryTime(this, an));
return rval;
}
public ANumber arccos() {
ANumber rval = new ANumber(Math.acos(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber arcsin() {
ANumber rval = new ANumber(Math.asin(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber arctan() {
ANumber rval = new ANumber(Math.atan(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber cosine() {
ANumber rval = new ANumber(Math.cos(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber sine() {
ANumber rval = new ANumber(Math.sin(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber tangent() {
ANumber rval = new ANumber(Math.tan(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber exp() {
ANumber rval = new ANumber(Math.exp(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber floor() {
ANumber rval = new ANumber(Math.floor(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber ceiling() {
ANumber rval = new ANumber(Math.ceil(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber truncate() {
return isPositive() ? floor() : ceiling(); // truncate towards zero - spec 9.16.13
}
public ANumber round() {
ANumber rval;
if (isWholeNumber()) {
rval = new ANumber(this);
} else if (isPositive()) {
rval = new ANumber(Math.round(asFractionalNumber()));
} else {
rval = new ANumber(Math.round(Math.abs(asFractionalNumber())) * -1);
}
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber abs() {
ANumber rval;
if (isPositive()) {
rval = new ANumber(this);
} else if (isWholeNumber()) {
rval = new ANumber(Math.abs(asWholeNumber()));
} else {
rval = new ANumber(Math.abs(asFractionalNumber()));
}
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
/**
* Returns the square root of its argument. Because imaginary numbers are not supported, the square root of a
* negative number results in {@code null}.
* @see 9.16.16
* @return
*/
public ANumber sqrt() {
if (isPositive()) {
ANumber rval = new ANumber(Math.sqrt(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
} else {
return null;
}
}
public ANumber log() {
ANumber rval = new ANumber(Math.log(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
public ANumber log10() {
ANumber rval = new ANumber(Math.log10(asFractionalNumber()));
rval.setPrimaryTime(getPrimaryTime());
return rval;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy