xnd 0.2.0dev5 → 0.2.0dev6

Sign up to get free protection for your applications and to get access to all the features.
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
+ }