mdarray 0.4.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/LICENSE.txt +54 -0
  2. data/LICENSE.txt~ +32 -0
  3. data/README.md +21 -0
  4. data/Rakefile +40 -0
  5. data/lib/env.rb +11 -0
  6. data/lib/mdarray.rb +414 -0
  7. data/lib/mdarray/access.rb +237 -0
  8. data/lib/mdarray/counter.rb +779 -0
  9. data/lib/mdarray/creation.rb +413 -0
  10. data/lib/mdarray/fast_non_numerical.rb +102 -0
  11. data/lib/mdarray/function_creation.rb +100 -0
  12. data/lib/mdarray/function_map.rb +56 -0
  13. data/lib/mdarray/hierarchy.rb +177 -0
  14. data/lib/mdarray/operators.rb +220 -0
  15. data/lib/mdarray/printing.rb +275 -0
  16. data/lib/mdarray/proc_util.rb +159 -0
  17. data/lib/mdarray/ruby_functions.rb +78 -0
  18. data/lib/mdarray/ruby_generic_functions.rb +37 -0
  19. data/lib/mdarray/ruby_math.rb +57 -0
  20. data/lib/mdarray/ruby_numeric_functions.rb +187 -0
  21. data/lib/mdarray/ruby_operators.rb +201 -0
  22. data/lib/mdarray/ruby_stats.rb +149 -0
  23. data/lib/mdarray/slices.rb +185 -0
  24. data/lib/mdarray/statistics.rb +86 -0
  25. data/test/arithmetic_casting.rb +195 -0
  26. data/test/env.rb +50 -0
  27. data/test/test_access.rb +247 -0
  28. data/test/test_boolean.rb +67 -0
  29. data/test/test_comparison.rb +126 -0
  30. data/test/test_complete.rb +69 -0
  31. data/test/test_counter.rb +184 -0
  32. data/test/test_creation.rb +364 -0
  33. data/test/test_error.rb +53 -0
  34. data/test/test_lazy.rb +52 -0
  35. data/test/test_operator.rb +337 -0
  36. data/test/test_printing.rb +66 -0
  37. data/test/test_shape.rb +96 -0
  38. data/test/test_slices.rb +146 -0
  39. data/test/test_speed.rb +311 -0
  40. data/test/test_statistics.rb +45 -0
  41. data/test/test_trigonometry.rb +60 -0
  42. data/vendor/netcdfAll-4.3.16.jar +0 -0
  43. data/version.rb +2 -0
  44. metadata +197 -0
@@ -0,0 +1,96 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##########################################################################################
4
+ # Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
5
+ # and distribute this software and its documentation, without fee and without a signed
6
+ # licensing agreement, is hereby granted, provided that the above copyright notice, this
7
+ # paragraph and the following two paragraphs appear in all copies, modifications, and
8
+ # distributions.
9
+ #
10
+ # IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
11
+ # INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
12
+ # THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
13
+ # POSSIBILITY OF SUCH DAMAGE.
14
+ #
15
+ # RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
17
+ # SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
18
+ # RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
19
+ # OR MODIFICATIONS.
20
+ ##########################################################################################
21
+
22
+ require 'rubygems'
23
+ require "test/unit"
24
+ require 'shoulda'
25
+
26
+ require 'mdarray'
27
+
28
+ class MDArrayTest < Test::Unit::TestCase
29
+
30
+ context "Shape Manipulation" do
31
+
32
+ setup do
33
+
34
+ # create an int array with 15 elements and 1 dimension
35
+ # [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
36
+ @a = MDArray.arange(15)
37
+ assert_equal([15], @a.shape)
38
+ assert_equal(1, @a.ndim)
39
+ assert_equal(1, @a.rank)
40
+ assert_equal(15, @a.size)
41
+ assert_equal("int", @a.dtype)
42
+
43
+ end
44
+
45
+ #-------------------------------------------------------------------------------------
46
+ #
47
+ #-------------------------------------------------------------------------------------
48
+
49
+ should "allow getting a section from an array" do
50
+
51
+ b = @a.reshape([3, 5])
52
+ c = b.section([0, 0], [3, 1])
53
+ # c.print
54
+ c = b.section([0, 1], [3, 1])
55
+ # c.print
56
+ c = b.section([0, 2], [3, 1])
57
+ # c.print
58
+
59
+ end
60
+
61
+ #-------------------------------------------------------------------------------------
62
+ #
63
+ #-------------------------------------------------------------------------------------
64
+
65
+ should "allow array reshaping" do
66
+
67
+ # reshape the array in place
68
+ # [[0 1 2 3 4]
69
+ # [5 6 7 8 9]
70
+ # [10 11 12 13 14]]
71
+ @a.reshape!([3, 5])
72
+ assert_equal(2, @a.ndim)
73
+ assert_equal([3, 5], @a.shape)
74
+ assert_equal(0, @a[0, 0])
75
+ assert_equal(5, @a[1, 0])
76
+ assert_equal(12, @a[2, 2])
77
+ assert_raise ( RuntimeError ) { @a[3, 4] }
78
+
79
+ # reshape the array without copy
80
+ b = @a.reshape([15])
81
+ b[0] = 15
82
+ assert_equal(15, b[0])
83
+ assert_equal(15, @a[0, 0])
84
+
85
+ # reshape the array with copy
86
+ c = b.reshape([3, 5], true)
87
+ assert_equal(15, c[0, 0])
88
+ c[0, 1] = 20
89
+ assert_equal(20, c[0, 1])
90
+ assert_equal(1, b[1])
91
+
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,146 @@
1
+ require 'rubygems'
2
+ require "test/unit"
3
+ require 'shoulda'
4
+
5
+ require 'env'
6
+ require 'mdarray'
7
+
8
+ class MDArrayTest < Test::Unit::TestCase
9
+
10
+ context "Slice Tests" do
11
+
12
+ setup do
13
+
14
+ # creates an array from a function (actually a block). The name fromfunction
15
+ # is preserved to maintain API compatibility with NumPy (is it necessary?)
16
+
17
+ # simulating financial data: 1 year, 20 days, 10 securities, 7 values (open,
18
+ # close, high, low, volume, e1, e2)
19
+ @a = MDArray.fromfunction("double", [1, 20, 10, 7]) do |x, y, z, k|
20
+ 0.5 * x + y + 10 * (z + 1) + Math.sin(k + x)
21
+ end
22
+
23
+ @b = MDArray.int([2, 2])
24
+
25
+ end
26
+
27
+ #-------------------------------------------------------------------------------------
28
+ #
29
+ #-------------------------------------------------------------------------------------
30
+ =begin
31
+ should "get section with range" do
32
+
33
+ @b[/1:2:3/, /1:5/, /3:4/, 1]
34
+
35
+ end
36
+ =end
37
+
38
+ #-------------------------------------------------------------------------------------
39
+ #
40
+ #-------------------------------------------------------------------------------------
41
+
42
+ should "slice array along axes" do
43
+
44
+ @a.each_along_axes([3]) do |slice|
45
+ slice.print
46
+ print "\n"
47
+ end
48
+
49
+ # each_along_axes returns sub-arrays (sections) of the original array. Each section
50
+ # is taken by walking along the given axis and getting the all elements of the
51
+ # axis that were not given. For instance, array @a shape is [1, 20, 10, 7]. Slicing
52
+ # along axes [0, 2] will get the following sections of @a:
53
+ # section([0, 0, 0, 0], [1, 20, 1, 7]), section ([0, 0, 1, 0], [1, 20, 1, 7]),
54
+ # section([0, 0, 2, 0], [1, 20, 1, 7])...
55
+ # This is actually getting all values for every security for the 20 days.
56
+
57
+ @a.each_along_axes([0, 2]) do |slice|
58
+ slice.print
59
+ p slice.cum_op(MDArray.method(:add))
60
+ print "\n"
61
+ end
62
+
63
+ # Here we are getting 7 arrays for "open", "close", "High", "Low", etc. each
64
+ # containing all the 20 days for each security. So, the first array has 20 elements
65
+ # each with the "open" value for the first security. The second array returns
66
+ # has 20 elements, each with the "close" value for the first security.
67
+ @a.each_along_axes([2, 3]) do |slice|
68
+ slice.print
69
+ print "\n"
70
+ end
71
+
72
+ end
73
+
74
+ #-------------------------------------------------------------------------------------
75
+ #
76
+ #-------------------------------------------------------------------------------------
77
+
78
+ should "get array section" do
79
+
80
+ # 1 -> first year (only 1 year)
81
+ # 20 -> 20 days
82
+ # 10 -> number os secs
83
+ # 7 - > number of values
84
+
85
+ # b is a section of @a, starting a position (0) and taking only the first two
86
+ # elements of the first dimension. Getting all values, for all secs for the first
87
+ # 2 days
88
+ b = @a.section([0, 0, 0, 0], [1, 2, 10, 7])
89
+ assert_equal(true, b.section?)
90
+ assert_equal([1, 2, 10, 7], b.shape)
91
+ ind = b.get_index
92
+ ind.each do |elmt|
93
+ assert_equal(@a.get(elmt), b.get(elmt))
94
+ end
95
+
96
+ # getting "open" for the first 2 days of the 3rd sec
97
+ b = @a.section([0, 0, 3, 0], [1, 2, 1, 1])
98
+ assert_equal(40.00, b[0, 0, 0, 0])
99
+ assert_equal(41.00, b[0, 1, 0, 0])
100
+
101
+ # getting "close" (2nd) value of the 3rd sec for the second day with
102
+ # shape reduction. Note that in this case, with shape reduction, b is a
103
+ # number and not an array any more
104
+ b = @a.section([0, 1, 2, 1], [1, 1, 1, 1], true)
105
+ assert_equal(@a[0, 1, 2, 1], b)
106
+
107
+ # getting the "close" (2nd) value of the 3rd sec for the second day without
108
+ # shape reduction
109
+ b = @a.section([0, 1, 2, 1], [1, 1, 1, 1])
110
+ assert_equal([1, 1, 1, 1], b.shape)
111
+ assert_equal(@a[0, 1, 2, 1], b[0, 0, 0, 0])
112
+
113
+ # getting the "open" (1rst) value of the second secs for two days
114
+ b = @a.section([0, 0, 0, 0], [1, 2, 1, 1])
115
+ assert_equal([1, 2, 1, 1], b.shape)
116
+ assert_equal(@a[0, 0, 0, 0], b[0, 0, 0, 0])
117
+ assert_equal(@a[0, 1, 0, 0], b[0, 1, 0, 0])
118
+
119
+ # getting the "open" (1rst) value of the second secs for two days with rank
120
+ # reduction
121
+ b = @a.section([0, 0, 0, 0], [1, 2, 1, 1], true)
122
+ assert_equal([2], b.shape)
123
+ assert_equal(@a[0, 0, 0, 0], b[0])
124
+ assert_equal(@a[0, 1, 0, 0], b[1])
125
+
126
+ # getting the first security, all values
127
+ b = @a.section([0, 0, 0, 0], [1, 1, 1, 7])
128
+ # b.print
129
+
130
+ # getting the 2 security, all values
131
+ b = @a.section([0, 0, 1, 0], [1, 1, 1, 7])
132
+ # b.print
133
+
134
+ # getting the 1 day, all then secs
135
+ b = @a.section([0, 0, 0, 0], [1, 1, 10, 7])
136
+ # b.print
137
+
138
+ # getting the "open" (1st) value of all secs for the first day
139
+ b = @a.section([0, 0, 0, 0], [1, 1, 10, 1])
140
+ # b.print
141
+
142
+ end
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,311 @@
1
+ require 'rubygems'
2
+ require "test/unit"
3
+ require 'shoulda'
4
+ require 'jruby/profiler'
5
+
6
+ require 'env'
7
+ require 'benchmark'
8
+
9
+ require 'mdarray'
10
+
11
+ class MDArrayTest < Test::Unit::TestCase
12
+
13
+ context "Speed Tests" do
14
+
15
+ #=begin
16
+ setup do
17
+
18
+ p "starting speed test"
19
+
20
+ end
21
+
22
+ #-------------------------------------------------------------------------------------
23
+ #
24
+ #-------------------------------------------------------------------------------------
25
+
26
+ should "test addition" do
27
+
28
+ @a = MDArray.typed_arange("double", 10_000_000)
29
+ @b = MDArray.typed_arange("double", 10_000_000)
30
+
31
+ @c = MDArray.arange(10_000_000)
32
+ @d = MDArray.arange(10_000_000)
33
+
34
+ puts Benchmark.measure {
35
+ @a + @b
36
+ p @a[10]
37
+ }
38
+
39
+ puts Benchmark.measure {
40
+ @a - @b
41
+ }
42
+
43
+ puts Benchmark.measure {
44
+ @a + @b
45
+ p @a[10]
46
+ }
47
+
48
+ puts Benchmark.measure {
49
+ @a.plus(@b)
50
+ p @a[10]
51
+ }
52
+
53
+ puts Benchmark.measure {
54
+ @c.plus(@d)
55
+ }
56
+
57
+ puts Benchmark.measure {
58
+ @a.fast_add(@b)
59
+ p @a[10]
60
+ }
61
+
62
+ end
63
+
64
+
65
+ =begin
66
+ should "test inner product" do
67
+
68
+ @a = MDArray.typed_arange("double", 10_000_000)
69
+ @b = MDArray.typed_arange("double", 10_000_000)
70
+
71
+ MDArray.make_binary_op("inner_product", "reduce",
72
+ Proc.new { |sum, val1, val2| sum + (val1 * val2) },
73
+ nil,
74
+ Proc.new { 0 })
75
+
76
+ puts "measuring inner_product of two arrays of size: 10.000.000 in seconds"
77
+ @a.binary_operator = BinaryOperator
78
+ puts Benchmark.measure {
79
+ p @a.inner_product(@b)
80
+ # p (@a * @b).sum
81
+
82
+ }
83
+
84
+ end
85
+ =end
86
+
87
+ #-------------------------------------------------------------------------------------
88
+ #
89
+ #-------------------------------------------------------------------------------------
90
+
91
+ =begin
92
+ should "execute fromfunction" do
93
+
94
+ # creates an array from a function (actually a block). The name fromfunction
95
+ # is preserved to maintain API compatibility with NumPy (is it necessary?)
96
+ # requires 105.981s to run the following block
97
+ # requires 92.343s to run the following block
98
+ # requires 34.096s to run the following block in Java 7 with invokedynamics
99
+ # requires 5s to run with loop transfered to java
100
+
101
+ puts "measuring fromfunction of size: #{7*500*20*320} in seconds"
102
+ puts Benchmark.measure {
103
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
104
+ # counter[0] + counter[1] + counter[2] + counter[3]
105
+ x + y + z + k
106
+ end
107
+ }
108
+
109
+ end
110
+ =end
111
+
112
+ =begin
113
+ @a = MDArray.double([7, 500, 20, 320])
114
+ # @a.unary_operator = UnaryOperator
115
+ @a.fill do |x, y, z, k|
116
+ # counter[0] + counter[1] + counter[2] + counter[3]
117
+ x + y + z + k
118
+ end
119
+
120
+ assert_equal(0, @a[0, 0, 0, 0])
121
+ assert_equal(50, @a[5, 10, 15, 20])
122
+
123
+ end
124
+ =end
125
+
126
+
127
+ =begin
128
+ should "do binary operations in place fast" do
129
+
130
+ # @a.fromfunction = 5s (fast), @b.fromfunction = 5s
131
+ # inplace add requires @a and @b loops each taking a little over 6s.
132
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
133
+ # @a = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
134
+ (x + y + z + k) * -1.2345
135
+ end
136
+
137
+ @b = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
138
+ # @b = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
139
+ (x + y + z + k) * -1.2345
140
+ end
141
+
142
+ @a.add!(@b)
143
+ # b = 100 + @a
144
+ # @a.print
145
+ # c.print
146
+
147
+ end
148
+
149
+ =end
150
+
151
+ #-------------------------------------------------------------------------------------
152
+ #
153
+ #-------------------------------------------------------------------------------------
154
+
155
+ =begin
156
+ should "iterate fast" do
157
+ @a = MDArray.double([7, 500, 20, 320])
158
+ @a.set_all do |counter|
159
+ counter[0] + counter[1] + counter[2] + counter[3]
160
+ end
161
+
162
+ p @a[0, 0, 0, 0]
163
+ p @a[1, 120, 10, 300]
164
+
165
+ end
166
+
167
+ =end
168
+
169
+ =begin
170
+
171
+ # executes in 8.37s
172
+ should "iterate fast" do
173
+
174
+ profile_data = JRuby::Profiler.profile do
175
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |counter|
176
+ counter[0] + counter[1] + counter[2] + counter[3]
177
+ # x + y + z + k
178
+ end
179
+ end
180
+
181
+ profile_printer = JRuby::Profiler::FlatProfilePrinter.new(profile_data)
182
+ profile_printer.printProfile(STDOUT)
183
+
184
+ p @a[0, 0, 0, 0]
185
+ p @a[1, 120, 10, 300]
186
+
187
+ end
188
+
189
+ =end
190
+
191
+ =begin
192
+
193
+ should "iterate fast" do
194
+
195
+ @a = MDArray.fromfunction("int", [7, 500, 20, 320]) do |x, y, z, k|
196
+ x + y + z + k
197
+ end
198
+
199
+ p @a[0, 0, 0, 0]
200
+ p @a[1, 120, 10, 300]
201
+
202
+
203
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
204
+ x + y + z + k
205
+ end
206
+
207
+ p @a[0, 0, 0, 0]
208
+ p @a[1, 120, 10, 300]
209
+
210
+ end
211
+
212
+ =end
213
+
214
+ =begin
215
+ should "do unary operations fast" do
216
+
217
+ # first test of unary operation 15.258s. fromfunction takes 5.097s, so simple
218
+ # unary operation is taking 10s, should not take more than fromfunction!
219
+ # second test of unary operation 10.187s. fromfunction takes 5.097s, so simple
220
+ # unary operation is taking 5s. OK.
221
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
222
+ # @a = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
223
+ (x + y + z + k) * -1.2345
224
+ end
225
+
226
+ b = @a.abs
227
+ # @a.print
228
+ # b.print
229
+
230
+ end
231
+ =end
232
+
233
+ =begin
234
+ should "do binary operations fast" do
235
+
236
+ # first test of unary operation 15.258s. fromfunction takes 5.097s, so simple
237
+ # unary operation is taking 10s, should not take more than fromfunction!
238
+ # second test of unary operation 10.187s. fromfunction takes 5.097s, so simple
239
+ # unary operation is taking 5s. OK.
240
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
241
+ # @a = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
242
+ (x + y + z + k) * -1.2345
243
+ end
244
+
245
+ @b = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
246
+ # @b = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
247
+ (x + y + z + k) * -1.2345
248
+ end
249
+
250
+ c = @a + @b
251
+ # b = 100 + @a
252
+ # @a.print
253
+ # c.print
254
+
255
+ end
256
+ =end
257
+
258
+ =begin
259
+ should "do binary operations fast with arrays of different types" do
260
+
261
+ # first test of unary operation 15.258s. fromfunction takes 5.097s, so simple
262
+ # unary operation is taking 10s, should not take more than fromfunction!
263
+ # second test of unary operation 10.187s. fromfunction takes 5.097s, so simple
264
+ # unary operation is taking 5s. OK.
265
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
266
+ # @a = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
267
+ (x + y + z + k) * -1.2345
268
+ end
269
+
270
+ @b = MDArray.fromfunction("float", [7, 500, 20, 320]) do |x, y, z, k|
271
+ # @b = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
272
+ (x + y + z + k) * -1.2345
273
+ end
274
+
275
+ c = @a + @b
276
+ # b = 100 + @a
277
+ # @a.print
278
+ # c.print
279
+
280
+ end
281
+ =end
282
+
283
+ =begin
284
+ should "do comparison operations fast" do
285
+
286
+ # first test of unary operation 15.258s. fromfunction takes 5.097s, so simple
287
+ # unary operation is taking 10s, should not take more than fromfunction!
288
+ # second test of unary operation 10.187s. fromfunction takes 5.097s, so simple
289
+ # unary operation is taking 5s. OK.
290
+ @a = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
291
+ # @a = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
292
+ (x + y + z + k) * -1.2345
293
+ end
294
+
295
+ @b = MDArray.fromfunction("double", [7, 500, 20, 320]) do |x, y, z, k|
296
+ # @b = MDArray.fromfunction("double", [2, 2, 2, 2]) do |x, y, z, k|
297
+ (x + y + z + k) * -1.2345
298
+ end
299
+
300
+ c = @a > @b
301
+ # b = 100 + @a
302
+ # @a.print
303
+ # c.print
304
+
305
+ end
306
+ =end
307
+
308
+ end
309
+
310
+ end
311
+