Unit.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright (c) 1997 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.math;
  4. /* A unit of measurement, either primitive (meter) or derived (kilogram).
  5. * @author Per Bothner
  6. */
  7. public abstract class Unit extends Quantity
  8. {
  9. Dimensions dims;
  10. /** The value of this Unit is factor*dims. */
  11. double factor;
  12. MulUnit products;
  13. /** A Unit equivalent to this unit, divided by factor.
  14. Same as the value of the dimensions() only. */
  15. Unit base;
  16. /** A hash table of named Units. */
  17. static NamedUnit[] table = new NamedUnit[100];
  18. public final Dimensions dimensions() { return dims; }
  19. public final double doubleValue() { return factor; }
  20. public int hashCode () { return dims.hashCode (); }
  21. public String getName() { return null; }
  22. static Unit times(Unit unit1, int power1, Unit unit2, int power2)
  23. {
  24. // First try various simplifications.
  25. if (unit1 == unit2)
  26. {
  27. power1 += power2;
  28. unit2 = Unit.Empty;
  29. power2 = 0;
  30. }
  31. if (power1 == 0 || unit1 == Unit.Empty)
  32. {
  33. unit1 = unit2;
  34. power1 = power2;
  35. unit2 = Unit.Empty;
  36. power2 = 0;
  37. }
  38. if (power2 == 0 || unit2 == Unit.Empty)
  39. {
  40. if (power1 == 1)
  41. return unit1;
  42. if (power1 == 0)
  43. return Unit.Empty;
  44. }
  45. if (unit1 instanceof MulUnit)
  46. {
  47. MulUnit munit1 = (MulUnit) unit1;
  48. if (munit1.unit1 == unit2)
  49. return times(unit2, munit1.power1 * power1 + power2,
  50. munit1.unit2, munit1.power2 * power1);
  51. if (munit1.unit2 == unit2)
  52. return times(munit1.unit1, munit1.power1 * power1,
  53. unit2, munit1.power2 * power1 + power2);
  54. if (unit2 instanceof MulUnit)
  55. {
  56. MulUnit munit2 = (MulUnit) unit2;
  57. if (munit1.unit1 == munit2.unit1 && munit1.unit2 == munit2.unit2)
  58. return times(munit1.unit1,
  59. munit1.power1 * power1 + munit2.power1 * power2,
  60. munit1.unit2,
  61. munit1.power2 * power1 + munit2.power2 * power2);
  62. if (munit1.unit1 == munit2.unit2 && munit1.unit2 == munit2.unit1)
  63. return times(munit1.unit1,
  64. munit1.power1 * power1 + munit2.power2 * power2,
  65. munit1.unit2,
  66. munit1.power2 * power1 + munit2.power1 * power2);
  67. }
  68. }
  69. if (unit2 instanceof MulUnit)
  70. {
  71. MulUnit munit2 = (MulUnit) unit2;
  72. if (munit2.unit1 == unit1)
  73. return times(unit1, power1 + munit2.power1 * power2,
  74. munit2.unit2, munit2.power2 * power2);
  75. if (munit2.unit2 == unit1)
  76. return times(munit2.unit1, munit2.power1 * power2,
  77. unit1, power1 + munit2.power2 * power2);
  78. }
  79. return MulUnit.make(unit1, power1, unit2, power2);
  80. }
  81. public static Unit times(Unit unit1, Unit unit2)
  82. {
  83. return times(unit1, 1, unit2, 1);
  84. }
  85. public static Unit divide (Unit unit1, Unit unit2)
  86. {
  87. return times(unit1, 1, unit2, -1);
  88. }
  89. public static Unit pow (Unit unit, int power)
  90. {
  91. return times(unit, power, Unit.Empty, 0);
  92. }
  93. Unit ()
  94. {
  95. factor = 1.0;
  96. }
  97. public static NamedUnit make (String name, Quantity value)
  98. {
  99. return NamedUnit.make(name, value);
  100. }
  101. public static Unit define (String name, DQuantity value)
  102. {
  103. return new NamedUnit (name, value);
  104. }
  105. public static Unit define (String name, double factor, Unit base)
  106. {
  107. return new NamedUnit (name, factor, base);
  108. }
  109. public Complex number() { return DFloNum.one(); }
  110. public boolean isExact () { return false; }
  111. public final boolean isZero () { return false; }
  112. public Numeric power (IntNum y)
  113. {
  114. if (y.words != null)
  115. throw new ArithmeticException("Unit raised to bignum power");
  116. return pow (this, y.ival);
  117. }
  118. public Unit sqrt ()
  119. {
  120. if (this == Unit.Empty)
  121. return this;
  122. throw new RuntimeException ("unimplemented Unit.sqrt");
  123. }
  124. public static BaseUnit Empty = new BaseUnit();
  125. static { Dimensions.Empty.bases[0] = Empty; }
  126. public static NamedUnit lookup (String name)
  127. {
  128. return NamedUnit.lookup(name);
  129. }
  130. public String toString (double val)
  131. {
  132. String str = Double.toString(val);
  133. if (this == Unit.Empty)
  134. return str;
  135. else
  136. return str + this.toString();
  137. }
  138. public String toString (RealNum val)
  139. {
  140. return toString (val.doubleValue());
  141. }
  142. /*
  143. public String toString (Complex val)
  144. {
  145. String str = toString(val.re());
  146. RealNum im = val.im();
  147. if (im.isZero())
  148. return str;
  149. // This conflicts with using '@' for polar notation.
  150. return str + "@" + toString(im);
  151. }
  152. */
  153. public String toString ()
  154. {
  155. String name = getName();
  156. if (name != null)
  157. return name;
  158. else if (this == Unit.Empty)
  159. return "unit";
  160. else
  161. return Double.toString(factor) + "<unnamed unit>";
  162. }
  163. public Unit unit ()
  164. {
  165. return this;
  166. }
  167. /** A magic factor to indicate units that have the same "dimension"
  168. * but not a fixed multiple.
  169. * E.g. "month" and "day", or money of different currencies.
  170. * Since they have the same dimension, they can be added to get
  171. * an (unimplemented) combined quantity, but they cannot be compared.
  172. * No general support yet, but used for time Duration.
  173. */
  174. public static double NON_COMBINABLE = 0.0;
  175. public static final BaseUnit meter = new BaseUnit ("m", "Length");
  176. public static final BaseUnit duration = new BaseUnit ("duration", "Time");
  177. public static final BaseUnit gram = new BaseUnit ("g", "Mass");
  178. public static final Unit cm = define("cm", 0.01, meter);
  179. public static final Unit mm = define("mm", 0.1, cm);
  180. public static final Unit in = define("in", 0.0254, meter);
  181. public static final Unit pt = define("pt", 0.0003527778, meter);
  182. public static final Unit pica = define("pica", 0.004233333, meter);
  183. public static final Unit radian = define("rad", 1.0, Unit.Empty);
  184. public static final Unit degree = define("deg", Math.PI/180, Unit.Empty);
  185. public static final Unit gradian = define("grad", Math.PI/200, Unit.Empty);
  186. public static final NamedUnit date =
  187. new NamedUnit("date", NON_COMBINABLE, duration);
  188. public static final NamedUnit second =
  189. new NamedUnit("s", NON_COMBINABLE, duration);
  190. public static final NamedUnit month =
  191. new NamedUnit("month", NON_COMBINABLE, duration);
  192. public static final Unit minute = define("min", 60.0, second);
  193. public static final Unit hour = define("hour", 60.0, minute);
  194. }