xnd 0.2.0dev5 → 0.2.0dev6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c72739d8baf63a7ea8c88c629cdcd95e66bf63b
4
- data.tar.gz: af5fd4043cb9ef384045fa9336afd4b6ada916c3
3
+ metadata.gz: 536c884cecfd158e1e01e9aff7064f4d0e2e676c
4
+ data.tar.gz: 3021eac9e7c2432bd1a1442370eee8d606499377
5
5
  SHA512:
6
- metadata.gz: 185d044acea2787a12fb235a8aa45e156db2cd90a7e7dfe7b6dc4eb26efc401c89a36df5db31c97a8db17b092deb2d4181e140dd2c6fa1630d36152762a6a127
7
- data.tar.gz: 171bbee778e719d8038e662a2c55b37921426b2c6e3dafb284b4ec872dd0f445d59f3182d83beffb58dc3aa8e5b7f69e4c89f3177b4710ce847ca14fd5d6ea90
6
+ metadata.gz: f9c5d29e4dd7da6d5004f1dfbb2cbbadd79c096f7cf7b1e4c61f33eb1781c8af9e4e246caf67f53b106428a3544f18e72aa9ed0a7b54c7376f114c8b16fac272
7
+ data.tar.gz: '097f3df97bb4fa565f3d499329f6c8359759427b364e579689eee4fb8efc503036f49fa11ee6aa0c93cfe7ddff6080f6d2c8c06e7efc83cd08887495d79f11b1'
data/README.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # Introduction
2
2
 
3
+ XND is a library for storing typed data defined by ndtypes. It is a wrapper
4
+ over the libxnd C library.
5
+
3
6
  # Installation
4
7
 
8
+ For direct installation, run: `gem install xnd --pre`.
9
+
5
10
  # Usage
6
11
 
7
12
  # Acknowledgments
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rake'
2
2
  require 'rake/extensiontask'
3
- require 'rspec/core/rake_task'
4
3
  require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
5
  require 'fileutils'
6
6
  require 'xnd/version.rb'
7
7
 
@@ -13,6 +13,12 @@ Rake::ExtensionTask.new(ext_name, gemspec) do |ext|
13
13
  ext.source_pattern = "**/*.{c,h}"
14
14
  end
15
15
 
16
+ Rake::TestTask.new(:test) do |t|
17
+ t.libs << "test"
18
+ t.libs << "lib"
19
+ t.test_files = FileList['test/**/test_*.rb']
20
+ end
21
+
16
22
  def run *cmd
17
23
  sh(cmd.join(" "))
18
24
  end
@@ -53,55 +59,19 @@ VALGRIND_MEMORYFILL_OPTIONS = [
53
59
  "--free-fill=66 ",
54
60
  ]
55
61
 
56
- GDB_OPTIONS = []
57
-
58
- namespace :spec do
59
- # partial-loads-ok and undef-value-errors necessary to ignore
60
- # spurious (and eminently ignorable) warnings from the ruby
61
- # interpreter
62
+ # partial-loads-ok and undef-value-errors necessary to ignore
63
+ # spurious (and eminently ignorable) warnings from the ruby
64
+ # interpreter
62
65
 
63
- RSPEC_CMD = [ 'ruby', '-S', 'rspec', '-Ilib:ext', SPECDIR.to_s ]
64
-
65
- desc "Run specs under GDB."
66
- task :gdb => [ :compile ] do |task|
67
- cmd = [ 'gdb' ] + GDB_OPTIONS
68
- cmd += [ '--args' ]
69
- cmd += RSPEC_CMD
70
- run( *cmd )
71
- end
72
-
73
- desc "Run specs under cgdb."
74
- task :cgdb => [ :compile ] do |task|
75
- cmd = [ 'cgdb' ] + GDB_OPTIONS
76
- cmd += [ '--args' ]
77
- cmd += RSPEC_CMD
78
- run( *cmd )
79
- end
80
-
81
- desc "Run specs under Valgrind."
82
- task :valgrind => [ :compile ] do |task|
83
- cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
84
- cmd += RSPEC_CMD
85
- run( *cmd )
86
- end
87
-
88
- desc "Run specs under Callgrind."
89
- task :callgrind => [ :compile ] do |task|
90
- cmd = [ 'valgrind' ] + CALLGRIND_OPTIONS
91
- cmd += RSPEC_CMD
92
- run( *cmd )
93
- end
94
- end
95
-
96
- LEAKCHECK_CMD = [ 'ruby', '-Ilib:ext', "#{SPECDIR}/leakcheck.rb" ]
97
-
98
- desc "Run leakcheck script."
99
- task :leakcheck => [ :compile ] do |task|
66
+ desc "Run specs under Valgrind."
67
+ task :valgrind => [ :compile ] do |task|
100
68
  cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
101
- cmd += LEAKCHECK_CMD
69
+ cmd += [" rake test "]
102
70
  run( *cmd )
103
71
  end
104
72
 
73
+ LEAKCHECK_CMD = [ 'ruby', '-Ilib:ext', "#{SPECDIR}/leakcheck.rb" ]
74
+
105
75
  task :clobber do |task|
106
76
  [
107
77
  "ext/#{ext_name}/include",
@@ -14,7 +14,7 @@ end
14
14
 
15
15
  # libndtypes config
16
16
 
17
- ndtypes_version = ">= 0.2.0dev3"
17
+ ndtypes_version = ">= 0.2.0dev5"
18
18
  ndtypes_spec = Gem::Specification.find_by_name("ndtypes", ndtypes_version)
19
19
  ndtypes_extdir = File.join(ndtypes_spec.gem_dir, 'ext', 'ruby_ndtypes')
20
20
  ndtypes_includedir = File.join(ndtypes_extdir, 'include')
@@ -52,6 +52,10 @@ headers = File.expand_path(File.join(File.dirname(__FILE__) + "/include/"))
52
52
  find_library("xnd", nil, binaries)
53
53
  find_header("xnd.h", headers)
54
54
 
55
+ FileUtils.copy_file File.expand_path(File.join(File.dirname(__FILE__) +
56
+ "/ruby_xnd.h")),
57
+ "#{headers}/ruby_xnd.h"
58
+
55
59
  dir_config("xnd", [headers], [binaries])
56
60
 
57
61
  $INSTALLFILES = [
@@ -62,7 +66,7 @@ $INSTALLFILES = [
62
66
  # for macOS
63
67
  append_ldflags("-Wl,-rpath #{binaries}")
64
68
 
65
- basenames = %w{float_pack_unpack gc_guard ruby_xnd}
69
+ basenames = %w{util float_pack_unpack gc_guard ruby_xnd}
66
70
  $objs = basenames.map { |b| "#{b}.o" }
67
71
  $srcs = basenames.map { |b| "#{b}.c" }
68
72
 
@@ -34,6 +34,14 @@
34
34
  Author: Sameer Deshmukh (@v0dro)
35
35
  */
36
36
 
37
+ int rb_xnd_pack_float32(double num, unsigned char* ptr, int le);
38
+
39
+ int rb_xnd_unpack_float32(float *x, unsigned char* ptr, int le);
40
+
41
+ int rb_xnd_pack_float64(double num, unsigned char *ptr, int le);
42
+
43
+ int rb_xnd_unpack_float64(double *x, unsigned char *ptr, int le);
44
+
37
45
  #ifdef XND_DEBUG
38
46
  void run_float_pack_unpack_tests(void);
39
47
  #endif
@@ -40,7 +40,6 @@
40
40
  VALUE cRubyXND;
41
41
  VALUE cXND;
42
42
  static VALUE cRubyXND_MBlock;
43
- static VALUE cRubyXND_Ellipsis;
44
43
  static const rb_data_type_t MemoryBlockObject_type;
45
44
  static const rb_data_type_t XndObject_type;
46
45
 
@@ -72,7 +71,8 @@ obj_inspect(const char* msg, VALUE obj)
72
71
  static VALUE
73
72
  xnd_ellipsis(void)
74
73
  {
75
- return rb_funcall(cRubyXND_Ellipsis, rb_intern("initialize"), 0, NULL);
74
+ return rb_funcall(rb_const_get_at(cXND, rb_intern("Ellipsis")),
75
+ rb_intern("new"), 0, NULL);
76
76
  }
77
77
 
78
78
  /****************************************************************************/
@@ -213,13 +213,6 @@ _strncpy(char *dest, const void *src, size_t len, size_t size)
213
213
  memset(dest+len, '\0', size-len);
214
214
  }
215
215
 
216
- /* Return true if String is unicode. */
217
- static int
218
- string_is_unicode(VALUE str)
219
- {
220
-
221
- }
222
-
223
216
  static int
224
217
  string_is_ascii(VALUE str)
225
218
  {
@@ -241,14 +234,6 @@ string_is_u8(VALUE str)
241
234
  );
242
235
  }
243
236
 
244
- /* Encode a string to enc. enc should be name of the constant in Encoding::*. */
245
- static VALUE
246
- string_encode(VALUE str, const char * enc)
247
- {
248
- return rb_funcall(str, rb_intern("encode"), 1,
249
- rb_const_get(rb_cEncoding, rb_intern(enc)));
250
- }
251
-
252
237
  static int64_t
253
238
  u8_skip_trailing_zero(const uint8_t *ptr, int64_t codepoints)
254
239
  {
@@ -1013,6 +998,7 @@ XND_type(VALUE self)
1013
998
 
1014
999
  GET_XND(self, xnd_p);
1015
1000
 
1001
+
1016
1002
  return xnd_p->type;
1017
1003
  }
1018
1004
 
@@ -1072,6 +1058,9 @@ _XND_value(const xnd_t * const x, const int64_t maxshape)
1072
1058
  seterr(&ctx);
1073
1059
  raise_error();
1074
1060
  }
1061
+ if (shape > maxshape) {
1062
+ shape = maxshape;
1063
+ }
1075
1064
 
1076
1065
  array = array_new(shape);
1077
1066
 
@@ -1131,7 +1120,7 @@ _XND_value(const xnd_t * const x, const int64_t maxshape)
1131
1120
  hash = rb_hash_new();
1132
1121
 
1133
1122
  for (i = 0; i < shape; ++i) {
1134
- if (i == maxshape - i) {
1123
+ if (i == maxshape - 1) {
1135
1124
  rb_hash_aset(hash, xnd_ellipsis(), xnd_ellipsis());
1136
1125
  break;
1137
1126
  }
@@ -1459,7 +1448,7 @@ convert_single(xnd_index_t *key, VALUE obj, size_t size)
1459
1448
  rb_raise(rb_eIndexError, "Cannot use Range on this type.");
1460
1449
  };
1461
1450
 
1462
- size_t begin, end, step;
1451
+ long long begin, end, step;
1463
1452
 
1464
1453
  rb_range_unpack(obj, &begin, &end, &step, size);
1465
1454
  key->tag = Slice;
@@ -1536,11 +1525,10 @@ XND_array_aref(int argc, VALUE *argv, VALUE self)
1536
1525
  NDT_STATIC_CONTEXT(ctx);
1537
1526
  xnd_index_t indices[NDT_MAX_DIM];
1538
1527
  xnd_t x;
1539
- int len, state;
1528
+ int len;
1540
1529
  uint8_t flags;
1541
1530
  XndObject *xnd_p;
1542
1531
  size_t size;
1543
- VALUE rb_size;
1544
1532
 
1545
1533
  if (argc == 0) {
1546
1534
  rb_raise(rb_eArgError, "expected atleast one argument for #[].");
@@ -1563,6 +1551,15 @@ XND_array_aref(int argc, VALUE *argv, VALUE self)
1563
1551
  return RubyXND_view_move_type(xnd_p, &x);
1564
1552
  }
1565
1553
 
1554
+ /* Compare between data of an XND object and Ruby object. */
1555
+ static VALUE
1556
+ convert_compare(VALUE self, VALUE other)
1557
+ {
1558
+ VALUE vcmp = XND_value(self);
1559
+
1560
+ return rb_funcall(vcmp, rb_intern("=="), 1, other);
1561
+ }
1562
+
1566
1563
  /* Implementation for #== method.
1567
1564
 
1568
1565
  @param other Other Ruby object to compare with.
@@ -1576,7 +1573,7 @@ XND_eqeq(VALUE self, VALUE other)
1576
1573
  int r;
1577
1574
 
1578
1575
  if (!XND_CHECK_TYPE(other)) {
1579
- return Qfalse;
1576
+ return convert_compare(self, other);
1580
1577
  }
1581
1578
 
1582
1579
  GET_XND(self, left_p);
@@ -1789,6 +1786,27 @@ XND_each(VALUE self)
1789
1786
 
1790
1787
  }
1791
1788
 
1789
+ /* Implement XND#short_value */
1790
+ static VALUE
1791
+ XND_short_value(VALUE self, VALUE maxshape)
1792
+ {
1793
+ if (maxshape == Qnil) {
1794
+ return XND_value(self);
1795
+ }
1796
+ else {
1797
+ long max = NUM2LONG(maxshape);
1798
+ XndObject *self_p;
1799
+
1800
+ GET_XND(self, self_p);
1801
+
1802
+ if (max < 0) {
1803
+ rb_raise(rb_eArgError, "maxshape must be positive.");
1804
+ }
1805
+
1806
+ return _XND_value(XND(self_p), max);
1807
+ }
1808
+ }
1809
+
1792
1810
  /*************************** Singleton methods ********************************/
1793
1811
 
1794
1812
  static VALUE
@@ -1910,11 +1928,26 @@ rb_xnd_get_type(void)
1910
1928
 
1911
1929
  void Init_ruby_xnd(void)
1912
1930
  {
1931
+ NDT_STATIC_CONTEXT(ctx);
1932
+ static int initialized = 0;
1933
+
1934
+ if (!initialized) {
1935
+ if (xnd_init_float(&ctx) < 0) {
1936
+ seterr(&ctx);
1937
+ raise_error();
1938
+ }
1939
+
1940
+ if (!ndt_exists()) {
1941
+ rb_raise(rb_eLoadError, "NDT does not exist.");
1942
+ }
1943
+
1944
+ initialized = 1;
1945
+ }
1946
+
1913
1947
  /* init classes */
1914
1948
  cRubyXND = rb_define_class("RubyXND", rb_cObject);
1915
1949
  cXND = rb_define_class("XND", cRubyXND);
1916
1950
  cRubyXND_MBlock = rb_define_class_under(cRubyXND, "MBlock", rb_cObject);
1917
- cRubyXND_Ellipsis = rb_define_class_under(cRubyXND, "Ellipsis", rb_cObject);
1918
1951
  mRubyXND_GCGuard = rb_define_module_under(cRubyXND, "GCGuard");
1919
1952
 
1920
1953
  /* errors */
@@ -1934,6 +1967,7 @@ void Init_ruby_xnd(void)
1934
1967
  rb_define_method(cXND, "<=>", XND_spaceship, 1);
1935
1968
  rb_define_method(cXND, "strict_equal", XND_strict_equal, 1);
1936
1969
  rb_define_method(cXND, "size", XND_size, 0);
1970
+ rb_define_method(cXND, "short_value", XND_short_value, 1);
1937
1971
 
1938
1972
  /* iterators */
1939
1973
  rb_define_method(cXND, "each", XND_each, 0);
@@ -0,0 +1,165 @@
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
+
32
+ #include "ruby.h"
33
+ #include <stdlib.h>
34
+ #include <stdint.h>
35
+ #include <inttypes.h>
36
+ #include "ndtypes.h"
37
+
38
+ void
39
+ raise_error(void)
40
+ {
41
+ VALUE exeception = rb_errinfo();
42
+
43
+ rb_set_errinfo(Qnil);
44
+ rb_exc_raise(exeception);
45
+ }
46
+
47
+ void
48
+ set_error_info(VALUE err, const char * msg)
49
+ {
50
+ rb_set_errinfo(rb_exc_new2(err, msg));
51
+ }
52
+
53
+ size_t
54
+ safe_downcast(int64_t size)
55
+ {
56
+ #if SIZE_MAX < INT64_MAX
57
+ if (size > INT32_MAX) {
58
+ rb_raise(rb_eSizeError,
59
+ "sizes should never exceed INT32_MAX on 32-bit platforms.");
60
+ }
61
+ #endif
62
+ return (size_t)size;
63
+ }
64
+
65
+ bool
66
+ check_invariants(const ndt_t *t)
67
+ {
68
+ #if SIZE_MAX < INT64_MAX
69
+ return safe_downcast(t->datasize) >= 0;
70
+ #else
71
+ (void)t;
72
+ return 1;
73
+ #endif
74
+ }
75
+
76
+ VALUE
77
+ array_new(int64_t size)
78
+ {
79
+ #if SIZE_MAX < INT64_MAX
80
+ size_t n = safe_downcast(size);
81
+ return n < 0 ? NULL : rb_ary_new2(n);
82
+ #else
83
+ return rb_ary_new2(size);
84
+ #endif
85
+ }
86
+
87
+ VALUE
88
+ bytes_from_string_and_size(const char *str, int64_t size)
89
+ {
90
+ #if SIZE_MAX < INT64_MAX
91
+ size_t n = safe_downcast(size);
92
+ return n < 0 ? NULL : rb_str_new(str, n);
93
+ #else
94
+ return rb_str_new(str, size);
95
+ #endif
96
+ }
97
+
98
+ long long
99
+ mod(long long a, long long b)
100
+ {
101
+ long long r = a % b;
102
+ return r < 0 ? r + b : r;
103
+ }
104
+
105
+ void
106
+ rb_range_unpack(VALUE range, long long *begin, long long *end, long long *step, size_t size)
107
+ {
108
+ /* FIXME: As of 27 Aug. 2018 Ruby trunk implements step as a property of
109
+ Range and XND will support it as and when it is available. Maybe for
110
+ now we can implement a #step iterator in a separate method.
111
+ */
112
+ *step = 1;
113
+ VALUE rb_begin = rb_funcall(range, rb_intern("begin"), 0, NULL);
114
+ VALUE rb_end = rb_funcall(range, rb_intern("end"), 0, NULL);
115
+ int exclude_end = RTEST(rb_funcall(range, rb_intern("exclude_end?"), 0, NULL));
116
+
117
+ if (RB_TYPE_P(rb_begin, T_FLOAT)) {
118
+ double value = RFLOAT_VALUE(rb_begin);
119
+
120
+ if (isinf(value)) {
121
+ *begin = 0;
122
+ }
123
+ }
124
+ else {
125
+ long long temp = NUM2LL(rb_begin);
126
+
127
+ if (temp < 0) { /* if negative index map to positive. */
128
+ temp = mod(temp, (long long)size);
129
+ }
130
+
131
+ *begin = temp;
132
+ }
133
+
134
+ if (RB_TYPE_P(rb_end, T_FLOAT)) {
135
+ double value = RFLOAT_VALUE(rb_end);
136
+
137
+ if (isinf(value)) {
138
+ *end = INT64_MAX;
139
+ return;
140
+ }
141
+ }
142
+ else {
143
+ long long temp = NUM2LL(rb_end);
144
+
145
+ if (temp < 0) { /* if negative index map to ppositive. */
146
+ temp = mod(temp, (long long)size);
147
+ }
148
+
149
+ *end = temp;
150
+ }
151
+
152
+ /* a[0..0] in Ruby returns the 0th index.
153
+ a[0...0] in Ruby returns empty array like a[0:0] in Python.
154
+ libxnd does not include the last index by default.
155
+ */
156
+ if (!exclude_end) {
157
+ *end += 1;
158
+ }
159
+ }
160
+
161
+ int
162
+ ndt_exists(void)
163
+ {
164
+ return RTEST(rb_const_get(rb_cObject, rb_intern("NDT")));
165
+ }