propane 2.9.0-java → 2.9.1-java

Sign up to get free protection for your applications and to get access to all the features.
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
+ }