View Javadoc
1   package org.djunits.value.vfloat.scalar.base;
2   
3   import org.djunits.unit.Unit;
4   import org.djunits.unit.si.SIPrefixes;
5   import org.djunits.value.Absolute;
6   import org.djunits.value.base.Scalar;
7   import org.djunits.value.formatter.Format;
8   import org.djunits.value.util.ValueUtil;
9   
10  /**
11   * Static methods to create and operate on FloatScalars.
12   * <p>
13   * Copyright (c) 2015-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
15   * </p>
16   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
17   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
18   * @param <U> the unit
19   * @param <S> the type
20   */
21  public abstract class FloatScalar<U extends Unit<U>, S extends FloatScalar<U, S>> extends Scalar<U, S>
22  {
23      /** */
24      private static final long serialVersionUID = 20161015L;
25  
26      /** The value, stored in the standard SI unit. */
27      @SuppressWarnings("checkstyle:visibilitymodifier")
28      public final float si;
29  
30      /**
31       * Construct a new FloatScalar.
32       * @param value the value to store, expressed in the given unit
33       * @param unit the unit
34       */
35      public FloatScalar(final float value, final U unit)
36      {
37          super(unit);
38          this.si = unit.isBaseSIUnit() ? value : (float) ValueUtil.expressAsSIUnit(value, unit);
39      }
40  
41      /**
42       * Construct a new FloatScalar.
43       * @param value the value to duplicate
44       */
45      public FloatScalar(final S value)
46      {
47          super(value.getDisplayUnit());
48          this.si = value.getSI();
49      }
50  
51      /**
52       * Return the value in the underlying SI unit.
53       * @return the value in the underlying SI unit
54       */
55      public final float getSI()
56      {
57          return this.si;
58      }
59  
60      /**
61       * Retrieve the value in the original unit.
62       * @return float
63       */
64      public final float getInUnit()
65      {
66          return (float) ValueUtil.expressAsUnit(getSI(), getDisplayUnit());
67      }
68  
69      /**
70       * Retrieve the value converted into some specified unit.
71       * @param targetUnit the unit to convert the value into
72       * @return float
73       */
74      public final float getInUnit(final U targetUnit)
75      {
76          return (float) ValueUtil.expressAsUnit(getSI(), targetUnit);
77      }
78  
79      @Override
80      public final boolean lt(final S o)
81      {
82          return this.getSI() < o.getSI();
83      }
84  
85      @Override
86      public final boolean le(final S o)
87      {
88          return this.getSI() <= o.getSI();
89      }
90  
91      @Override
92      public final boolean gt(final S o)
93      {
94          return this.getSI() > o.getSI();
95      }
96  
97      @Override
98      public final boolean ge(final S o)
99      {
100         return this.getSI() >= o.getSI();
101     }
102 
103     @Override
104     public final boolean eq(final S o)
105     {
106         return this.getSI() == o.getSI();
107     }
108 
109     @Override
110     public final boolean ne(final S o)
111     {
112         return this.getSI() != o.getSI();
113     }
114 
115     @Override
116     public final boolean lt0()
117     {
118         return this.getSI() < 0.0;
119     }
120 
121     @Override
122     public final boolean le0()
123     {
124         return this.getSI() <= 0.0;
125     }
126 
127     @Override
128     public final boolean gt0()
129     {
130         return this.getSI() > 0.0;
131     }
132 
133     @Override
134     public final boolean ge0()
135     {
136         return this.getSI() >= 0.0;
137     }
138 
139     @Override
140     public final boolean eq0()
141     {
142         return this.getSI() == 0.0;
143     }
144 
145     @Override
146     public final boolean ne0()
147     {
148         return this.getSI() != 0.0;
149     }
150 
151     @Override
152     public final int compareTo(final S o)
153     {
154         return Float.compare(this.getSI(), o.getSI());
155     }
156 
157     @Override
158     public int intValue()
159     {
160         return (int) this.getSI();
161     }
162 
163     @Override
164     public long longValue()
165     {
166         return (long) this.getSI();
167     }
168 
169     @Override
170     public float floatValue()
171     {
172         return this.getSI();
173     }
174 
175     @Override
176     public double doubleValue()
177     {
178         return this.getSI();
179     }
180 
181     /**********************************************************************************/
182     /********************************* GENERIC METHODS ********************************/
183     /**********************************************************************************/
184 
185     @Override
186     public String toString()
187     {
188         return toString(getDisplayUnit(), false, true);
189     }
190 
191     @Override
192     public String toString(final U displayUnit)
193     {
194         return toString(displayUnit, false, true);
195     }
196 
197     @Override
198     public String toString(final boolean verbose, final boolean withUnit)
199     {
200         return toString(getDisplayUnit(), verbose, withUnit);
201     }
202 
203     @Override
204     public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
205     {
206         StringBuffer buf = new StringBuffer();
207         if (verbose)
208         {
209             buf.append(this instanceof Absolute ? "Abs " : "Rel ");
210         }
211         float d = (float) ValueUtil.expressAsUnit(getSI(), displayUnit);
212         buf.append(Format.format(d));
213         if (withUnit)
214         {
215             buf.append(" "); // Insert one space as prescribed by SI writing conventions
216             buf.append(displayUnit.getLocalizedDisplayAbbreviation());
217         }
218         return buf.toString();
219     }
220 
221     /**
222      * Format this DoubleScalar in SI unit using prefixes when possible. If the value is too small or too large, e-notation and
223      * the plain SI unit are used.
224      * @return formatted value of this DoubleScalar
225      */
226     public String toStringSIPrefixed()
227     {
228         return toStringSIPrefixed(-30, 32);
229     }
230 
231     /**
232      * Format this DoubleScalar in SI unit using prefixes when possible and within the specified size range. If the value is too
233      * small or too large, e-notation and the plain SI unit are used.
234      * @param smallestPower the smallest exponent value that will be written using an SI prefix
235      * @param biggestPower the largest exponent value that will be written using an SI prefix
236      * @return formatted value of this DoubleScalar
237      */
238     public String toStringSIPrefixed(final int smallestPower, final int biggestPower)
239     {
240         // Override this method for weights, nonlinear units and DimensionLess.
241         if (!Double.isFinite(this.si))
242         {
243             return toString(getDisplayUnit().getStandardUnit());
244         }
245         // PK: I can't think of an easier way to figure out what the exponent will be; rounding of the mantissa to the available
246         // width makes this hard; This feels like an expensive way.
247         String check = String.format(this.si >= 0 ? "%10.8E" : "%10.7E", this.si);
248         int exponent = Integer.parseInt(check.substring(check.indexOf("E") + 1));
249         if (exponent < -30 || exponent < smallestPower || exponent > 30 + 2 || exponent > biggestPower)
250         {
251             // Out of SI prefix range; do not scale.
252             return String.format(this.si >= 0 ? "%10.4E" : "%10.3E", this.si) + " "
253                     + getDisplayUnit().getStandardUnit().getId();
254         }
255         Integer roundedExponent = (int) Math.ceil((exponent - 2.0) / 3) * 3;
256         // System.out.print(String.format("exponent=%d; roundedExponent=%d ", exponent, roundedExponent));
257         String key =
258                 SIPrefixes.FACTORS.get(roundedExponent).getDefaultTextualPrefix() + getDisplayUnit().getStandardUnit().getId();
259         U displayUnit = getDisplayUnit().getQuantity().getUnitByAbbreviation(key);
260         return toString(displayUnit);
261     }
262 
263     @Override
264     public String toTextualString()
265     {
266         return toTextualString(getDisplayUnit());
267     }
268 
269     @Override
270     public String toTextualString(final U displayUnit)
271     {
272         float f = (float) ValueUtil.expressAsUnit(getSI(), displayUnit);
273         return format(f) + " " + displayUnit.getLocalizedTextualAbbreviation();
274     }
275 
276     @Override
277     public String toDisplayString()
278     {
279         return toDisplayString(getDisplayUnit());
280     }
281 
282     @Override
283     public String toDisplayString(final U displayUnit)
284     {
285         float f = (float) ValueUtil.expressAsUnit(getSI(), displayUnit);
286         return format(f) + " " + displayUnit.getLocalizedDisplayAbbreviation();
287     }
288 
289     @Override
290     @SuppressWarnings("checkstyle:designforextension")
291     public int hashCode()
292     {
293         final int prime = 31;
294         int result = getDisplayUnit().getStandardUnit().hashCode();
295         long temp;
296         temp = Float.floatToIntBits(this.getSI());
297         result = prime * result + (int) (temp ^ (temp >>> 32));
298         return result;
299     }
300 
301     @Override
302     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces", "unchecked"})
303     public boolean equals(final Object obj)
304     {
305         if (this == obj)
306             return true;
307         if (obj == null)
308             return false;
309         if (getClass() != obj.getClass())
310             return false;
311         FloatScalar<U, S> other = (FloatScalar<U, S>) obj;
312         if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
313             return false;
314         if (Float.floatToIntBits(this.getSI()) != Float.floatToIntBits(other.getSI()))
315             return false;
316         return true;
317     }
318 
319 }