BaseUnit.java 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. import java.io.*;
  5. /** A primitive Unit of measurement (such as a meter).
  6. * @author Per Bothner
  7. */
  8. public class BaseUnit extends NamedUnit implements Externalizable
  9. {
  10. /** The name of the "dimension" this is a base unit for. */
  11. String dimension;
  12. /** BaseUnits are numberd with globally unique indexes. */
  13. static int base_count = 0;
  14. /** This is an index in the bases array.
  15. * The index may change if there are insertions in bases. */
  16. int index;
  17. /* Array of all existing BaseUnits.
  18. * This array is kept sorted (according to the compareTo method).
  19. * The reason is to make it easy to keep the BaseUnits in a Dimensions
  20. * array to be sorted "lexicographically". One reason we want to
  21. * do that is to have a stable serialization representtion. *
  22. // static BaseUnit[] bases = null;
  23. /** A name for the dimension bing measured.
  24. * A meter has the dimension "Length".
  25. * BaseUnits are considered equal if their name <em>and</em>
  26. * their dimension are equal. (In that case they are also identical.)
  27. * We use dimension as a partial guard against accidental name clashes.
  28. */
  29. public String getDimension()
  30. {
  31. return dimension;
  32. }
  33. /** Name for Unit.Empty. */
  34. private static final String unitName = "(name)";
  35. /** Should only be used for serialization, and Unit.Empty. */
  36. public BaseUnit()
  37. {
  38. name = unitName;
  39. index = 0x7fffffff;
  40. dims = Dimensions.Empty;
  41. }
  42. protected void init()
  43. {
  44. this.base = this;
  45. this.scale = 1.0;
  46. this.dims = new Dimensions (this);
  47. super.init();
  48. this.index = BaseUnit.base_count++;
  49. /*
  50. if (bases == null)
  51. bases = new BaseUnit[10];
  52. else if (index >= bases.length)
  53. {
  54. BaseUnit[] b = new BaseUnit[2 * index];
  55. System.arraycopy(bases, 0, b, 0, bases.length);
  56. bases = b;
  57. }
  58. bases[index] = this;
  59. // Make sure bases array is sorted.
  60. for (int i = index; --i >= 0; )
  61. {
  62. BaseUnit old = bases[i];
  63. int code = compare(old, this);
  64. if (code == 0)
  65. throw new Error("internal invariant failure");
  66. if (code > 0)
  67. break;
  68. // Swap old and this, and their index fields.
  69. bases[i] = this;
  70. bases[index] = old;
  71. old.index = index;
  72. index = i;
  73. }
  74. */
  75. }
  76. public BaseUnit (String name)
  77. {
  78. this.name = name;
  79. init();
  80. }
  81. public BaseUnit (String name, String dimension)
  82. {
  83. this.name = name;
  84. this.dimension = dimension;
  85. init();
  86. }
  87. public int hashCode () { return name.hashCode(); }
  88. public Unit unit() { return this; }
  89. /** Look for an existing matching BaseUnit.
  90. * @param name name of desired BaseUnit, such as "m"
  91. * @param dimension a name for what the unit measures, such as "Length".
  92. */
  93. public static BaseUnit lookup(String name, String dimension)
  94. {
  95. name = name.intern();
  96. if (name == unitName && dimension == null)
  97. return Unit.Empty;
  98. int hash = name.hashCode();
  99. int index = (hash & 0x7FFFFFFF) % table.length;
  100. for (NamedUnit unit = table[index]; unit != null; unit = unit.chain)
  101. {
  102. if (unit.name == name && unit instanceof BaseUnit)
  103. {
  104. BaseUnit bunit = (BaseUnit) unit;
  105. if (bunit.dimension == dimension)
  106. return bunit;
  107. }
  108. }
  109. return null;
  110. }
  111. public static BaseUnit make(String name, String dimension)
  112. {
  113. BaseUnit old = lookup(name, dimension);
  114. return old == null ? new BaseUnit(name, dimension) : old;
  115. }
  116. public static int compare (BaseUnit unit1, BaseUnit unit2)
  117. {
  118. int code = unit1.name.compareTo(unit2.name);
  119. if (code != 0)
  120. return code;
  121. String dim1 = unit1.dimension;
  122. String dim2 = unit2.dimension;
  123. if (dim1 == dim2)
  124. return 0;
  125. if (dim1 == null)
  126. return -1;
  127. if (dim2 == null)
  128. return 1;
  129. return dim1.compareTo(dim2);
  130. }
  131. /**
  132. * @serialData Write the unit name (using writeUTF), followed.
  133. * followed by the name of the dimension it is a unit for.
  134. * The latter is either null or a String and is written with writeObject.
  135. */
  136. public void writeExternal(ObjectOutput out) throws IOException
  137. {
  138. out.writeUTF(name);
  139. out.writeObject(dimension);
  140. }
  141. public void readExternal(ObjectInput in)
  142. throws IOException, ClassNotFoundException
  143. {
  144. name = in.readUTF();
  145. dimension = (String) in.readObject();
  146. }
  147. public Object readResolve() throws ObjectStreamException
  148. {
  149. BaseUnit unit = lookup(name, dimension);
  150. if (unit != null)
  151. return unit;
  152. init();
  153. return this;
  154. }
  155. }