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