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