View Javadoc
1   package org.djunits.value.vfloat.vector.base;
2   
3   import java.io.Serializable;
4   import java.lang.reflect.Array;
5   import java.util.Iterator;
6   import java.util.NoSuchElementException;
7   
8   import org.djunits.unit.Unit;
9   import org.djunits.value.Absolute;
10  import org.djunits.value.AbstractIndexedValue;
11  import org.djunits.value.ValueRuntimeException;
12  import org.djunits.value.formatter.Format;
13  import org.djunits.value.storage.StorageType;
14  import org.djunits.value.util.ValueUtil;
15  import org.djunits.value.vfloat.function.FloatFunction;
16  import org.djunits.value.vfloat.function.FloatMathFunctions;
17  import org.djunits.value.vfloat.scalar.base.AbstractFloatScalar;
18  import org.djunits.value.vfloat.scalar.base.FloatScalar;
19  import org.djunits.value.vfloat.vector.data.FloatVectorData;
20  import org.djutils.exceptions.Throw;
21  
22  /**
23   * The most basic abstract class for the FloatVector.
24   * <p>
25   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
26   * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
27   * </p>
28   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
30   * @param <U> the unit
31   * @param <S> the scalar with unit U
32   * @param <V> the generic vector type
33   */
34  public abstract class AbstractFloatVector<U extends Unit<U>, S extends AbstractFloatScalar<U, S>,
35          V extends AbstractFloatVector<U, S, V>> extends AbstractIndexedValue<U, S, V, FloatVectorData>
36          implements FloatVectorInterface<U, S, V>
37  {
38      /** */
39      private static final long serialVersionUID = 20161015L;
40  
41      /** The stored data as an object, can be sparse or dense. */
42      @SuppressWarnings("checkstyle:visibilitymodifier")
43      protected FloatVectorData data;
44  
45      /**
46       * Construct a new FloatVector.
47       * @param data FloatVectorData; an internal data object
48       * @param unit U; the unit
49       */
50      AbstractFloatVector(final FloatVectorData data, final U unit)
51      {
52          super(unit);
53          Throw.whenNull(data, "data cannot be null");
54          this.data = data;
55      }
56  
57      /** {@inheritDoc} */
58      @Override
59      protected final FloatVectorData getData()
60      {
61          return this.data;
62      }
63  
64      /** {@inheritDoc} */
65      @Override
66      protected void setData(final FloatVectorData data)
67      {
68          this.data = data;
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public final float[] getValuesSI()
74      {
75          return getData().getDenseVectorSI();
76      }
77  
78      /** {@inheritDoc} */
79      @Override
80      public final float[] getValuesInUnit()
81      {
82          return getValuesInUnit(getDisplayUnit());
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      public final float[] getValuesInUnit(final U targetUnit)
88      {
89          float[] values = getValuesSI();
90          for (int i = values.length; --i >= 0;)
91          {
92              values[i] = (float) ValueUtil.expressAsUnit(values[i], targetUnit);
93          }
94          return values;
95      }
96  
97      /** {@inheritDoc} */
98      @Override
99      public final int size()
100     {
101         return getData().size();
102     }
103 
104     /**
105      * Check that a provided index is valid.
106      * @param index int; the value to check
107      * @throws ValueRuntimeException when index is invalid
108      */
109     protected final void checkIndex(final int index) throws ValueRuntimeException
110     {
111         if (index < 0 || index >= size())
112         {
113             throw new ValueRuntimeException("index out of range (valid range is 0.." + (size() - 1) + ", got " + index + ")");
114         }
115     }
116 
117     /** {@inheritDoc} */
118     @Override
119     public final float getSI(final int index) throws ValueRuntimeException
120     {
121         checkIndex(index);
122         return getData().getSI(index);
123     }
124 
125     /** {@inheritDoc} */
126     @Override
127     public S get(final int index) throws ValueRuntimeException
128     {
129         return FloatScalar.instantiateSI(getSI(index), getDisplayUnit());
130     }
131 
132     /** {@inheritDoc} */
133     @Override
134     public final float getInUnit(final int index) throws ValueRuntimeException
135     {
136         return (float) ValueUtil.expressAsUnit(getSI(index), getDisplayUnit());
137     }
138 
139     /** {@inheritDoc} */
140     @Override
141     public final float getInUnit(final int index, final U targetUnit) throws ValueRuntimeException
142     {
143         return (float) ValueUtil.expressAsUnit(getSI(index), targetUnit);
144     }
145 
146     /** {@inheritDoc} */
147     @Override
148     public final void setSI(final int index, final float valueSI) throws ValueRuntimeException
149     {
150         checkIndex(index);
151         checkCopyOnWrite();
152         getData().setSI(index, valueSI);
153     }
154 
155     /** {@inheritDoc} */
156     @Override
157     public void setInUnit(final int index, final float valueInUnit) throws ValueRuntimeException
158     {
159         setSI(index, (float) ValueUtil.expressAsSIUnit(valueInUnit, getDisplayUnit()));
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public void setInUnit(final int index, final float valueInUnit, final U valueUnit) throws ValueRuntimeException
165     {
166         setSI(index, (float) ValueUtil.expressAsSIUnit(valueInUnit, valueUnit));
167     }
168 
169     /** {@inheritDoc} */
170     @Override
171     public void set(final int index, final S value) throws ValueRuntimeException
172     {
173         setSI(index, value.si);
174     }
175 
176     /** {@inheritDoc} */
177     @SuppressWarnings("unchecked")
178     @Override
179     public S[] getScalars()
180     {
181         S[] array = (S[]) Array.newInstance(getScalarClass(), size());
182         for (int i = 0; i < size(); i++)
183         {
184             array[i] = get(i);
185         }
186         return array;
187     }
188 
189     /** {@inheritDoc} */
190     @SuppressWarnings("unchecked")
191     @Override
192     public V toSparse()
193     {
194         V result;
195         if (getStorageType().equals(StorageType.SPARSE))
196         {
197             result = (V) this;
198             result.setDisplayUnit(getDisplayUnit());
199         }
200         else
201         {
202             result = instantiateVector(getData().toSparse(), getDisplayUnit());
203         }
204         result.setDisplayUnit(getDisplayUnit());
205         return result;
206     }
207 
208     /** {@inheritDoc} */
209     @SuppressWarnings("unchecked")
210     @Override
211     public V toDense()
212     {
213         V result;
214         if (getStorageType().equals(StorageType.DENSE))
215         {
216             result = (V) this;
217             result.setDisplayUnit(getDisplayUnit());
218         }
219         else
220         {
221             result = instantiateVector(getData().toDense(), getDisplayUnit());
222         }
223         return result;
224     }
225 
226     /** {@inheritDoc} */
227     @SuppressWarnings("unchecked")
228     @Override
229     public final V assign(final FloatFunction floatFunction)
230     {
231         checkCopyOnWrite();
232         this.data.assign(floatFunction);
233         return (V) this;
234     }
235 
236     /** {@inheritDoc} */
237     @Override
238     public final V abs()
239     {
240         return assign(FloatMathFunctions.ABS);
241     }
242 
243     /** {@inheritDoc} */
244     @Override
245     public final V ceil()
246     {
247         return assign(FloatMathFunctions.CEIL);
248     }
249 
250     /** {@inheritDoc} */
251     @Override
252     public final V floor()
253     {
254         return assign(FloatMathFunctions.FLOOR);
255     }
256 
257     /** {@inheritDoc} */
258     @Override
259     public final V neg()
260     {
261         return assign(FloatMathFunctions.NEG);
262     }
263 
264     /** {@inheritDoc} */
265     @Override
266     public final V rint()
267     {
268         return assign(FloatMathFunctions.RINT);
269     }
270 
271     /** {@inheritDoc} */
272     @Override
273     public String toString()
274     {
275         return toString(getDisplayUnit(), false, true);
276     }
277 
278     /** {@inheritDoc} */
279     @Override
280     public String toString(final U displayUnit)
281     {
282         return toString(displayUnit, false, true);
283     }
284 
285     /** {@inheritDoc} */
286     @Override
287     public String toString(final boolean verbose, final boolean withUnit)
288     {
289         return toString(getDisplayUnit(), verbose, withUnit);
290     }
291 
292     /** {@inheritDoc} */
293     @Override
294     public String toString(final U displayUnit, final boolean verbose, final boolean withUnit)
295     {
296         StringBuffer buf = new StringBuffer();
297         if (verbose)
298         {
299             String ar = this instanceof Absolute ? "Abs " : "Rel ";
300             String ds = getData().isDense() ? "Dense  " : getData().isSparse() ? "Sparse " : "?????? ";
301             if (isMutable())
302             {
303                 buf.append("Mutable   " + ar + ds);
304             }
305             else
306             {
307                 buf.append("Immutable " + ar + ds);
308             }
309         }
310         buf.append("[");
311         for (int i = 0; i < size(); i++)
312         {
313             try
314             {
315                 float f = (float) ValueUtil.expressAsUnit(getSI(i), displayUnit);
316                 buf.append(" " + Format.format(f));
317             }
318             catch (ValueRuntimeException ve)
319             {
320                 buf.append(" " + "********************".substring(0, Format.DEFAULTSIZE));
321             }
322         }
323         buf.append("]");
324         if (withUnit)
325         {
326             buf.append(" " + displayUnit.getLocalizedDisplayAbbreviation());
327         }
328         return buf.toString();
329     }
330 
331     /**
332      * Centralized size equality check.
333      * @param other FloatVectorInterface&lt;?, ?, ?&gt;; other FloatVector
334      * @throws NullPointerException when other vector is null
335      * @throws ValueRuntimeException when vectors have unequal size
336      */
337     protected final void checkSize(final FloatVectorInterface<?, ?, ?> other) throws ValueRuntimeException
338     {
339         Throw.whenNull(other, "Other vector is null");
340         Throw.when(size() != other.size(), ValueRuntimeException.class, "The vectors have different sizes: %d != %d", size(),
341                 other.size());
342     }
343 
344     /** {@inheritDoc} */
345     @Override
346     @SuppressWarnings("checkstyle:designforextension")
347     public int hashCode()
348     {
349         final int prime = 31;
350         int result = getDisplayUnit().getStandardUnit().hashCode();
351         result = prime * result + ((this.data == null) ? 0 : this.data.hashCode());
352         return result;
353     }
354 
355     /** {@inheritDoc} */
356     @Override
357     @SuppressWarnings({"checkstyle:designforextension", "checkstyle:needbraces"})
358     public boolean equals(final Object obj)
359     {
360         if (this == obj)
361             return true;
362         if (obj == null)
363             return false;
364         if (getClass() != obj.getClass())
365             return false;
366         AbstractFloatVector<?, ?, ?> other = (AbstractFloatVector<?, ?, ?>) obj;
367         if (!getDisplayUnit().getStandardUnit().equals(other.getDisplayUnit().getStandardUnit()))
368             return false;
369         if (this.data == null)
370         {
371             if (other.data != null)
372                 return false;
373         }
374         else if (!this.data.equals(other.data))
375             return false;
376         return true;
377     }
378 
379     /* ============================================================================================ */
380     /* =============================== ITERATOR METHODS AND CLASS ================================= */
381     /* ============================================================================================ */
382 
383     /** {@inheritDoc} */
384     @Override
385     public Iterator<S> iterator()
386     {
387         return new Itr();
388     }
389 
390     /**
391      * The iterator class is loosely based in AbstractList.Itr. It does not throw a ConcurrentModificationException, because the
392      * size of the vector does not change. Normal (non-mutable) vectors cannot change their size, nor their content. The only
393      * thing for the MutableVector that can change is its content, not its length.
394      */
395     protected class Itr implements Iterator<S>, Serializable
396     {
397         /** ... */
398         private static final long serialVersionUID = 20191018L;
399 
400         /** index of next element to return. */
401         private int cursor = 0;
402 
403         /** {@inheritDoc} */
404         @Override
405         public boolean hasNext()
406         {
407             return this.cursor != size();
408         }
409 
410         /** {@inheritDoc} */
411         @Override
412         public S next()
413         {
414             if (this.cursor >= size())
415             {
416                 throw new NoSuchElementException();
417             }
418             try
419             {
420                 int i = this.cursor;
421                 S next = get(i);
422                 this.cursor = i + 1;
423                 return next;
424             }
425             catch (ValueRuntimeException exception)
426             {
427                 throw new RuntimeException(exception);
428             }
429         }
430 
431         /** {@inheritDoc} */
432         @Override
433         public void remove()
434         {
435             throw new RuntimeException("Remove function cannot be applied on fixed-size DJUNITS Vector");
436         }
437 
438         /** {@inheritDoc} */
439         @Override
440         public String toString()
441         {
442             return "Itr [cursor=" + this.cursor + "]";
443         }
444 
445     }
446 
447 }