001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.math;
005:
006: /* A unit of measurement, either primitive (meter) or derived (kilogram).
007: * @author Per Bothner
008: */
009:
010: public abstract class Unit extends Quantity {
011: Dimensions dims;
012: /** The value of this Unit is factor*dims. */
013: double factor;
014: MulUnit products;
015:
016: /** A Unit equivalent to this unit, divided by factor.
017: Same as the value of the dimensions() only. */
018: Unit base;
019:
020: /** A hash table of named Units. */
021: static NamedUnit[] table = new NamedUnit[100];
022:
023: public final Dimensions dimensions() {
024: return dims;
025: }
026:
027: public final double doubleValue() {
028: return factor;
029: }
030:
031: public int hashCode() {
032: return dims.hashCode();
033: }
034:
035: public String getName() {
036: return null;
037: }
038:
039: static Unit times(Unit unit1, int power1, Unit unit2, int power2) {
040: // First try various simplifications.
041: if (unit1 == unit2) {
042: power1 += power2;
043: unit2 = Unit.Empty;
044: power2 = 0;
045: }
046: if (power1 == 0 || unit1 == Unit.Empty) {
047: unit1 = unit2;
048: power1 = power2;
049: unit2 = Unit.Empty;
050: power2 = 0;
051: }
052: if (power2 == 0 || unit2 == Unit.Empty) {
053: if (power1 == 1)
054: return unit1;
055: if (power1 == 0)
056: return Unit.Empty;
057: }
058: if (unit1 instanceof MulUnit) {
059: MulUnit munit1 = (MulUnit) unit1;
060: if (munit1.unit1 == unit2)
061: return times(unit2, munit1.power1 * power1 + power2,
062: munit1.unit2, munit1.power2 * power1);
063: if (munit1.unit2 == unit2)
064: return times(munit1.unit1, munit1.power1 * power1,
065: unit2, munit1.power2 * power1 + power2);
066: if (unit2 instanceof MulUnit) {
067: MulUnit munit2 = (MulUnit) unit2;
068: if (munit1.unit1 == munit2.unit1
069: && munit1.unit2 == munit2.unit2)
070: return times(munit1.unit1, munit1.power1 * power1
071: + munit2.power1 * power2, munit1.unit2,
072: munit1.power2 * power1 + munit2.power2
073: * power2);
074: if (munit1.unit1 == munit2.unit2
075: && munit1.unit2 == munit2.unit1)
076: return times(munit1.unit1, munit1.power1 * power1
077: + munit2.power2 * power2, munit1.unit2,
078: munit1.power2 * power1 + munit2.power1
079: * power2);
080: }
081: }
082: if (unit2 instanceof MulUnit) {
083: MulUnit munit2 = (MulUnit) unit2;
084: if (munit2.unit1 == unit1)
085: return times(unit1, power1 + munit2.power1 * power2,
086: munit2.unit2, munit2.power2 * power2);
087: if (munit2.unit2 == unit1)
088: return times(munit2.unit1, munit2.power1 * power2,
089: unit1, power1 + munit2.power2 * power2);
090: }
091:
092: return MulUnit.make(unit1, power1, unit2, power2);
093: }
094:
095: public static Unit times(Unit unit1, Unit unit2) {
096: return times(unit1, 1, unit2, 1);
097: }
098:
099: public static Unit divide(Unit unit1, Unit unit2) {
100: return times(unit1, 1, unit2, -1);
101: }
102:
103: public static Unit pow(Unit unit, int power) {
104: return times(unit, power, Unit.Empty, 0);
105: }
106:
107: Unit() {
108: factor = 1.0;
109: }
110:
111: public static NamedUnit make(String name, Quantity value) {
112: return NamedUnit.make(name, value);
113: }
114:
115: public static Unit define(String name, DQuantity value) {
116: return new NamedUnit(name, value);
117: }
118:
119: public static Unit define(String name, double factor, Unit base) {
120: return new NamedUnit(name, factor, base);
121: }
122:
123: public Complex number() {
124: return DFloNum.one();
125: }
126:
127: public boolean isExact() {
128: return false;
129: }
130:
131: public final boolean isZero() {
132: return false;
133: }
134:
135: public Numeric power(IntNum y) {
136: if (y.words != null)
137: throw new ArithmeticException("Unit raised to bignum power");
138: return pow(this , y.ival);
139: }
140:
141: public Unit sqrt() {
142: if (this == Unit.Empty)
143: return this ;
144: throw new RuntimeException("unimplemented Unit.sqrt");
145: }
146:
147: public static BaseUnit Empty = new BaseUnit();
148: static {
149: Dimensions.Empty.bases[0] = Empty;
150: }
151:
152: public static NamedUnit lookup(String name) {
153: return NamedUnit.lookup(name);
154: }
155:
156: public String toString(double val) {
157: String str = Double.toString(val);
158: if (this == Unit.Empty)
159: return str;
160: else
161: return str + this .toString();
162: }
163:
164: public String toString(RealNum val) {
165: return toString(val.doubleValue());
166: }
167:
168: /*
169: public String toString (Complex val)
170: {
171: String str = toString(val.re());
172: RealNum im = val.im();
173: if (im.isZero())
174: return str;
175: // This conflicts with using '@' for polar notation.
176: return str + "@" + toString(im);
177: }
178: */
179:
180: public String toString() {
181: String name = getName();
182: if (name != null)
183: return name;
184: else if (this == Unit.Empty)
185: return "unit";
186: else
187: return Double.toString(factor) + "<unnamed unit>";
188: }
189:
190: public Unit unit() {
191: return this ;
192: }
193:
194: /** A magic factor to indicate units that have the same "dimension"
195: * but not a fixed multiple.
196: * E.g. "month" and "day", or money of different currencies.
197: * Since they have the same dimension, they can be added to get
198: * an (unimplemented) combined quantity, but they cannot be compared.
199: * No general support yet, but used for time Duration.
200: */
201: public static double NON_COMBINABLE = 0.0;
202:
203: public static final BaseUnit meter = new BaseUnit("m", "Length");
204: public static final BaseUnit duration = new BaseUnit("duration",
205: "Time");
206: public static final BaseUnit gram = new BaseUnit("g", "Mass");
207: public static final Unit cm = define("cm", 0.01, meter);
208: public static final Unit mm = define("mm", 0.1, cm);
209: public static final Unit in = define("in", 0.0254, meter);
210: public static final Unit pt = define("pt", 0.0003527778, meter);
211: public static final Unit pica = define("pica", 0.004233333, meter);
212: public static final Unit radian = define("rad", 1.0, Unit.Empty);
213:
214: public static final NamedUnit date = new NamedUnit("date",
215: NON_COMBINABLE, duration);
216: public static final NamedUnit second = new NamedUnit("s",
217: NON_COMBINABLE, duration);
218: public static final NamedUnit month = new NamedUnit("month",
219: NON_COMBINABLE, duration);
220: public static final Unit minute = define("min", 60.0, second);
221: public static final Unit hour = define("hour", 60.0, minute);
222: }
|