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