1 package nl.tudelft.simulation.dsol.animation.graph;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7
8 /**
9 * FloatList is a random access list of float values to which values can only be appended. It stores the values as primitives
10 * rather than as wrapping Objects. For the rest, it behaves like a regular list, with the exception of the absence of the
11 * add(i, value) method and the remove methods.
12 * <p>
13 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
14 * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
15 * project is distributed under a three-clause BSD-style license, which can be found at
16 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
17 * </p>
18 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19 */
20 public class FloatAppendList implements Iterable<Float>, Serializable
21 {
22 /** */
23 private static final long serialVersionUID = 20210103L;
24
25 /** the chunk size. */
26 private static final int CHUNK_SIZE = 256;
27
28 /** the number of bits of the chunk size. */
29 private static final int CHUNK_BITS = 8;
30
31 /** the mask for the rightmost CHUNK_BITS bits. */
32 private static final int CHUNK_MASK = CHUNK_SIZE - 1;
33
34 /** the backing list with chunks. */
35 private final List<float[]> storage = new ArrayList<>();
36
37 /** the current chunk, already stored in the List. */
38 private float[] currentChunk;
39
40 /** the total number of elements. */
41 private int numElements;
42
43 /** the current in-chunk counter that indicates the next value to be written. */
44 private int inChunkNext;
45
46 /**
47 * Initialize the FloatAppendList.
48 */
49 public FloatAppendList()
50 {
51 this.numElements = 0;
52 this.inChunkNext = 0;
53 this.currentChunk = new float[CHUNK_SIZE];
54 this.storage.add(this.currentChunk);
55 }
56
57 /**
58 * Add a value to the list.
59 * @param value float; the value to add
60 */
61 public void add(final float value)
62 {
63 if (this.inChunkNext == CHUNK_SIZE)
64 {
65 this.inChunkNext = 0;
66 this.currentChunk = new float[CHUNK_SIZE];
67 this.storage.add(this.currentChunk);
68 }
69 this.currentChunk[this.inChunkNext] = value;
70 this.inChunkNext++;
71 this.numElements++;
72 }
73
74 /**
75 * Return the number of elements.
76 * @return int; the number of elements
77 */
78 public int size()
79 {
80 return this.numElements;
81 }
82
83 /**
84 * Return the value at a position.
85 * @param i int; the position
86 * @return float; the value at the position
87 * @throws IndexOutOfBoundsException when i < 0 or i > number of values
88 */
89 public float get(final int i)
90 {
91 if (i < 0 || i >= this.numElements)
92 {
93 throw new IndexOutOfBoundsException("FloatAppendList.get(i) -- i out of bounds.");
94 }
95 return this.storage.get(i >> CHUNK_BITS)[i & CHUNK_MASK];
96 }
97
98 /** {@inheritDoc} */
99 @Override
100 public Iterator<Float> iterator()
101 {
102 return new FloatAppendIterator(this);
103 }
104
105 /**
106 * An iterator for the FloatAppendList.
107 */
108 class FloatAppendIterator implements Iterator<Float>
109 {
110 /** the list to iterate over. */
111 private final FloatAppendList list;
112
113 /** the counter. */
114 private int counter;
115
116 /**
117 * Make an iterator for the FloatAppendList.
118 * @param list FloatAppendList; the list to iterate over
119 */
120 FloatAppendIterator(final FloatAppendList list)
121 {
122 this.list = list;
123 this.counter = 0;
124 }
125
126 /** {@inheritDoc} */
127 @Override
128 public boolean hasNext()
129 {
130 return this.counter < this.list.size();
131 }
132
133 /** {@inheritDoc} */
134 @Override
135 public Float next()
136 {
137 return this.list.get(this.counter++);
138 }
139 }
140
141 }