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.
- data/LICENSE.txt +54 -0
- data/LICENSE.txt~ +32 -0
- data/README.md +21 -0
- data/Rakefile +40 -0
- data/lib/env.rb +11 -0
- data/lib/mdarray.rb +414 -0
- data/lib/mdarray/access.rb +237 -0
- data/lib/mdarray/counter.rb +779 -0
- data/lib/mdarray/creation.rb +413 -0
- data/lib/mdarray/fast_non_numerical.rb +102 -0
- data/lib/mdarray/function_creation.rb +100 -0
- data/lib/mdarray/function_map.rb +56 -0
- data/lib/mdarray/hierarchy.rb +177 -0
- data/lib/mdarray/operators.rb +220 -0
- data/lib/mdarray/printing.rb +275 -0
- data/lib/mdarray/proc_util.rb +159 -0
- data/lib/mdarray/ruby_functions.rb +78 -0
- data/lib/mdarray/ruby_generic_functions.rb +37 -0
- data/lib/mdarray/ruby_math.rb +57 -0
- data/lib/mdarray/ruby_numeric_functions.rb +187 -0
- data/lib/mdarray/ruby_operators.rb +201 -0
- data/lib/mdarray/ruby_stats.rb +149 -0
- data/lib/mdarray/slices.rb +185 -0
- data/lib/mdarray/statistics.rb +86 -0
- data/test/arithmetic_casting.rb +195 -0
- data/test/env.rb +50 -0
- data/test/test_access.rb +247 -0
- data/test/test_boolean.rb +67 -0
- data/test/test_comparison.rb +126 -0
- data/test/test_complete.rb +69 -0
- data/test/test_counter.rb +184 -0
- data/test/test_creation.rb +364 -0
- data/test/test_error.rb +53 -0
- data/test/test_lazy.rb +52 -0
- data/test/test_operator.rb +337 -0
- data/test/test_printing.rb +66 -0
- data/test/test_shape.rb +96 -0
- data/test/test_slices.rb +146 -0
- data/test/test_speed.rb +311 -0
- data/test/test_statistics.rb +45 -0
- data/test/test_trigonometry.rb +60 -0
- data/vendor/netcdfAll-4.3.16.jar +0 -0
- data/version.rb +2 -0
- metadata +197 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
##########################################################################################
|
2
|
+
#
|
3
|
+
##########################################################################################
|
4
|
+
|
5
|
+
module RubyStats
|
6
|
+
extend FunctionCreation
|
7
|
+
extend RubyFunctions
|
8
|
+
|
9
|
+
#======================================================================================
|
10
|
+
# Statistics
|
11
|
+
#======================================================================================
|
12
|
+
|
13
|
+
=begin
|
14
|
+
func = ["ruby_sum", "RubyFunction", Proc.new { |sum, val| sum + val }, "*", "*", "void"]
|
15
|
+
make_unary_op("sum", "reduce", func, nil, Proc.new { 0 })
|
16
|
+
|
17
|
+
#---------------------------------------------------------------------------------------
|
18
|
+
# calculates the minimum
|
19
|
+
#---------------------------------------------------------------------------------------
|
20
|
+
|
21
|
+
pre_calc = Proc.new { |arr1, *args| arr1[0] }
|
22
|
+
|
23
|
+
calc = Proc.new { |min, val| min = (min < val)? min : val }
|
24
|
+
|
25
|
+
make_unary_op("min", :reduce, calc, nil, pre_calc)
|
26
|
+
|
27
|
+
#---------------------------------------------------------------------------------------
|
28
|
+
# calculates the maximum
|
29
|
+
#---------------------------------------------------------------------------------------
|
30
|
+
|
31
|
+
pre_calc = Proc.new { |arr1, *args| arr1[0] }
|
32
|
+
|
33
|
+
calc = Proc.new { |max, val| max = (max > val)? max : val }
|
34
|
+
|
35
|
+
make_unary_op("max", :reduce, calc, nil, pre_calc)
|
36
|
+
|
37
|
+
#---------------------------------------------------------------------------------------
|
38
|
+
# calculates the mean
|
39
|
+
#---------------------------------------------------------------------------------------
|
40
|
+
|
41
|
+
pre_calc = Proc.new { 0 }
|
42
|
+
|
43
|
+
calc = Proc.new { |start, val| start += val }
|
44
|
+
|
45
|
+
post_calc = Proc.new do |result, *args|
|
46
|
+
arr = args.shift
|
47
|
+
if (arr.size == 0)
|
48
|
+
next nil
|
49
|
+
end
|
50
|
+
result / arr.size
|
51
|
+
end
|
52
|
+
|
53
|
+
make_unary_op("mean", :reduce, calc, nil, pre_calc, post_calc)
|
54
|
+
|
55
|
+
#---------------------------------------------------------------------------------------
|
56
|
+
# calculates the weighted mean
|
57
|
+
#---------------------------------------------------------------------------------------
|
58
|
+
|
59
|
+
pre_calc = Proc.new { [0, 0] }
|
60
|
+
|
61
|
+
calc = Proc.new do |result, val, weight|
|
62
|
+
result[0] += (val * weight)
|
63
|
+
result[1] += weight
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
post_calc = Proc.new do |result, *args|
|
68
|
+
arr = args.shift
|
69
|
+
if (arr.size == 0)
|
70
|
+
next [nil, nil]
|
71
|
+
end
|
72
|
+
[result[0] / result[1], arr.size]
|
73
|
+
end
|
74
|
+
|
75
|
+
make_binary_op("weighted_mean", :reduce, calc, nil, pre_calc, post_calc)
|
76
|
+
|
77
|
+
#---------------------------------------------------------------------------------------
|
78
|
+
# Expectation value
|
79
|
+
#---------------------------------------------------------------------------------------
|
80
|
+
|
81
|
+
pre_calc = Proc.new do |*args|
|
82
|
+
arr = args.shift
|
83
|
+
mean = arr.mean
|
84
|
+
method = MDArray.method(:square).to_proc * MDArray.method(:sub).to_proc.bind2nd(mean)
|
85
|
+
[0, 0, method]
|
86
|
+
end
|
87
|
+
|
88
|
+
calc = Proc.new do |result, val, method|
|
89
|
+
result[0] += (method.call(val) * weight)
|
90
|
+
result[1] += weight
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
post_calc = Proc.new do |result, *args|
|
95
|
+
arr = args.shift
|
96
|
+
if (arr.size == 0)
|
97
|
+
next nil
|
98
|
+
end
|
99
|
+
result / arr.size
|
100
|
+
end
|
101
|
+
=end
|
102
|
+
=begin
|
103
|
+
|
104
|
+
def mean
|
105
|
+
expectation_value(Proc.identity, Proc.everywhere)[0]
|
106
|
+
end
|
107
|
+
|
108
|
+
#---------------------------------------------------------------------------------------
|
109
|
+
#
|
110
|
+
#---------------------------------------------------------------------------------------
|
111
|
+
|
112
|
+
def variance
|
113
|
+
|
114
|
+
s2 = expectation_value(MDArray.method(:square).to_proc *
|
115
|
+
MDArray.method(:sub).to_proc.bind2nd(mean),
|
116
|
+
Proc.everywhere)[0]
|
117
|
+
return s2*size/(size-1)
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
#---------------------------------------------------------------------------------------
|
122
|
+
#
|
123
|
+
#---------------------------------------------------------------------------------------
|
124
|
+
|
125
|
+
def expectation_value(method, in_range, weight = nil)
|
126
|
+
|
127
|
+
num = 0
|
128
|
+
den = 0
|
129
|
+
n = 0
|
130
|
+
each do |elmt|
|
131
|
+
if (in_range.call(elmt))
|
132
|
+
num += method.call(elmt)
|
133
|
+
den += 1
|
134
|
+
n += 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
if (n == 0)
|
138
|
+
return [nil, nil]
|
139
|
+
else
|
140
|
+
return [num / den, n]
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
# calculates the mean
|
146
|
+
|
147
|
+
=end
|
148
|
+
|
149
|
+
end # RubyStats
|
@@ -0,0 +1,185 @@
|
|
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
|
+
class MDArray
|
23
|
+
|
24
|
+
#------------------------------------------------------------------------------------
|
25
|
+
# Create a copy of this Array, copying the data so that physical order is the same as
|
26
|
+
# logical order
|
27
|
+
#------------------------------------------------------------------------------------
|
28
|
+
|
29
|
+
def copy
|
30
|
+
MDArray.new(@nc_array.copy())
|
31
|
+
end
|
32
|
+
|
33
|
+
#------------------------------------------------------------------------------------
|
34
|
+
#
|
35
|
+
#------------------------------------------------------------------------------------
|
36
|
+
|
37
|
+
def reshape(shape, copy = false)
|
38
|
+
|
39
|
+
new_shape = shape.to_java :int
|
40
|
+
|
41
|
+
if (copy)
|
42
|
+
nc_array = @nc_array.reshape(new_shape)
|
43
|
+
else
|
44
|
+
nc_array = @nc_array.reshapeNoCopy(new_shape)
|
45
|
+
end
|
46
|
+
|
47
|
+
MDArray.new(@type, nc_array)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
#------------------------------------------------------------------------------------
|
52
|
+
#
|
53
|
+
#------------------------------------------------------------------------------------
|
54
|
+
|
55
|
+
def reshape!(shape)
|
56
|
+
new_shape = shape.to_java :int
|
57
|
+
@nc_array = @nc_array.reshapeNoCopy(new_shape)
|
58
|
+
# when we reshape an array we need to re-initialize its index and local_iterator
|
59
|
+
@local_index = Counter.new(self)
|
60
|
+
@local_iterator = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
#------------------------------------------------------------------------------------
|
64
|
+
#
|
65
|
+
#------------------------------------------------------------------------------------
|
66
|
+
|
67
|
+
def reduce(dim = nil)
|
68
|
+
|
69
|
+
if (dim)
|
70
|
+
nc_array = @nc_array.reduce(dim.to_java :int)
|
71
|
+
else
|
72
|
+
nc_array = @nc_array.reduce
|
73
|
+
end
|
74
|
+
|
75
|
+
shape = MDArray.get_shape(nc_array)
|
76
|
+
MDArray.new(@type, nc_array)
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
#---------------------------------------------------------------------------------------
|
81
|
+
# Create a new Array using same backing store as this Array, by permuting the indices.
|
82
|
+
# Parameters:
|
83
|
+
# <tt>indices</tt> the old index dims[k] becomes the new kth index.
|
84
|
+
# Returns:
|
85
|
+
# the new Array
|
86
|
+
# Throws:
|
87
|
+
# IllegalArgumentException: - wrong rank or dim[k] not valid
|
88
|
+
#---------------------------------------------------------------------------------------
|
89
|
+
|
90
|
+
def permute(indices)
|
91
|
+
|
92
|
+
ind = indices.to_java :int
|
93
|
+
|
94
|
+
begin
|
95
|
+
perm = @nc_array.permute(ind)
|
96
|
+
rescue # should catch IllegalArgumentException
|
97
|
+
raise "Illegal argument"
|
98
|
+
end
|
99
|
+
|
100
|
+
MDArray.new(@type, perm)
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
#------------------------------------------------------------------------------------
|
105
|
+
# Create a new Array as a subsection of this Array, without rank reduction. No data
|
106
|
+
# is moved, so the new Array references the same backing store as the original.
|
107
|
+
# Parameters:
|
108
|
+
# origin - int array specifying the starting index. Must be same rank as original Array.
|
109
|
+
# shape - int array specifying the extents in each dimension. This becomes the shape
|
110
|
+
# of the returned Array. Must be same rank as original Array.
|
111
|
+
# stride - int array specifying the strides in each dimension. If null, assume all ones.
|
112
|
+
# Returns:
|
113
|
+
# the new Array
|
114
|
+
# Throws:
|
115
|
+
# InvalidRangeException - if ranges is invalid
|
116
|
+
#------------------------------------------------------------------------------------
|
117
|
+
|
118
|
+
def section(origin, shape, reduce = false)
|
119
|
+
|
120
|
+
jorigin = origin.to_java :int
|
121
|
+
jshape = shape.to_java :int
|
122
|
+
|
123
|
+
if (reduce)
|
124
|
+
arr = @nc_array.section(jorigin, jshape)
|
125
|
+
else
|
126
|
+
arr = @nc_array.sectionNoReduce(jorigin, jshape, nil)
|
127
|
+
end
|
128
|
+
|
129
|
+
# this is an array section, set it to true
|
130
|
+
if (arr.rank == 0)
|
131
|
+
return arr.get()
|
132
|
+
end
|
133
|
+
|
134
|
+
section = MDArray.new(@type, arr, true)
|
135
|
+
copy_print_parameters(section)
|
136
|
+
return section
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
#------------------------------------------------------------------------------------
|
141
|
+
#
|
142
|
+
#------------------------------------------------------------------------------------
|
143
|
+
|
144
|
+
def section_with_stride(origin, shape, stride, reduce = false)
|
145
|
+
|
146
|
+
jorigin = origin.to_java :int
|
147
|
+
jshape = shape.to_java :int
|
148
|
+
jstride = stride.to_java :int
|
149
|
+
|
150
|
+
if (reduce)
|
151
|
+
arr = @nc_array.section(jorigin, jshape, jstride)
|
152
|
+
else
|
153
|
+
arr = @nc_array.sectionNoReduce(jorigin, jshape, jstride)
|
154
|
+
end
|
155
|
+
|
156
|
+
# this is an array section, set it to true
|
157
|
+
section = MDArray.new(@type, arr, true)
|
158
|
+
copy_print_parameters(section)
|
159
|
+
return section
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
#------------------------------------------------------------------------------------
|
164
|
+
#
|
165
|
+
#------------------------------------------------------------------------------------
|
166
|
+
|
167
|
+
def section?
|
168
|
+
@section
|
169
|
+
end
|
170
|
+
|
171
|
+
#------------------------------------------------------------------------------------
|
172
|
+
#
|
173
|
+
#------------------------------------------------------------------------------------
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
#------------------------------------------------------------------------------------
|
178
|
+
#
|
179
|
+
#------------------------------------------------------------------------------------
|
180
|
+
|
181
|
+
def section=(value)
|
182
|
+
@section = value
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -0,0 +1,86 @@
|
|
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
|
+
class MDArray
|
23
|
+
|
24
|
+
#---------------------------------------------------------------------------------------
|
25
|
+
#
|
26
|
+
#---------------------------------------------------------------------------------------
|
27
|
+
|
28
|
+
def stdev
|
29
|
+
return Math.sqrt(variance)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias standard_deviation :stdev
|
33
|
+
|
34
|
+
#---------------------------------------------------------------------------------------
|
35
|
+
#
|
36
|
+
#---------------------------------------------------------------------------------------
|
37
|
+
|
38
|
+
def error_estimate
|
39
|
+
Math.sqrt(variance/size)
|
40
|
+
end
|
41
|
+
|
42
|
+
#---------------------------------------------------------------------------------------
|
43
|
+
#
|
44
|
+
#---------------------------------------------------------------------------------------
|
45
|
+
|
46
|
+
def skewness
|
47
|
+
|
48
|
+
n = size
|
49
|
+
|
50
|
+
if (n <= 2)
|
51
|
+
raise "Cannot calculate skewness on array with less than 3 elements"
|
52
|
+
end
|
53
|
+
|
54
|
+
x = expectation_value(MDArray.method(:cube).to_proc *
|
55
|
+
MDArray.method(:sub).to_proc.bind2nd(mean),
|
56
|
+
Proc.everywhere)[0]
|
57
|
+
sigma = stdev
|
58
|
+
|
59
|
+
return (x/(sigma*sigma*sigma)) * (n/(n-1)) * (n/(n-2))
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
#---------------------------------------------------------------------------------------
|
64
|
+
#
|
65
|
+
#---------------------------------------------------------------------------------------
|
66
|
+
|
67
|
+
def kurtosis
|
68
|
+
|
69
|
+
n = size
|
70
|
+
|
71
|
+
if (n <= 3)
|
72
|
+
raise "Cannot calculate kurtosis on array with less than 4 elements"
|
73
|
+
end
|
74
|
+
|
75
|
+
x = expectation_value(MDArray.method(:fourth).to_proc *
|
76
|
+
MDArray.method(:sub).to_proc.bind2nd(mean),
|
77
|
+
Proc.everywhere)[0]
|
78
|
+
|
79
|
+
sigma2 = variance
|
80
|
+
c1 = (n/(n-1)) * (n/(n-2)) * ((n+1)/(n-3))
|
81
|
+
c2 = 3 * ((n-1)/(n-2)) * ((n-1)/(n-3))
|
82
|
+
return c1 * (x/(sigma2*sigma2)) - c2
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,195 @@
|
|
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
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require "test/unit"
|
25
|
+
require 'shoulda'
|
26
|
+
|
27
|
+
require 'mdarray'
|
28
|
+
|
29
|
+
class MDArrayTest < Test::Unit::TestCase
|
30
|
+
|
31
|
+
context "Arithmetic Tests" do
|
32
|
+
|
33
|
+
setup do
|
34
|
+
|
35
|
+
# create a = [20 30 40 50]
|
36
|
+
@a = MDArray.arange(20, 60, 10)
|
37
|
+
# create b = [0 1 2 3]
|
38
|
+
@b = MDArray.arange(4)
|
39
|
+
# create c = [1.87 5.34 7.18 8.84]
|
40
|
+
@c = MDArray.double([4], [1.87, 5.34, 7.18, 8.84])
|
41
|
+
# create d = [[1 2] [3 4]]
|
42
|
+
@d = MDArray.int([2, 2], [1, 2, 3, 4])
|
43
|
+
# creates an array from a function (actually a block). The name fromfunction
|
44
|
+
# is preserved to maintain API compatibility with NumPy (is it necessary?)
|
45
|
+
@e = MDArray.fromfunction("double", [4, 5, 6]) do |x, y, z|
|
46
|
+
3.21 * (x + y + z)
|
47
|
+
end
|
48
|
+
@f = MDArray.fromfunction("double", [4, 5, 6]) do |x, y, z|
|
49
|
+
9.57 * x + y + z
|
50
|
+
end
|
51
|
+
@bool = MDArray.boolean([4], [true, true, false, false])
|
52
|
+
|
53
|
+
end # setup
|
54
|
+
|
55
|
+
#-------------------------------------------------------------------------------------
|
56
|
+
#
|
57
|
+
#-------------------------------------------------------------------------------------
|
58
|
+
|
59
|
+
should "do down-casting when in-place operation" do
|
60
|
+
|
61
|
+
# in place operation between an "int" array and a "double" array will keep the
|
62
|
+
# type of a to "int", no up-casting. Values will be truncated
|
63
|
+
@a.add! @c
|
64
|
+
assert_equal(21, @a[0])
|
65
|
+
assert_equal(@a.type, "int")
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
#-------------------------------------------------------------------------------------
|
70
|
+
#
|
71
|
+
#-------------------------------------------------------------------------------------
|
72
|
+
|
73
|
+
should "do up-casting" do
|
74
|
+
|
75
|
+
# when doing operations between two arrays, the resulting array will have the
|
76
|
+
# highest casting value. result will be of type double
|
77
|
+
result = @a + @c
|
78
|
+
assert_equal(21.87, result[0])
|
79
|
+
assert_equal("double", result.dtype)
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
#-------------------------------------------------------------------------------------
|
84
|
+
#
|
85
|
+
#-------------------------------------------------------------------------------------
|
86
|
+
|
87
|
+
should "do up-casting with basic types" do
|
88
|
+
|
89
|
+
result = 1.57 * @a
|
90
|
+
# since @a is an int, this should be converted to double, as there is no "float"
|
91
|
+
# type in ruby
|
92
|
+
assert_equal("double", result.dtype)
|
93
|
+
assert_equal(result.to_string, "31.400000000000002 47.1 62.800000000000004 78.5 ")
|
94
|
+
|
95
|
+
result = @c * 1.57
|
96
|
+
assert_equal("double", result.dtype)
|
97
|
+
|
98
|
+
# array @a will be cast to "double"
|
99
|
+
result = @a ** 2.5
|
100
|
+
assert_equal("double", result.dtype)
|
101
|
+
|
102
|
+
# array @c will keep its double type
|
103
|
+
result = @c ** 2.5
|
104
|
+
assert_equal("double", result.dtype)
|
105
|
+
|
106
|
+
# force result to be of given type. Cannot use binary operators, need to use the
|
107
|
+
# corresponding function. Upcast int @a to float
|
108
|
+
result = @a.mul(1.57, "float")
|
109
|
+
assert_equal("float", result.dtype)
|
110
|
+
|
111
|
+
result = @a.div(2, "short")
|
112
|
+
assert_equal("short", result.dtype)
|
113
|
+
|
114
|
+
# force result to be of given type. Cannot use binary operators, need to use the
|
115
|
+
# corresponding function.
|
116
|
+
result = @e.mul(1.57, "float")
|
117
|
+
assert_equal("float", result.dtype)
|
118
|
+
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
#-------------------------------------------------------------------------------------
|
123
|
+
#
|
124
|
+
#-------------------------------------------------------------------------------------
|
125
|
+
|
126
|
+
should "allow forced casting" do
|
127
|
+
|
128
|
+
# force result to be of type float, by normal rules it would be of type double
|
129
|
+
result = @a.mul(1.57, "float")
|
130
|
+
assert_equal("float", result.dtype)
|
131
|
+
# final result depends on when casting occurs. It is possible that the operation
|
132
|
+
# is done in double and cast when storing on the float array, or the operation
|
133
|
+
# can be done in float already. Ruby operations perform the former, i.e.,
|
134
|
+
# double operation and cast to float.
|
135
|
+
if (MDArray.binary_operator == RubyBinaryOperator)
|
136
|
+
assert_equal("31.4 47.1 62.8 78.5 ", result.to_string)
|
137
|
+
else
|
138
|
+
assert_equal("31.400002 47.100002 62.800003 78.5 ", result.to_string)
|
139
|
+
end
|
140
|
+
|
141
|
+
# force result to be ot type "int"
|
142
|
+
# @a.binary_operator = BinaryOperator
|
143
|
+
result = @a.mul(3.43, "int")
|
144
|
+
assert_equal(result.type, "int")
|
145
|
+
if (MDArray.binary_operator == RubyBinaryOperator)
|
146
|
+
# When BinaryOperator with force casting, values are operated first and then
|
147
|
+
# casted. So, in the example above we have 20 * 3.43 = 68,6 and then the value
|
148
|
+
# is casted to int for a result of 68
|
149
|
+
assert_equal(68, result[0])
|
150
|
+
else
|
151
|
+
# When we cast earlier values are first cast to the the selected type
|
152
|
+
# and then operated upon. So, in the example we have 20 * 3.43, which becomes
|
153
|
+
# 20 * 3 = 60
|
154
|
+
assert_equal(60, result[0])
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
#-------------------------------------------------------------------------------------
|
160
|
+
#
|
161
|
+
#-------------------------------------------------------------------------------------
|
162
|
+
|
163
|
+
should "allow mixing types" do
|
164
|
+
|
165
|
+
# adding double to number
|
166
|
+
res = @c + 10.5
|
167
|
+
assert_equal(res.to_string, "12.370000000000001 15.84 17.68 19.34 ")
|
168
|
+
# adding two double arrays
|
169
|
+
res = @e + @f
|
170
|
+
|
171
|
+
# adding a double to an int, should cast to double
|
172
|
+
res = @c + @a
|
173
|
+
assert_equal("21.87 35.34 47.18 58.84 ", res.to_string)
|
174
|
+
# adding an int to a double, should cast to double
|
175
|
+
res = @a + @c
|
176
|
+
assert_equal("21.87 35.34 47.18 58.84 ", res.to_string)
|
177
|
+
# adding an int array to a (ruby) float/double number, should cast to double
|
178
|
+
res = @a + 10.55
|
179
|
+
assert_equal("30.55 40.55 50.55 60.55 ", res.to_string)
|
180
|
+
# adding two ints
|
181
|
+
res = @a + @b
|
182
|
+
assert_equal(res.to_string, "20 31 42 53 ")
|
183
|
+
# unary operation on arrays
|
184
|
+
res = @c.floor
|
185
|
+
assert_equal(res.to_string, "1.0 5.0 7.0 8.0 ")
|
186
|
+
# Can also operate with the number first. Still doing elementwise operation
|
187
|
+
c = 10 / @c
|
188
|
+
assert_equal("5.347593582887701 1.8726591760299627 1.392757660167131 1.1312217194570136 ",
|
189
|
+
c.to_string)
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|