propane 3.1.0.pre-java → 3.2.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/CHANGELOG.md +1 -5
- data/README.md +23 -12
- data/Rakefile +23 -12
- data/lib/propane/helpers/version_error.rb +6 -0
- data/lib/propane/runner.rb +12 -0
- data/lib/propane/version.rb +1 -1
- data/library/slider/slider.rb +1 -1
- data/mvnw +234 -0
- data/mvnw.cmd +145 -0
- data/pom.xml +28 -27
- data/propane.gemspec +2 -2
- data/src/main/java/japplemenubar/JAppleMenuBar.java +41 -47
- data/src/main/java/monkstone/ColorUtil.java +1 -1
- data/src/main/java/monkstone/MathToolModule.java +12 -11
- data/src/main/java/monkstone/PropaneLibrary.java +9 -10
- data/src/main/java/monkstone/core/LibraryProxy.java +124 -113
- data/src/main/java/monkstone/fastmath/Deglut.java +86 -89
- data/src/main/java/monkstone/filechooser/Chooser.java +7 -13
- data/src/main/java/monkstone/noise/SimplexNoise.java +0 -1
- data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +4 -4
- data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +9 -9
- data/src/main/java/monkstone/slider/SimpleSlider.java +0 -9
- data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +11 -13
- data/src/main/java/monkstone/slider/Slider.java +1 -1
- data/src/main/java/monkstone/slider/SliderBar.java +1 -1
- data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
- data/src/main/java/monkstone/slider/WheelHandler.java +8 -9
- data/src/main/java/monkstone/vecmath/AppRender.java +2 -2
- data/src/main/java/monkstone/vecmath/ShapeRender.java +2 -2
- data/src/main/java/monkstone/vecmath/package-info.java +2 -2
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
- data/src/main/java/monkstone/videoevent/VideoInterface.java +11 -5
- data/src/main/java/monkstone/videoevent/package-info.java +2 -2
- data/src/main/java/processing/awt/PGraphicsJava2D.java +1742 -2243
- data/src/main/java/processing/awt/PShapeJava2D.java +268 -270
- data/src/main/java/processing/awt/PSurfaceAWT.java +821 -920
- data/src/main/java/processing/core/DesktopHandler.java +94 -0
- data/src/main/java/processing/core/PApplet.java +14170 -14082
- data/src/main/java/processing/core/PConstants.java +447 -473
- data/src/main/java/processing/core/PFont.java +867 -873
- data/src/main/java/processing/core/PGraphics.java +7193 -7428
- data/src/main/java/processing/core/PImage.java +3051 -3117
- data/src/main/java/processing/core/PMatrix.java +159 -172
- data/src/main/java/processing/core/PMatrix2D.java +403 -444
- data/src/main/java/processing/core/PMatrix3D.java +735 -749
- data/src/main/java/processing/core/PShape.java +2651 -2793
- data/src/main/java/processing/core/PShapeOBJ.java +415 -422
- data/src/main/java/processing/core/PShapeSVG.java +1466 -1475
- data/src/main/java/processing/core/PStyle.java +37 -40
- data/src/main/java/processing/core/PSurface.java +98 -103
- data/src/main/java/processing/core/PSurfaceNone.java +208 -236
- data/src/main/java/processing/core/PVector.java +961 -990
- data/src/main/java/processing/data/DoubleDict.java +709 -753
- data/src/main/java/processing/data/DoubleList.java +695 -748
- data/src/main/java/processing/data/FloatDict.java +702 -746
- data/src/main/java/processing/data/FloatList.java +697 -751
- data/src/main/java/processing/data/IntDict.java +673 -718
- data/src/main/java/processing/data/IntList.java +633 -699
- data/src/main/java/processing/data/JSONArray.java +873 -931
- data/src/main/java/processing/data/JSONObject.java +1165 -1262
- data/src/main/java/processing/data/JSONTokener.java +341 -351
- data/src/main/java/processing/data/LongDict.java +662 -707
- data/src/main/java/processing/data/LongList.java +634 -700
- data/src/main/java/processing/data/Sort.java +41 -37
- data/src/main/java/processing/data/StringDict.java +486 -522
- data/src/main/java/processing/data/StringList.java +580 -624
- data/src/main/java/processing/data/Table.java +3508 -3686
- data/src/main/java/processing/data/TableRow.java +183 -182
- data/src/main/java/processing/data/XML.java +883 -957
- data/src/main/java/processing/event/Event.java +66 -87
- data/src/main/java/processing/event/KeyEvent.java +41 -48
- data/src/main/java/processing/event/MouseEvent.java +93 -103
- data/src/main/java/processing/event/TouchEvent.java +6 -10
- data/src/main/java/processing/javafx/PGraphicsFX2D.java +5 -69
- data/src/main/java/processing/javafx/PSurfaceFX.java +2 -7
- data/src/main/java/processing/opengl/FontTexture.java +270 -290
- data/src/main/java/processing/opengl/FrameBuffer.java +363 -375
- data/src/main/java/processing/opengl/LinePath.java +500 -543
- data/src/main/java/processing/opengl/LineStroker.java +582 -593
- data/src/main/java/processing/opengl/PGL.java +2881 -2904
- data/src/main/java/processing/opengl/PGraphics2D.java +315 -408
- data/src/main/java/processing/opengl/PGraphics3D.java +72 -107
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12043 -12230
- data/src/main/java/processing/opengl/PJOGL.java +1681 -1745
- data/src/main/java/processing/opengl/PShader.java +1257 -1260
- data/src/main/java/processing/opengl/PShapeOpenGL.java +4599 -4662
- data/src/main/java/processing/opengl/PSurfaceJOGL.java +1030 -1047
- data/src/main/java/processing/opengl/Texture.java +1397 -1462
- data/src/main/java/processing/opengl/VertexBuffer.java +55 -57
- data/src/main/resources/icon/icon-1024.png +0 -0
- data/src/main/resources/icon/icon-128.png +0 -0
- data/src/main/resources/icon/icon-16.png +0 -0
- data/src/main/resources/icon/icon-256.png +0 -0
- data/src/main/resources/icon/icon-32.png +0 -0
- data/src/main/resources/icon/icon-48.png +0 -0
- data/src/main/resources/icon/icon-512.png +0 -0
- data/src/main/resources/icon/icon-64.png +0 -0
- data/vendors/Rakefile +1 -1
- metadata +12 -8
- data/src/main/java/processing/core/ThinkDifferent.java +0 -70
|
@@ -7,7 +7,6 @@ import java.util.Map;
|
|
|
7
7
|
|
|
8
8
|
import processing.core.PApplet;
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
/**
|
|
12
11
|
* A simple table class to use a String as a lookup for an double value.
|
|
13
12
|
*
|
|
@@ -17,832 +16,789 @@ import processing.core.PApplet;
|
|
|
17
16
|
*/
|
|
18
17
|
public class DoubleDict {
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @nowebref
|
|
75
|
-
*/
|
|
76
|
-
public DoubleDict(String[] keys, double[] values) {
|
|
77
|
-
if (keys.length != values.length) {
|
|
78
|
-
throw new IllegalArgumentException("key and value arrays must be the same length");
|
|
79
|
-
}
|
|
80
|
-
this.keys = keys;
|
|
81
|
-
this.values = values;
|
|
82
|
-
count = keys.length;
|
|
83
|
-
for (int i = 0; i < count; i++) {
|
|
84
|
-
indices.put(keys[i], i);
|
|
19
|
+
/**
|
|
20
|
+
* Number of elements in the table
|
|
21
|
+
*/
|
|
22
|
+
protected int count;
|
|
23
|
+
|
|
24
|
+
protected String[] keys;
|
|
25
|
+
protected double[] values;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Internal implementation for faster lookups
|
|
29
|
+
*/
|
|
30
|
+
private HashMap<String, Integer> indices = new HashMap<>();
|
|
31
|
+
|
|
32
|
+
public DoubleDict() {
|
|
33
|
+
count = 0;
|
|
34
|
+
keys = new String[10];
|
|
35
|
+
values = new double[10];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Create a new lookup with a specific size. This is more efficient than not
|
|
40
|
+
* specifying a size. Use it when you know the rough size of the thing
|
|
41
|
+
* you're creating.
|
|
42
|
+
*
|
|
43
|
+
* @nowebref
|
|
44
|
+
*/
|
|
45
|
+
public DoubleDict(int length) {
|
|
46
|
+
count = 0;
|
|
47
|
+
keys = new String[length];
|
|
48
|
+
values = new double[length];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Read a set of entries from a Reader that has each key/value pair on a
|
|
53
|
+
* single line, separated by a tab.
|
|
54
|
+
*
|
|
55
|
+
* @nowebref
|
|
56
|
+
*/
|
|
57
|
+
public DoubleDict(BufferedReader reader) {
|
|
58
|
+
String[] lines = PApplet.loadStrings(reader);
|
|
59
|
+
keys = new String[lines.length];
|
|
60
|
+
values = new double[lines.length];
|
|
61
|
+
|
|
62
|
+
for (int i = 0; i < lines.length; i++) {
|
|
63
|
+
String[] pieces = PApplet.split(lines[i], '\t');
|
|
64
|
+
if (pieces.length == 2) {
|
|
65
|
+
keys[count] = pieces[0];
|
|
66
|
+
values[count] = PApplet.parseFloat(pieces[1]);
|
|
67
|
+
indices.put(pieces[0], count);
|
|
68
|
+
count++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
85
71
|
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
72
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
for (int i = 0; i < count; i++) {
|
|
103
|
-
keys[i] = (String) pairs[i][0];
|
|
104
|
-
values[i] = (Float) pairs[i][1];
|
|
105
|
-
indices.put(keys[i], i);
|
|
73
|
+
/**
|
|
74
|
+
* @nowebref
|
|
75
|
+
*/
|
|
76
|
+
public DoubleDict(String[] keys, double[] values) {
|
|
77
|
+
if (keys.length != values.length) {
|
|
78
|
+
throw new IllegalArgumentException("key and value arrays must be the same length");
|
|
79
|
+
}
|
|
80
|
+
this.keys = keys;
|
|
81
|
+
this.values = values;
|
|
82
|
+
count = keys.length;
|
|
83
|
+
for (int i = 0; i < count; i++) {
|
|
84
|
+
indices.put(keys[i], i);
|
|
85
|
+
}
|
|
106
86
|
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
87
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Constructor to allow (more intuitive) inline initialization, e.g.:
|
|
90
|
+
* <pre>
|
|
91
|
+
* new FloatDict(new Object[][] {
|
|
92
|
+
* { "key1", 1 },
|
|
93
|
+
* { "key2", 2 }
|
|
94
|
+
* });
|
|
95
|
+
* </pre>
|
|
96
|
+
*/
|
|
97
|
+
public DoubleDict(Object[][] pairs) {
|
|
98
|
+
count = pairs.length;
|
|
99
|
+
this.keys = new String[count];
|
|
100
|
+
this.values = new double[count];
|
|
101
|
+
for (int i = 0; i < count; i++) {
|
|
102
|
+
keys[i] = (String) pairs[i][0];
|
|
103
|
+
values[i] = (Float) pairs[i][1];
|
|
104
|
+
indices.put(keys[i], i);
|
|
105
|
+
}
|
|
120
106
|
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* @webref doubledict:method
|
|
126
|
-
* @brief Returns the number of key/value pairs
|
|
127
|
-
*/
|
|
128
|
-
public int size() {
|
|
129
|
-
return count;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
107
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
|
|
108
|
+
public DoubleDict(Map<String, Double> incoming) {
|
|
109
|
+
count = incoming.size();
|
|
110
|
+
keys = new String[count];
|
|
111
|
+
values = new double[count];
|
|
112
|
+
int index = 0;
|
|
113
|
+
for (Map.Entry<String, Double> e : incoming.entrySet()) {
|
|
114
|
+
keys[index] = e.getKey();
|
|
115
|
+
values[index] = e.getValue();
|
|
116
|
+
indices.put(keys[index], index);
|
|
117
|
+
index++;
|
|
118
|
+
}
|
|
145
119
|
}
|
|
146
120
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
resetIndices();
|
|
155
|
-
}
|
|
156
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @webref doubledict:method
|
|
123
|
+
* @brief Returns the number of key/value pairs
|
|
124
|
+
*/
|
|
125
|
+
public int size() {
|
|
126
|
+
return count;
|
|
127
|
+
}
|
|
157
128
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
indices = new HashMap<>();
|
|
167
|
-
}
|
|
129
|
+
/**
|
|
130
|
+
* Resize the internal data, this can only be used to shrink the list.
|
|
131
|
+
* Helpful for situations like sorting and then grabbing the top 50 entries.
|
|
132
|
+
*/
|
|
133
|
+
public void resize(int length) {
|
|
134
|
+
if (length == count) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
168
137
|
|
|
138
|
+
if (length > count) {
|
|
139
|
+
throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
|
|
140
|
+
}
|
|
141
|
+
if (length < 1) {
|
|
142
|
+
throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
|
|
143
|
+
}
|
|
169
144
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
145
|
+
String[] newKeys = new String[length];
|
|
146
|
+
double[] newValues = new double[length];
|
|
147
|
+
PApplet.arrayCopy(keys, newKeys, length);
|
|
148
|
+
PApplet.arrayCopy(values, newValues, length);
|
|
149
|
+
keys = newKeys;
|
|
150
|
+
values = newValues;
|
|
151
|
+
count = length;
|
|
152
|
+
resetIndices();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Remove all entries.
|
|
157
|
+
*
|
|
158
|
+
* @webref doubledict:method
|
|
159
|
+
* @brief Remove all entries
|
|
160
|
+
*/
|
|
161
|
+
public void clear() {
|
|
162
|
+
count = 0;
|
|
163
|
+
indices = new HashMap<>();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private void resetIndices() {
|
|
167
|
+
indices = new HashMap<>(count);
|
|
168
|
+
for (int i = 0; i < count; i++) {
|
|
169
|
+
indices.put(keys[i], i);
|
|
170
|
+
}
|
|
174
171
|
}
|
|
175
|
-
}
|
|
176
172
|
|
|
173
|
+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
174
|
+
public class Entry {
|
|
177
175
|
|
|
178
|
-
|
|
176
|
+
public String key;
|
|
177
|
+
public double value;
|
|
179
178
|
|
|
179
|
+
Entry(String key, double value) {
|
|
180
|
+
this.key = key;
|
|
181
|
+
this.value = value;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
public double value;
|
|
185
|
+
public Iterable<Entry> entries() {
|
|
186
|
+
return new Iterable<Entry>() {
|
|
184
187
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
public Iterator<Entry> iterator() {
|
|
189
|
+
return entryIterator();
|
|
190
|
+
}
|
|
191
|
+
};
|
|
188
192
|
}
|
|
189
|
-
}
|
|
190
193
|
|
|
194
|
+
public Iterator<Entry> entryIterator() {
|
|
195
|
+
return new Iterator<Entry>() {
|
|
196
|
+
int index = -1;
|
|
191
197
|
|
|
192
|
-
|
|
193
|
-
|
|
198
|
+
public void remove() {
|
|
199
|
+
removeIndex(index);
|
|
200
|
+
index--;
|
|
201
|
+
}
|
|
194
202
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
public Entry next() {
|
|
204
|
+
++index;
|
|
205
|
+
Entry e = new Entry(keys[index], values[index]);
|
|
206
|
+
return e;
|
|
207
|
+
}
|
|
200
208
|
|
|
209
|
+
public boolean hasNext() {
|
|
210
|
+
return index + 1 < size();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
201
214
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
|
216
|
+
public String key(int index) {
|
|
217
|
+
return keys[index];
|
|
218
|
+
}
|
|
205
219
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
220
|
+
protected void crop() {
|
|
221
|
+
if (count != keys.length) {
|
|
222
|
+
keys = PApplet.subset(keys, 0, count);
|
|
223
|
+
values = PApplet.subset(values, 0, count);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
210
226
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
Entry e = new Entry(keys[index], values[index]);
|
|
214
|
-
return e;
|
|
215
|
-
}
|
|
227
|
+
public Iterable<String> keys() {
|
|
228
|
+
return new Iterable<String>() {
|
|
216
229
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
230
|
+
@Override
|
|
231
|
+
public Iterator<String> iterator() {
|
|
232
|
+
return keyIterator();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
222
236
|
|
|
237
|
+
// Use this to iterate when you want to be able to remove elements along the way
|
|
238
|
+
public Iterator<String> keyIterator() {
|
|
239
|
+
return new Iterator<String>() {
|
|
240
|
+
int index = -1;
|
|
223
241
|
|
|
224
|
-
|
|
242
|
+
public void remove() {
|
|
243
|
+
removeIndex(index);
|
|
244
|
+
index--;
|
|
245
|
+
}
|
|
225
246
|
|
|
247
|
+
public String next() {
|
|
248
|
+
return key(++index);
|
|
249
|
+
}
|
|
226
250
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
251
|
+
public boolean hasNext() {
|
|
252
|
+
return index + 1 < size();
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
230
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Return a copy of the internal keys array. This array can be modified.
|
|
259
|
+
*
|
|
260
|
+
* @webref doubledict:method
|
|
261
|
+
* @brief Return a copy of the internal keys array
|
|
262
|
+
*/
|
|
263
|
+
public String[] keyArray() {
|
|
264
|
+
crop();
|
|
265
|
+
return keyArray(null);
|
|
266
|
+
}
|
|
231
267
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
268
|
+
public String[] keyArray(String[] outgoing) {
|
|
269
|
+
if (outgoing == null || outgoing.length != count) {
|
|
270
|
+
outgoing = new String[count];
|
|
271
|
+
}
|
|
272
|
+
System.arraycopy(keys, 0, outgoing, 0, count);
|
|
273
|
+
return outgoing;
|
|
236
274
|
}
|
|
237
|
-
}
|
|
238
275
|
|
|
276
|
+
public double value(int index) {
|
|
277
|
+
return values[index];
|
|
278
|
+
}
|
|
239
279
|
|
|
240
|
-
|
|
241
|
-
|
|
280
|
+
/**
|
|
281
|
+
* @webref doubledict:method
|
|
282
|
+
* @brief Return the internal array being used to store the values
|
|
283
|
+
*/
|
|
284
|
+
public Iterable<Double> values() {
|
|
285
|
+
return new Iterable<Double>() {
|
|
242
286
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
287
|
+
@Override
|
|
288
|
+
public Iterator<Double> iterator() {
|
|
289
|
+
return valueIterator();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
249
293
|
|
|
294
|
+
public Iterator<Double> valueIterator() {
|
|
295
|
+
return new Iterator<Double>() {
|
|
296
|
+
int index = -1;
|
|
250
297
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
298
|
+
public void remove() {
|
|
299
|
+
removeIndex(index);
|
|
300
|
+
index--;
|
|
301
|
+
}
|
|
255
302
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
303
|
+
public Double next() {
|
|
304
|
+
return value(++index);
|
|
305
|
+
}
|
|
260
306
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
307
|
+
public boolean hasNext() {
|
|
308
|
+
return index + 1 < size();
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Create a new array and copy each of the values into it.
|
|
315
|
+
*
|
|
316
|
+
* @webref doubledict:method
|
|
317
|
+
* @brief Create a new array and copy each of the values into it
|
|
318
|
+
*/
|
|
319
|
+
public double[] valueArray() {
|
|
320
|
+
crop();
|
|
321
|
+
return valueArray(null);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Fill an already-allocated array with the values (more efficient than
|
|
326
|
+
* creating a new array each time). If 'array' is null, or not the same size
|
|
327
|
+
* as the number of values, a new array will be allocated and returned.
|
|
328
|
+
*/
|
|
329
|
+
public double[] valueArray(double[] array) {
|
|
330
|
+
if (array == null || array.length != size()) {
|
|
331
|
+
array = new double[count];
|
|
332
|
+
}
|
|
333
|
+
System.arraycopy(values, 0, array, 0, count);
|
|
334
|
+
return array;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Return a value for the specified key.
|
|
339
|
+
*
|
|
340
|
+
* @webref doubledict:method
|
|
341
|
+
* @brief Return a value for the specified key
|
|
342
|
+
*/
|
|
343
|
+
public double get(String key) {
|
|
344
|
+
int index = index(key);
|
|
345
|
+
if (index == -1) {
|
|
346
|
+
throw new IllegalArgumentException("No key named '" + key + "'");
|
|
347
|
+
}
|
|
348
|
+
return values[index];
|
|
349
|
+
}
|
|
264
350
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
351
|
+
public double get(String key, double alternate) {
|
|
352
|
+
int index = index(key);
|
|
353
|
+
if (index == -1) {
|
|
354
|
+
return alternate;
|
|
355
|
+
}
|
|
356
|
+
return values[index];
|
|
357
|
+
}
|
|
270
358
|
|
|
359
|
+
/**
|
|
360
|
+
* @webref doubledict:method
|
|
361
|
+
* @brief Create a new key/value pair or change the value of one
|
|
362
|
+
*/
|
|
363
|
+
public void set(String key, double amount) {
|
|
364
|
+
int index = index(key);
|
|
365
|
+
if (index == -1) {
|
|
366
|
+
create(key, amount);
|
|
367
|
+
} else {
|
|
368
|
+
values[index] = amount;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
271
371
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
372
|
+
public void setIndex(int index, String key, double value) {
|
|
373
|
+
if (index < 0 || index >= count) {
|
|
374
|
+
throw new ArrayIndexOutOfBoundsException(index);
|
|
375
|
+
}
|
|
376
|
+
keys[index] = key;
|
|
377
|
+
values[index] = value;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* @webref doubledict:method
|
|
382
|
+
* @brief Check if a key is a part of the data structure
|
|
383
|
+
*/
|
|
384
|
+
public boolean hasKey(String key) {
|
|
385
|
+
return index(key) != -1;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @webref doubledict:method
|
|
390
|
+
* @brief Add to a value
|
|
391
|
+
*/
|
|
392
|
+
public void add(String key, double amount) {
|
|
393
|
+
int index = index(key);
|
|
394
|
+
if (index == -1) {
|
|
395
|
+
create(key, amount);
|
|
396
|
+
} else {
|
|
397
|
+
values[index] += amount;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
282
400
|
|
|
401
|
+
/**
|
|
402
|
+
* @webref doubledict:method
|
|
403
|
+
* @brief Subtract from a value
|
|
404
|
+
*/
|
|
405
|
+
public void sub(String key, double amount) {
|
|
406
|
+
add(key, -amount);
|
|
407
|
+
}
|
|
283
408
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
409
|
+
/**
|
|
410
|
+
* @webref doubledict:method
|
|
411
|
+
* @brief Multiply a value
|
|
412
|
+
*/
|
|
413
|
+
public void mult(String key, double amount) {
|
|
414
|
+
int index = index(key);
|
|
415
|
+
if (index != -1) {
|
|
416
|
+
values[index] *= amount;
|
|
417
|
+
}
|
|
287
418
|
}
|
|
288
|
-
System.arraycopy(keys, 0, outgoing, 0, count);
|
|
289
|
-
return outgoing;
|
|
290
|
-
}
|
|
291
419
|
|
|
420
|
+
/**
|
|
421
|
+
* @webref doubledict:method
|
|
422
|
+
* @brief Divide a value
|
|
423
|
+
*/
|
|
424
|
+
public void div(String key, double amount) {
|
|
425
|
+
int index = index(key);
|
|
426
|
+
if (index != -1) {
|
|
427
|
+
values[index] /= amount;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
292
430
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
431
|
+
private void checkMinMax(String functionName) {
|
|
432
|
+
if (count == 0) {
|
|
433
|
+
String msg
|
|
434
|
+
= String.format("Cannot use %s() on an empty %s.",
|
|
435
|
+
functionName, getClass().getSimpleName());
|
|
436
|
+
throw new RuntimeException(msg);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
297
439
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
440
|
+
/**
|
|
441
|
+
* @webref doublelist:method
|
|
442
|
+
* @brief Return the smallest value
|
|
443
|
+
*/
|
|
444
|
+
public int minIndex() {
|
|
445
|
+
//checkMinMax("minIndex");
|
|
446
|
+
if (count == 0) {
|
|
447
|
+
return -1;
|
|
448
|
+
}
|
|
304
449
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
450
|
+
// Will still return NaN if there are 1 or more entries, and they're all NaN
|
|
451
|
+
double m = Float.NaN;
|
|
452
|
+
int mi = -1;
|
|
453
|
+
for (int i = 0; i < count; i++) {
|
|
454
|
+
// find one good value to start
|
|
455
|
+
if (values[i] == values[i]) {
|
|
456
|
+
m = values[i];
|
|
457
|
+
mi = i;
|
|
458
|
+
|
|
459
|
+
// calculate the rest
|
|
460
|
+
for (int j = i + 1; j < count; j++) {
|
|
461
|
+
double d = values[j];
|
|
462
|
+
if ((d == d) && (d < m)) {
|
|
463
|
+
m = values[j];
|
|
464
|
+
mi = j;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return mi;
|
|
471
|
+
}
|
|
311
472
|
|
|
473
|
+
// return the key for the minimum value
|
|
474
|
+
public String minKey() {
|
|
475
|
+
checkMinMax("minKey");
|
|
476
|
+
int index = minIndex();
|
|
477
|
+
if (index == -1) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
return keys[index];
|
|
481
|
+
}
|
|
312
482
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
483
|
+
// return the minimum value, or throw an error if there are no values
|
|
484
|
+
public double minValue() {
|
|
485
|
+
checkMinMax("minValue");
|
|
486
|
+
int index = minIndex();
|
|
487
|
+
if (index == -1) {
|
|
488
|
+
return Float.NaN;
|
|
489
|
+
}
|
|
490
|
+
return values[index];
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* @webref doublelist:method
|
|
495
|
+
* @brief Return the largest value
|
|
496
|
+
*/
|
|
497
|
+
// The index of the entry that has the max value. Reference above is incorrect.
|
|
498
|
+
public int maxIndex() {
|
|
499
|
+
//checkMinMax("maxIndex");
|
|
500
|
+
if (count == 0) {
|
|
501
|
+
return -1;
|
|
502
|
+
}
|
|
503
|
+
// Will still return NaN if there is 1 or more entries, and they're all NaN
|
|
504
|
+
double m = Double.NaN;
|
|
505
|
+
int mi = -1;
|
|
506
|
+
for (int i = 0; i < count; i++) {
|
|
507
|
+
// find one good value to start
|
|
508
|
+
if (values[i] == values[i]) {
|
|
509
|
+
m = values[i];
|
|
510
|
+
mi = i;
|
|
511
|
+
|
|
512
|
+
// calculate the rest
|
|
513
|
+
for (int j = i + 1; j < count; j++) {
|
|
514
|
+
double d = values[j];
|
|
515
|
+
if (!Double.isNaN(d) && (d > m)) {
|
|
516
|
+
m = values[j];
|
|
517
|
+
mi = j;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return mi;
|
|
524
|
+
}
|
|
316
525
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
526
|
+
/**
|
|
527
|
+
* The key for a max value; null if empty or everything is NaN (no max).
|
|
528
|
+
*/
|
|
529
|
+
public String maxKey() {
|
|
530
|
+
//checkMinMax("maxKey");
|
|
531
|
+
int index = maxIndex();
|
|
532
|
+
if (index == -1) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
return keys[index];
|
|
536
|
+
}
|
|
321
537
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Create a new array and copy each of the values into it.
|
|
335
|
-
*
|
|
336
|
-
* @webref doubledict:method
|
|
337
|
-
* @brief Create a new array and copy each of the values into it
|
|
338
|
-
*/
|
|
339
|
-
public double[] valueArray() {
|
|
340
|
-
crop();
|
|
341
|
-
return valueArray(null);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Fill an already-allocated array with the values (more efficient than
|
|
347
|
-
* creating a new array each time). If 'array' is null, or not the same
|
|
348
|
-
* size as the number of values, a new array will be allocated and returned.
|
|
349
|
-
*/
|
|
350
|
-
public double[] valueArray(double[] array) {
|
|
351
|
-
if (array == null || array.length != size()) {
|
|
352
|
-
array = new double[count];
|
|
353
|
-
}
|
|
354
|
-
System.arraycopy(values, 0, array, 0, count);
|
|
355
|
-
return array;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Return a value for the specified key.
|
|
361
|
-
*
|
|
362
|
-
* @webref doubledict:method
|
|
363
|
-
* @brief Return a value for the specified key
|
|
364
|
-
*/
|
|
365
|
-
public double get(String key) {
|
|
366
|
-
int index = index(key);
|
|
367
|
-
if (index == -1) {
|
|
368
|
-
throw new IllegalArgumentException("No key named '" + key + "'");
|
|
369
|
-
}
|
|
370
|
-
return values[index];
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
public double get(String key, double alternate) {
|
|
375
|
-
int index = index(key);
|
|
376
|
-
if (index == -1) {
|
|
377
|
-
return alternate;
|
|
378
|
-
}
|
|
379
|
-
return values[index];
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* @webref doubledict:method
|
|
385
|
-
* @brief Create a new key/value pair or change the value of one
|
|
386
|
-
*/
|
|
387
|
-
public void set(String key, double amount) {
|
|
388
|
-
int index = index(key);
|
|
389
|
-
if (index == -1) {
|
|
390
|
-
create(key, amount);
|
|
391
|
-
} else {
|
|
392
|
-
values[index] = amount;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
public void setIndex(int index, String key, double value) {
|
|
398
|
-
if (index < 0 || index >= count) {
|
|
399
|
-
throw new ArrayIndexOutOfBoundsException(index);
|
|
400
|
-
}
|
|
401
|
-
keys[index] = key;
|
|
402
|
-
values[index] = value;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* @webref doubledict:method
|
|
408
|
-
* @brief Check if a key is a part of the data structure
|
|
409
|
-
*/
|
|
410
|
-
public boolean hasKey(String key) {
|
|
411
|
-
return index(key) != -1;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* @webref doubledict:method
|
|
417
|
-
* @brief Add to a value
|
|
418
|
-
*/
|
|
419
|
-
public void add(String key, double amount) {
|
|
420
|
-
int index = index(key);
|
|
421
|
-
if (index == -1) {
|
|
422
|
-
create(key, amount);
|
|
423
|
-
} else {
|
|
424
|
-
values[index] += amount;
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* @webref doubledict:method
|
|
431
|
-
* @brief Subtract from a value
|
|
432
|
-
*/
|
|
433
|
-
public void sub(String key, double amount) {
|
|
434
|
-
add(key, -amount);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* @webref doubledict:method
|
|
440
|
-
* @brief Multiply a value
|
|
441
|
-
*/
|
|
442
|
-
public void mult(String key, double amount) {
|
|
443
|
-
int index = index(key);
|
|
444
|
-
if (index != -1) {
|
|
445
|
-
values[index] *= amount;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* @webref doubledict:method
|
|
452
|
-
* @brief Divide a value
|
|
453
|
-
*/
|
|
454
|
-
public void div(String key, double amount) {
|
|
455
|
-
int index = index(key);
|
|
456
|
-
if (index != -1) {
|
|
457
|
-
values[index] /= amount;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
private void checkMinMax(String functionName) {
|
|
463
|
-
if (count == 0) {
|
|
464
|
-
String msg =
|
|
465
|
-
String.format("Cannot use %s() on an empty %s.",
|
|
466
|
-
functionName, getClass().getSimpleName());
|
|
467
|
-
throw new RuntimeException(msg);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* @webref doublelist:method
|
|
474
|
-
* @brief Return the smallest value
|
|
475
|
-
*/
|
|
476
|
-
public int minIndex() {
|
|
477
|
-
//checkMinMax("minIndex");
|
|
478
|
-
if (count == 0) return -1;
|
|
479
|
-
|
|
480
|
-
// Will still return NaN if there are 1 or more entries, and they're all NaN
|
|
481
|
-
double m = Float.NaN;
|
|
482
|
-
int mi = -1;
|
|
483
|
-
for (int i = 0; i < count; i++) {
|
|
484
|
-
// find one good value to start
|
|
485
|
-
if (values[i] == values[i]) {
|
|
486
|
-
m = values[i];
|
|
487
|
-
mi = i;
|
|
488
|
-
|
|
489
|
-
// calculate the rest
|
|
490
|
-
for (int j = i+1; j < count; j++) {
|
|
491
|
-
double d = values[j];
|
|
492
|
-
if ((d == d) && (d < m)) {
|
|
493
|
-
m = values[j];
|
|
494
|
-
mi = j;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
break;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
return mi;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
// return the key for the minimum value
|
|
505
|
-
public String minKey() {
|
|
506
|
-
checkMinMax("minKey");
|
|
507
|
-
int index = minIndex();
|
|
508
|
-
if (index == -1) {
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
|
-
return keys[index];
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
// return the minimum value, or throw an error if there are no values
|
|
516
|
-
public double minValue() {
|
|
517
|
-
checkMinMax("minValue");
|
|
518
|
-
int index = minIndex();
|
|
519
|
-
if (index == -1) {
|
|
520
|
-
return Float.NaN;
|
|
521
|
-
}
|
|
522
|
-
return values[index];
|
|
523
|
-
}
|
|
538
|
+
/**
|
|
539
|
+
* The max value. (Or NaN if no entries or they're all NaN.)
|
|
540
|
+
*/
|
|
541
|
+
public double maxValue() {
|
|
542
|
+
//checkMinMax("maxValue");
|
|
543
|
+
int index = maxIndex();
|
|
544
|
+
if (index == -1) {
|
|
545
|
+
return Float.NaN;
|
|
546
|
+
}
|
|
547
|
+
return values[index];
|
|
548
|
+
}
|
|
524
549
|
|
|
550
|
+
public double sum() {
|
|
551
|
+
double sum = 0;
|
|
552
|
+
for (int i = 0; i < count; i++) {
|
|
553
|
+
sum += values[i];
|
|
554
|
+
}
|
|
555
|
+
return sum;
|
|
556
|
+
}
|
|
525
557
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
// The index of the entry that has the max value. Reference above is incorrect.
|
|
531
|
-
public int maxIndex() {
|
|
532
|
-
//checkMinMax("maxIndex");
|
|
533
|
-
if (count == 0) {
|
|
534
|
-
return -1;
|
|
535
|
-
}
|
|
536
|
-
// Will still return NaN if there is 1 or more entries, and they're all NaN
|
|
537
|
-
double m = Double.NaN;
|
|
538
|
-
int mi = -1;
|
|
539
|
-
for (int i = 0; i < count; i++) {
|
|
540
|
-
// find one good value to start
|
|
541
|
-
if (values[i] == values[i]) {
|
|
542
|
-
m = values[i];
|
|
543
|
-
mi = i;
|
|
544
|
-
|
|
545
|
-
// calculate the rest
|
|
546
|
-
for (int j = i+1; j < count; j++) {
|
|
547
|
-
double d = values[j];
|
|
548
|
-
if (!Double.isNaN(d) && (d > m)) {
|
|
549
|
-
m = values[j];
|
|
550
|
-
mi = j;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
break;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
return mi;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
/** The key for a max value; null if empty or everything is NaN (no max). */
|
|
561
|
-
public String maxKey() {
|
|
562
|
-
//checkMinMax("maxKey");
|
|
563
|
-
int index = maxIndex();
|
|
564
|
-
if (index == -1) {
|
|
565
|
-
return null;
|
|
566
|
-
}
|
|
567
|
-
return keys[index];
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
/** The max value. (Or NaN if no entries or they're all NaN.) */
|
|
572
|
-
public double maxValue() {
|
|
573
|
-
//checkMinMax("maxValue");
|
|
574
|
-
int index = maxIndex();
|
|
575
|
-
if (index == -1) {
|
|
576
|
-
return Float.NaN;
|
|
577
|
-
}
|
|
578
|
-
return values[index];
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
public double sum() {
|
|
583
|
-
double sum = 0;
|
|
584
|
-
for (int i = 0; i < count; i++) {
|
|
585
|
-
sum += values[i];
|
|
586
|
-
}
|
|
587
|
-
return sum;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
public int index(String what) {
|
|
592
|
-
Integer found = indices.get(what);
|
|
593
|
-
return (found == null) ? -1 : found.intValue();
|
|
594
|
-
}
|
|
558
|
+
public int index(String what) {
|
|
559
|
+
Integer found = indices.get(what);
|
|
560
|
+
return (found == null) ? -1 : found.intValue();
|
|
561
|
+
}
|
|
595
562
|
|
|
563
|
+
protected void create(String what, double much) {
|
|
564
|
+
if (count == keys.length) {
|
|
565
|
+
keys = PApplet.expand(keys);
|
|
566
|
+
values = PApplet.expand(values);
|
|
567
|
+
}
|
|
568
|
+
indices.put(what, Integer.valueOf(count));
|
|
569
|
+
keys[count] = what;
|
|
570
|
+
values[count] = much;
|
|
571
|
+
count++;
|
|
572
|
+
}
|
|
596
573
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
/**
|
|
610
|
-
* @webref doubledict:method
|
|
611
|
-
* @brief Remove a key/value pair
|
|
612
|
-
*/
|
|
613
|
-
public int remove(String key) {
|
|
614
|
-
int index = index(key);
|
|
615
|
-
if (index != -1) {
|
|
616
|
-
removeIndex(index);
|
|
617
|
-
}
|
|
618
|
-
return index;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
public String removeIndex(int index) {
|
|
623
|
-
if (index < 0 || index >= count) {
|
|
624
|
-
throw new ArrayIndexOutOfBoundsException(index);
|
|
625
|
-
}
|
|
626
|
-
String key = keys[index];
|
|
627
|
-
//System.out.println("index is " + which + " and " + keys[which]);
|
|
628
|
-
indices.remove(keys[index]);
|
|
629
|
-
for (int i = index; i < count-1; i++) {
|
|
630
|
-
keys[i] = keys[i+1];
|
|
631
|
-
values[i] = values[i+1];
|
|
632
|
-
indices.put(keys[i], i);
|
|
633
|
-
}
|
|
634
|
-
count--;
|
|
635
|
-
keys[count] = null;
|
|
636
|
-
values[count] = 0;
|
|
637
|
-
return key;
|
|
638
|
-
}
|
|
574
|
+
/**
|
|
575
|
+
* @webref doubledict:method
|
|
576
|
+
* @brief Remove a key/value pair
|
|
577
|
+
*/
|
|
578
|
+
public int remove(String key) {
|
|
579
|
+
int index = index(key);
|
|
580
|
+
if (index != -1) {
|
|
581
|
+
removeIndex(index);
|
|
582
|
+
}
|
|
583
|
+
return index;
|
|
584
|
+
}
|
|
639
585
|
|
|
586
|
+
public String removeIndex(int index) {
|
|
587
|
+
if (index < 0 || index >= count) {
|
|
588
|
+
throw new ArrayIndexOutOfBoundsException(index);
|
|
589
|
+
}
|
|
590
|
+
String key = keys[index];
|
|
591
|
+
//System.out.println("index is " + which + " and " + keys[which]);
|
|
592
|
+
indices.remove(keys[index]);
|
|
593
|
+
for (int i = index; i < count - 1; i++) {
|
|
594
|
+
keys[i] = keys[i + 1];
|
|
595
|
+
values[i] = values[i + 1];
|
|
596
|
+
indices.put(keys[i], i);
|
|
597
|
+
}
|
|
598
|
+
count--;
|
|
599
|
+
keys[count] = null;
|
|
600
|
+
values[count] = 0;
|
|
601
|
+
return key;
|
|
602
|
+
}
|
|
640
603
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
604
|
+
public void swap(int a, int b) {
|
|
605
|
+
String tkey = keys[a];
|
|
606
|
+
double tvalue = values[a];
|
|
607
|
+
keys[a] = keys[b];
|
|
608
|
+
values[a] = values[b];
|
|
609
|
+
keys[b] = tkey;
|
|
610
|
+
values[b] = tvalue;
|
|
648
611
|
|
|
649
612
|
// indices.put(keys[a], Integer.valueOf(a));
|
|
650
613
|
// indices.put(keys[b], Integer.valueOf(b));
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
|
656
|
-
* tie-breaker (only really possible with a key that has a case change).
|
|
657
|
-
*
|
|
658
|
-
* @webref doubledict:method
|
|
659
|
-
* @brief Sort the keys alphabetically
|
|
660
|
-
*/
|
|
661
|
-
public void sortKeys() {
|
|
662
|
-
sortImpl(true, false, true);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
/**
|
|
667
|
-
* @webref doubledict:method
|
|
668
|
-
* @brief Sort the keys alphabetically in reverse
|
|
669
|
-
*/
|
|
670
|
-
public void sortKeysReverse() {
|
|
671
|
-
sortImpl(true, true, true);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
/**
|
|
676
|
-
* Sort by values in descending order (largest value will be at [0]).
|
|
677
|
-
*
|
|
678
|
-
* @webref doubledict:method
|
|
679
|
-
* @brief Sort by values in ascending order
|
|
680
|
-
*/
|
|
681
|
-
public void sortValues() {
|
|
682
|
-
sortValues(true);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* Set true to ensure that the order returned is identical. Slightly
|
|
688
|
-
* slower because the tie-breaker for identical values compares the keys.
|
|
689
|
-
* @param stable
|
|
690
|
-
*/
|
|
691
|
-
public void sortValues(boolean stable) {
|
|
692
|
-
sortImpl(false, false, stable);
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* @webref doubledict:method
|
|
698
|
-
* @brief Sort by values in descending order
|
|
699
|
-
*/
|
|
700
|
-
public void sortValuesReverse() {
|
|
701
|
-
sortValuesReverse(true);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
public void sortValuesReverse(boolean stable) {
|
|
706
|
-
sortImpl(false, true, stable);
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
|
711
|
-
final boolean stable) {
|
|
712
|
-
Sort s = new Sort() {
|
|
713
|
-
@Override
|
|
714
|
-
public int size() {
|
|
715
|
-
if (useKeys) {
|
|
716
|
-
return count; // don't worry about NaN values
|
|
717
|
-
|
|
718
|
-
} else if (count == 0) { // skip the NaN check, it'll AIOOBE
|
|
719
|
-
return 0;
|
|
720
|
-
|
|
721
|
-
} else { // first move NaN values to the end of the list
|
|
722
|
-
int right = count - 1;
|
|
723
|
-
while (values[right] != values[right]) {
|
|
724
|
-
right--;
|
|
725
|
-
if (right == -1) {
|
|
726
|
-
return 0; // all values are NaN
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
for (int i = right; i >= 0; --i) {
|
|
730
|
-
if (Double.isNaN(values[i])) {
|
|
731
|
-
swap(i, right);
|
|
732
|
-
--right;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
return right + 1;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
@Override
|
|
740
|
-
public int compare(int a, int b) {
|
|
741
|
-
double diff = 0;
|
|
742
|
-
if (useKeys) {
|
|
743
|
-
diff = keys[a].compareToIgnoreCase(keys[b]);
|
|
744
|
-
if (diff == 0) {
|
|
745
|
-
diff = values[a] - values[b];
|
|
746
|
-
}
|
|
747
|
-
} else { // sort values
|
|
748
|
-
diff = values[a] - values[b];
|
|
749
|
-
if (diff == 0 && stable) {
|
|
750
|
-
diff = keys[a].compareToIgnoreCase(keys[b]);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
if (diff == 0) {
|
|
754
|
-
return 0;
|
|
755
|
-
} else if (reverse) {
|
|
756
|
-
return diff < 0 ? 1 : -1;
|
|
757
|
-
} else {
|
|
758
|
-
return diff < 0 ? -1 : 1;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
@Override
|
|
763
|
-
public void swap(int a, int b) {
|
|
764
|
-
DoubleDict.this.swap(a, b);
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
s.run();
|
|
614
|
+
}
|
|
768
615
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
616
|
+
/**
|
|
617
|
+
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
|
618
|
+
* tie-breaker (only really possible with a key that has a case change).
|
|
619
|
+
*
|
|
620
|
+
* @webref doubledict:method
|
|
621
|
+
* @brief Sort the keys alphabetically
|
|
622
|
+
*/
|
|
623
|
+
public void sortKeys() {
|
|
624
|
+
sortImpl(true, false, true);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* @webref doubledict:method
|
|
629
|
+
* @brief Sort the keys alphabetically in reverse
|
|
630
|
+
*/
|
|
631
|
+
public void sortKeysReverse() {
|
|
632
|
+
sortImpl(true, true, true);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Sort by values in descending order (largest value will be at [0]).
|
|
637
|
+
*
|
|
638
|
+
* @webref doubledict:method
|
|
639
|
+
* @brief Sort by values in ascending order
|
|
640
|
+
*/
|
|
641
|
+
public void sortValues() {
|
|
642
|
+
sortValues(true);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Set true to ensure that the order returned is identical. Slightly slower
|
|
647
|
+
* because the tie-breaker for identical values compares the keys.
|
|
648
|
+
*
|
|
649
|
+
* @param stable
|
|
650
|
+
*/
|
|
651
|
+
public void sortValues(boolean stable) {
|
|
652
|
+
sortImpl(false, false, stable);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* @webref doubledict:method
|
|
657
|
+
* @brief Sort by values in descending order
|
|
658
|
+
*/
|
|
659
|
+
public void sortValuesReverse() {
|
|
660
|
+
sortValuesReverse(true);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
public void sortValuesReverse(boolean stable) {
|
|
664
|
+
sortImpl(false, true, stable);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
|
668
|
+
final boolean stable) {
|
|
669
|
+
Sort s = new Sort() {
|
|
670
|
+
@Override
|
|
671
|
+
public int size() {
|
|
672
|
+
if (useKeys) {
|
|
673
|
+
return count; // don't worry about NaN values
|
|
674
|
+
|
|
675
|
+
} else if (count == 0) { // skip the NaN check, it'll AIOOBE
|
|
676
|
+
return 0;
|
|
677
|
+
|
|
678
|
+
} else { // first move NaN values to the end of the list
|
|
679
|
+
int right = count - 1;
|
|
680
|
+
while (values[right] != values[right]) {
|
|
681
|
+
right--;
|
|
682
|
+
if (right == -1) {
|
|
683
|
+
return 0; // all values are NaN
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
for (int i = right; i >= 0; --i) {
|
|
687
|
+
if (Double.isNaN(values[i])) {
|
|
688
|
+
swap(i, right);
|
|
689
|
+
--right;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return right + 1;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
772
695
|
|
|
696
|
+
@Override
|
|
697
|
+
public int compare(int a, int b) {
|
|
698
|
+
double diff = 0;
|
|
699
|
+
if (useKeys) {
|
|
700
|
+
diff = keys[a].compareToIgnoreCase(keys[b]);
|
|
701
|
+
if (diff == 0) {
|
|
702
|
+
diff = values[a] - values[b];
|
|
703
|
+
}
|
|
704
|
+
} else { // sort values
|
|
705
|
+
diff = values[a] - values[b];
|
|
706
|
+
if (diff == 0 && stable) {
|
|
707
|
+
diff = keys[a].compareToIgnoreCase(keys[b]);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (diff == 0) {
|
|
711
|
+
return 0;
|
|
712
|
+
} else if (reverse) {
|
|
713
|
+
return diff < 0 ? 1 : -1;
|
|
714
|
+
} else {
|
|
715
|
+
return diff < 0 ? -1 : 1;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
773
718
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
719
|
+
@Override
|
|
720
|
+
public void swap(int a, int b) {
|
|
721
|
+
DoubleDict.this.swap(a, b);
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
s.run();
|
|
725
|
+
|
|
726
|
+
// Set the indices after sort/swaps (performance fix 160411)
|
|
727
|
+
resetIndices();
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Sum all of the values in this dictionary, then return a new FloatDict of
|
|
732
|
+
* each key, divided by the total sum. The total for all values will be
|
|
733
|
+
* ~1.0.
|
|
734
|
+
*
|
|
735
|
+
* @return a FloatDict with the original keys, mapped to their pct of the
|
|
736
|
+
* total
|
|
737
|
+
*/
|
|
738
|
+
public DoubleDict getPercent() {
|
|
739
|
+
double sum = sum();
|
|
740
|
+
DoubleDict outgoing = new DoubleDict();
|
|
741
|
+
for (int i = 0; i < size(); i++) {
|
|
742
|
+
double percent = value(i) / sum;
|
|
743
|
+
outgoing.set(key(i), percent);
|
|
744
|
+
}
|
|
745
|
+
return outgoing;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* Returns a duplicate copy of this object.
|
|
750
|
+
*/
|
|
751
|
+
public DoubleDict copy() {
|
|
752
|
+
DoubleDict outgoing = new DoubleDict(count);
|
|
753
|
+
System.arraycopy(keys, 0, outgoing.keys, 0, count);
|
|
754
|
+
System.arraycopy(values, 0, outgoing.values, 0, count);
|
|
755
|
+
for (int i = 0; i < count; i++) {
|
|
756
|
+
outgoing.indices.put(keys[i], i);
|
|
757
|
+
}
|
|
758
|
+
outgoing.count = count;
|
|
759
|
+
return outgoing;
|
|
785
760
|
}
|
|
786
|
-
return outgoing;
|
|
787
|
-
}
|
|
788
761
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
System.arraycopy(keys, 0, outgoing.keys, 0, count);
|
|
794
|
-
System.arraycopy(values, 0, outgoing.values, 0, count);
|
|
795
|
-
for (int i = 0; i < count; i++) {
|
|
796
|
-
outgoing.indices.put(keys[i], i);
|
|
762
|
+
public void print() {
|
|
763
|
+
for (int i = 0; i < size(); i++) {
|
|
764
|
+
System.out.println(keys[i] + " = " + values[i]);
|
|
765
|
+
}
|
|
797
766
|
}
|
|
798
|
-
outgoing.count = count;
|
|
799
|
-
return outgoing;
|
|
800
|
-
}
|
|
801
767
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
768
|
+
/**
|
|
769
|
+
* Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
|
|
770
|
+
*/
|
|
771
|
+
public void save(File file) {
|
|
772
|
+
PrintWriter writer = PApplet.createWriter(file);
|
|
773
|
+
write(writer);
|
|
774
|
+
writer.close();
|
|
806
775
|
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
|
|
812
|
-
*/
|
|
813
|
-
public void save(File file) {
|
|
814
|
-
PrintWriter writer = PApplet.createWriter(file);
|
|
815
|
-
write(writer);
|
|
816
|
-
writer.close();
|
|
817
|
-
}
|
|
818
776
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
777
|
+
/**
|
|
778
|
+
* Write tab-delimited entries out to
|
|
779
|
+
*
|
|
780
|
+
* @param writer
|
|
781
|
+
*/
|
|
782
|
+
public void write(PrintWriter writer) {
|
|
783
|
+
for (int i = 0; i < count; i++) {
|
|
784
|
+
writer.println(keys[i] + "\t" + values[i]);
|
|
785
|
+
}
|
|
786
|
+
writer.flush();
|
|
827
787
|
}
|
|
828
|
-
writer.flush();
|
|
829
|
-
}
|
|
830
|
-
|
|
831
788
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
789
|
+
/**
|
|
790
|
+
* Return this dictionary as a String in JSON format.
|
|
791
|
+
*/
|
|
792
|
+
public String toJSON() {
|
|
793
|
+
StringList items = new StringList();
|
|
794
|
+
for (int i = 0; i < count; i++) {
|
|
795
|
+
items.append(JSONObject.quote(keys[i]) + ": " + values[i]);
|
|
796
|
+
}
|
|
797
|
+
return "{ " + items.join(", ") + " }";
|
|
839
798
|
}
|
|
840
|
-
return "{ " + items.join(", ") + " }";
|
|
841
|
-
}
|
|
842
|
-
|
|
843
799
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
800
|
+
@Override
|
|
801
|
+
public String toString() {
|
|
802
|
+
return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
|
|
803
|
+
}
|
|
848
804
|
}
|