xnd 0.2.0dev3

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 (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