xnd 0.2.0dev3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +42 -0
  3. data/Gemfile +3 -0
  4. data/History.md +0 -0
  5. data/README.md +7 -0
  6. data/Rakefile +135 -0
  7. data/ext/ruby_xnd/extconf.rb +70 -0
  8. data/ext/ruby_xnd/float_pack_unpack.c +277 -0
  9. data/ext/ruby_xnd/float_pack_unpack.h +39 -0
  10. data/ext/ruby_xnd/gc_guard.c +36 -0
  11. data/ext/ruby_xnd/gc_guard.h +12 -0
  12. data/ext/ruby_xnd/include/xnd.h +449 -0
  13. data/ext/ruby_xnd/lib/libxnd.a +0 -0
  14. data/ext/ruby_xnd/lib/libxnd.so +1 -0
  15. data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
  16. data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
  17. data/ext/ruby_xnd/memory_block_object.c +32 -0
  18. data/ext/ruby_xnd/memory_block_object.h +33 -0
  19. data/ext/ruby_xnd/ruby_xnd.c +1953 -0
  20. data/ext/ruby_xnd/ruby_xnd.h +61 -0
  21. data/ext/ruby_xnd/ruby_xnd_internal.h +85 -0
  22. data/ext/ruby_xnd/util.h +170 -0
  23. data/ext/ruby_xnd/xnd/AUTHORS.txt +5 -0
  24. data/ext/ruby_xnd/xnd/INSTALL.txt +134 -0
  25. data/ext/ruby_xnd/xnd/LICENSE.txt +29 -0
  26. data/ext/ruby_xnd/xnd/MANIFEST.in +3 -0
  27. data/ext/ruby_xnd/xnd/Makefile.in +80 -0
  28. data/ext/ruby_xnd/xnd/README.rst +44 -0
  29. data/ext/ruby_xnd/xnd/config.guess +1530 -0
  30. data/ext/ruby_xnd/xnd/config.h.in +22 -0
  31. data/ext/ruby_xnd/xnd/config.sub +1782 -0
  32. data/ext/ruby_xnd/xnd/configure +4867 -0
  33. data/ext/ruby_xnd/xnd/configure.ac +164 -0
  34. data/ext/ruby_xnd/xnd/doc/Makefile +14 -0
  35. data/ext/ruby_xnd/xnd/doc/_static/copybutton.js +66 -0
  36. data/ext/ruby_xnd/xnd/doc/conf.py +26 -0
  37. data/ext/ruby_xnd/xnd/doc/index.rst +44 -0
  38. data/ext/ruby_xnd/xnd/doc/libxnd/data-structures.rst +186 -0
  39. data/ext/ruby_xnd/xnd/doc/libxnd/functions.rst +148 -0
  40. data/ext/ruby_xnd/xnd/doc/libxnd/index.rst +25 -0
  41. data/ext/ruby_xnd/xnd/doc/releases/index.rst +34 -0
  42. data/ext/ruby_xnd/xnd/doc/xnd/align-pack.rst +96 -0
  43. data/ext/ruby_xnd/xnd/doc/xnd/buffer-protocol.rst +42 -0
  44. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +30 -0
  45. data/ext/ruby_xnd/xnd/doc/xnd/quickstart.rst +62 -0
  46. data/ext/ruby_xnd/xnd/doc/xnd/types.rst +674 -0
  47. data/ext/ruby_xnd/xnd/install-sh +527 -0
  48. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +102 -0
  49. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +112 -0
  50. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +345 -0
  51. data/ext/ruby_xnd/xnd/libxnd/contrib.h +313 -0
  52. data/ext/ruby_xnd/xnd/libxnd/copy.c +944 -0
  53. data/ext/ruby_xnd/xnd/libxnd/equal.c +1216 -0
  54. data/ext/ruby_xnd/xnd/libxnd/inline.h +154 -0
  55. data/ext/ruby_xnd/xnd/libxnd/overflow.h +147 -0
  56. data/ext/ruby_xnd/xnd/libxnd/split.c +286 -0
  57. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.in +39 -0
  58. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.vc +44 -0
  59. data/ext/ruby_xnd/xnd/libxnd/tests/README.txt +2 -0
  60. data/ext/ruby_xnd/xnd/libxnd/tests/runtest.c +101 -0
  61. data/ext/ruby_xnd/xnd/libxnd/tests/test.h +48 -0
  62. data/ext/ruby_xnd/xnd/libxnd/tests/test_fixed.c +108 -0
  63. data/ext/ruby_xnd/xnd/libxnd/xnd.c +1304 -0
  64. data/ext/ruby_xnd/xnd/libxnd/xnd.h +449 -0
  65. data/ext/ruby_xnd/xnd/python/test_xnd.py +3144 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +290 -0
  67. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +2822 -0
  68. data/ext/ruby_xnd/xnd/python/xnd/contrib/pretty.py +850 -0
  69. data/ext/ruby_xnd/xnd/python/xnd/docstrings.h +129 -0
  70. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +200 -0
  71. data/ext/ruby_xnd/xnd/python/xnd/util.h +182 -0
  72. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +1121 -0
  73. data/ext/ruby_xnd/xnd/python/xnd_support.py +106 -0
  74. data/ext/ruby_xnd/xnd/setup.py +303 -0
  75. data/ext/ruby_xnd/xnd/vcbuild/INSTALL.txt +42 -0
  76. data/ext/ruby_xnd/xnd/vcbuild/runtest32.bat +16 -0
  77. data/ext/ruby_xnd/xnd/vcbuild/runtest64.bat +14 -0
  78. data/ext/ruby_xnd/xnd/vcbuild/vcbuild32.bat +29 -0
  79. data/ext/ruby_xnd/xnd/vcbuild/vcbuild64.bat +29 -0
  80. data/ext/ruby_xnd/xnd/vcbuild/vcclean.bat +13 -0
  81. data/ext/ruby_xnd/xnd/vcbuild/vcdistclean.bat +14 -0
  82. data/lib/ruby_xnd.so +0 -0
  83. data/lib/xnd.rb +306 -0
  84. data/lib/xnd/monkeys.rb +29 -0
  85. data/lib/xnd/version.rb +6 -0
  86. data/spec/debug_spec.rb +9 -0
  87. data/spec/gc_guard_spec.rb +10 -0
  88. data/spec/leakcheck.rb +9 -0
  89. data/spec/spec_helper.rb +877 -0
  90. data/spec/type_inference_spec.rb +81 -0
  91. data/spec/xnd_spec.rb +2921 -0
  92. data/xnd.gemspec +47 -0
  93. metadata +215 -0
@@ -0,0 +1,16 @@
1
+ @ECHO OFF
2
+ echo.
3
+ <nul (set /p x="Running static library tests ... ")
4
+ echo.
5
+ echo.
6
+ dist32\runtest.exe
7
+ IF ERRORLEVEL 1 echo FAIL
8
+ echo.
9
+ <nul (set /p x="Running shared library tests ... ")
10
+ echo.
11
+ echo.
12
+ copy /y ..\ndtypes\libndtypes\libndtypes-0.2.0dev3.dll dist32
13
+ dist32\runtest_shared.exe
14
+ IF ERRORLEVEL 1 echo FAIL
15
+
16
+
@@ -0,0 +1,14 @@
1
+ @ECHO OFF
2
+ echo.
3
+ <nul (set /p x="Running static library tests ... ")
4
+ echo.
5
+ echo.
6
+ dist64\runtest.exe
7
+ IF ERRORLEVEL 1 echo FAIL
8
+ echo.
9
+ <nul (set /p x="Running shared library tests ... ")
10
+ echo.
11
+ echo.
12
+ copy /y ..\ndtypes\libndtypes\libndtypes-0.2.0dev3.dll dist64
13
+ dist64\runtest_shared.exe
14
+ IF ERRORLEVEL 1 echo FAIL
@@ -0,0 +1,29 @@
1
+ @ECHO off
2
+
3
+ if not exist dist32 mkdir dist32
4
+ if exist dist32\* del /q dist32\*
5
+
6
+ cd ..\libxnd
7
+ copy /y Makefile.vc Makefile
8
+
9
+ nmake /nologo clean
10
+ nmake /nologo
11
+
12
+ copy /y libxnd-0.2.0dev3.lib ..\vcbuild\dist32
13
+ copy /y libxnd-0.2.0dev3.dll ..\vcbuild\dist32
14
+ copy /y libxnd-0.2.0dev3.dll.lib ..\vcbuild\dist32
15
+ copy /y libxnd-0.2.0dev3.dll.exp ..\vcbuild\dist32
16
+ copy /y xnd.h ..\vcbuild\dist32
17
+
18
+ cd tests
19
+ copy /y Makefile.vc Makefile
20
+ nmake /nologo clean
21
+ nmake /nologo
22
+
23
+ copy /y runtest.exe ..\..\vcbuild\dist32
24
+ copy /y runtest_shared.exe ..\..\vcbuild\dist32
25
+
26
+ cd ..\..\vcbuild
27
+
28
+
29
+
@@ -0,0 +1,29 @@
1
+ @ECHO off
2
+
3
+ if not exist dist64 mkdir dist64
4
+ if exist dist64\* del /q dist64\*
5
+
6
+ cd ..\libxnd
7
+ copy /y Makefile.vc Makefile
8
+
9
+ nmake /nologo clean
10
+ nmake /nologo
11
+
12
+ copy /y libxnd-0.2.0dev3.lib ..\vcbuild\dist64
13
+ copy /y libxnd-0.2.0dev3.dll ..\vcbuild\dist64
14
+ copy /y libxnd-0.2.0dev3.dll.lib ..\vcbuild\dist64
15
+ copy /y libxnd-0.2.0dev3.dll.exp ..\vcbuild\dist64
16
+ copy /y xnd.h ..\vcbuild\dist64
17
+
18
+ cd tests
19
+ copy /y Makefile.vc Makefile
20
+ nmake /nologo clean
21
+ nmake /nologo
22
+
23
+ copy /y runtest.exe ..\..\vcbuild\dist64
24
+ copy /y runtest_shared.exe ..\..\vcbuild\dist64
25
+
26
+ cd ..\..\vcbuild
27
+
28
+
29
+
@@ -0,0 +1,13 @@
1
+ @ECHO off
2
+
3
+ cd ..\libxnd
4
+ if exist Makefile nmake /nologo clean
5
+
6
+ cd tests
7
+ if exist Makefile nmake /nologo clean
8
+
9
+ cd ..\..\vcbuild
10
+ if exist dist64 rd /q /s dist64
11
+ if exist dist32 rd /q /s dist32
12
+
13
+
@@ -0,0 +1,14 @@
1
+ @ECHO off
2
+
3
+ cd ..\libxnd
4
+ if exist Makefile nmake /nologo distclean
5
+
6
+ cd tests
7
+ if exist Makefile nmake /nologo distclean
8
+
9
+ cd ..\..\vcbuild
10
+ if exist dist64 rd /q /s dist64
11
+ if exist dist32 rd /q /s dist32
12
+
13
+
14
+
Binary file
@@ -0,0 +1,306 @@
1
+ # BSD 3-Clause License
2
+ #
3
+ # Copyright (c) 2018, Quansight and Sameer Deshmukh
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # * Neither the name of the copyright holder nor the names of its
17
+ # contributors may be used to endorse or promote products derived from
18
+ # this software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'ndtypes'
32
+ require "ruby_xnd.so"
33
+
34
+ require 'xnd/monkeys'
35
+ require 'xnd/version'
36
+
37
+ INF = Float::INFINITY
38
+
39
+ class RubyXND
40
+ class Ellipsis
41
+ def to_s
42
+ "..."
43
+ end
44
+ end
45
+ end
46
+
47
+ class XND < RubyXND
48
+ # Immutable array type used when specifying XND tuples without wanting to
49
+ # specify the type. It is highly recommended to simply specify the type
50
+ # and use Ruby Arrays for specifying the data.
51
+ #
52
+ # If you call #to_a or #value on XND after specifying data as XND::T, note
53
+ # that XND will return the data in the form of Ruby Arrays.
54
+ #
55
+ # The sole purpose for the existence of this class is the facilitation of
56
+ # type inference. Before passing to the C interface, all instaces of XND::T
57
+ # will be converted into Ruby Arrays.
58
+ #
59
+ # @example
60
+ #
61
+ # x = XND.new XND::T.new([])
62
+ # #=> XND([], type: ())
63
+ class T
64
+ include Enumerable
65
+ attr_reader :data
66
+
67
+ def initialize *args, &block
68
+ @data = args
69
+ end
70
+
71
+ def each &block
72
+ @data.each(&block)
73
+ end
74
+
75
+ def map &block
76
+ @data.map(&block)
77
+ end
78
+
79
+ def map! &block
80
+ @data.map!(&block)
81
+ end
82
+
83
+ def [] *index
84
+ @data[index]
85
+ end
86
+ end
87
+
88
+ MAX_DIM = NDTypes::MAX_DIM
89
+
90
+ # Methods for type inference.
91
+ module TypeInference
92
+ class << self
93
+ # Infer the type of a Ruby value. In general, types should be explicitly
94
+ # specified.
95
+ def type_of value, dtype: nil
96
+ NDTypes.new actual_type_of(value, dtype: dtype)
97
+ end
98
+
99
+ def actual_type_of value, dtype: nil
100
+ ret = nil
101
+ if value.is_a?(Array)
102
+ data, shapes = data_shapes value
103
+ opt = data.include? nil
104
+
105
+ if dtype.nil?
106
+ if data.nil?
107
+ dtype = 'float64'
108
+ else
109
+ dtype = choose_dtype(data)
110
+
111
+ data.each do |x|
112
+ if !x.nil?
113
+ t = actual_type_of(x)
114
+ if t != dtype
115
+ raise ValueError, "dtype mismatch: have t=#{t} and dtype=#{dtype}"
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ dtype = '?' + dtype if opt
122
+ end
123
+
124
+ t = dtype
125
+ var = shapes.map { |lst| lst.uniq.size > 1 || nil }.any?
126
+ shapes.each do |lst|
127
+ opt = lst.include? nil
128
+ lst.map! { |x| x.nil? ? 0 : x }
129
+ t = add_dim(opt: opt, shapes: lst, typ: t, use_var: var)
130
+ end
131
+
132
+ ret = t
133
+ elsif !dtype.nil?
134
+ raise TypeError, "dtype argument is only supported for Arrays."
135
+ elsif value.is_a? Hash
136
+ if value.keys.all? { |k| k.is_a?(String) }
137
+ ret = "{" + value.map { |k, v| "#{k} : #{actual_type_of(v)}"}.join(", ") + "}"
138
+ else
139
+ raise ValueError, "all hash keys must be String."
140
+ end
141
+ elsif value.is_a? XND::T # tuple
142
+ ret = "(" + value.map { |v| actual_type_of(v) }.join(",") + ")"
143
+ elsif value.nil?
144
+ ret = '?float64'
145
+ elsif value.is_a? Float
146
+ ret = 'float64'
147
+ elsif value.is_a? Complex
148
+ ret = 'complex128'
149
+ elsif value.is_a? Integer
150
+ ret = 'int64'
151
+ elsif value.is_a? String
152
+ ret = value.encoding == Encoding::ASCII_8BIT ? 'bytes' : 'string'
153
+ elsif value.is_a?(TrueClass) || value.is_a?(FalseClass)
154
+ ret = 'bool'
155
+ else
156
+ raise ArgumentError, "cannot infer data type for: #{value}"
157
+ end
158
+
159
+ ret
160
+ end
161
+
162
+ def accumulate arr
163
+ result = []
164
+ arr.inject(0) do |memo, a|
165
+ result << memo + a
166
+ memo + a
167
+ end
168
+
169
+ result
170
+ end
171
+
172
+ # Construct a new dimension type based on the list of 'shapes' that
173
+ # are present in a dimension.
174
+ def add_dim *args, opt: false, shapes: nil, typ: nil, use_var: false
175
+ if use_var
176
+ offsets = [0] + accumulate(shapes)
177
+ return "#{opt ? '?' : ''}var(offsets=#{offsets}) * #{typ}"
178
+ else
179
+ n = shapes.uniq.size
180
+ shape = (n == 0 ? 0 : shapes[0])
181
+ return "#{shape} * #{typ}"
182
+ end
183
+ end
184
+
185
+ # Internal function for extracting the data and dimensions of nested arrays.
186
+ def search level, data, acc, minmax
187
+ raise(ValueError, "too many dimensions: #{level}") if level > MAX_DIM
188
+
189
+ current = acc[level]
190
+ if data.nil?
191
+ current << data
192
+ elsif data.is_a?(Array)
193
+ current << data.size
194
+ next_level = level + 1
195
+ minmax[1] = [next_level, minmax[1]].max
196
+
197
+ if !data
198
+ minmax[0] = [next_level, minmax[0]].min
199
+ else
200
+ data.each do |item|
201
+ search level+1, item, acc, minmax
202
+ end
203
+ end
204
+ else
205
+ acc[minmax[1]] << data
206
+ minmax[0] = [level, minmax[0]].min
207
+ end
208
+ end
209
+
210
+ # Extract array data and dimension shapes from a nested Array. The
211
+ # Array may contain nil for missing data or dimensions.
212
+ #
213
+ # @example
214
+ # data_shapes [[0, 1], [2, 3, 4], [5, 6, 7, 8]]
215
+ # #=> [[0, 1, 2, 3, 4, 5, 6, 7, 8], [[2, 3, 4], [3]]]
216
+ # # ^ ^ ^
217
+ # # | | `--- ndim=2: single shape 3
218
+ # # | `-- ndim=1: shapes 2, 3, 4
219
+ # # `--- ndim=0: extracted array data
220
+ def data_shapes tree
221
+ acc = Array.new(MAX_DIM + 1) { [] }
222
+ min_level = MAX_DIM + 1
223
+ max_level = 0
224
+ minmax = [min_level, max_level]
225
+
226
+ search max_level, tree, acc, minmax
227
+
228
+ min_level = minmax[0]
229
+ max_level = minmax[1]
230
+
231
+ if acc[max_level] && acc[max_level].all? { |a| a.nil? }
232
+ # min_level is not set in this special case. Hence the check.
233
+ elsif min_level != max_level
234
+ raise ValueError, "unbalanced tree: min depth #{min_level} and max depth #{max_level}"
235
+ end
236
+
237
+ data = acc[max_level]
238
+ shapes = acc[0...max_level].reverse
239
+
240
+ [data, shapes]
241
+ end
242
+
243
+ def choose_dtype array
244
+ array.each do |x|
245
+ return actual_type_of(x) if !x.nil?
246
+ end
247
+
248
+ 'float64'
249
+ end
250
+
251
+ def convert_xnd_t_to_ruby_array data
252
+ if data.is_a?(XND::T)
253
+ data.map! do |d|
254
+ convert_xnd_t_to_ruby_array d
255
+ end
256
+
257
+ return data.data
258
+ elsif data.is_a? Hash
259
+ data.each do |k, v|
260
+ data[k] = convert_xnd_t_to_ruby_array v
261
+ end
262
+ elsif data.is_a? Array
263
+ data.map! do |d|
264
+ convert_xnd_t_to_ruby_array d
265
+ end
266
+ else
267
+ return data
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ def initialize data, type: nil, dtype: nil, levels: nil, typedef: nil, dtypedef: nil
274
+ if [type, dtype, levels, typedef, dtypedef].count(nil) < 2
275
+ raise ArgumentError, "the 'type', 'dtype', 'levels' and 'typedef' arguments are "
276
+ "mutually exclusive."
277
+ end
278
+
279
+ if type
280
+ type = NDTypes.new(type) if type.is_a? String
281
+ elsif dtype
282
+ type = TypeInference.type_of data, dtype: dtype
283
+ elsif levels
284
+ args = levels.map { |l| l ? l : 'NA' }.join(', ')
285
+ t = "#{value.size} * categorical(#{args})"
286
+ type = NDTypes.new t
287
+ elsif typedef
288
+ type = NDTypes.new typedef
289
+ if type.abstract?
290
+ dtype = type.hidden_dtype
291
+ t = TypeInference.type_of data, dtype: dtype
292
+ type = NDTypes.instantiate typedef, t
293
+ end
294
+ elsif dtypedef
295
+ dtype = NDTypes.new dtypedef
296
+ type = TypeInference.type_of data, dtype: dtype
297
+ else
298
+ type = TypeInference.type_of data
299
+ data = TypeInference.convert_xnd_t_to_ruby_array data
300
+ end
301
+
302
+ super(type, data)
303
+ end
304
+
305
+ alias :to_a :value
306
+ end
@@ -0,0 +1,29 @@
1
+ class String
2
+ # Force encode string to ASCII-8BIT.
3
+ #
4
+ # Reference: https://idiosyncratic-ruby.com/56-us-ascii-8bit.html
5
+ # FIXME: Hopefully find a better way of doing this soon.
6
+ def b
7
+ self.force_encoding "ASCII-8BIT"
8
+ end
9
+
10
+ # Encode string as UTF-16.
11
+ def u16!
12
+ self.encode! Encoding::UTF_16
13
+ end
14
+
15
+ # Encode string as UTF-16.
16
+ def u16
17
+ self.encode Encoding::UTF_16
18
+ end
19
+
20
+ # Encode string as UTF-32.
21
+ def u32!
22
+ self.encode! Encoding::UTF_32
23
+ end
24
+
25
+ # Encode string as UTF-32.
26
+ def u32
27
+ self.encode Encoding::UTF_32
28
+ end
29
+ end