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 +4 -4
- data/README.md +5 -0
- data/Rakefile +15 -45
- data/ext/ruby_xnd/extconf.rb +6 -2
- data/ext/ruby_xnd/float_pack_unpack.h +8 -0
- data/ext/ruby_xnd/ruby_xnd.c +57 -23
- data/ext/ruby_xnd/util.c +165 -0
- data/ext/ruby_xnd/util.h +7 -116
- data/lib/xnd.rb +11 -3
- data/lib/xnd/version.rb +1 -1
- data/xnd.gemspec +3 -2
- metadata +21 -25
- data/ext/ruby_xnd/include/xnd.h +0 -449
- data/ext/ruby_xnd/lib/libxnd.a +0 -0
- data/ext/ruby_xnd/lib/libxnd.so +0 -1
- data/ext/ruby_xnd/lib/libxnd.so.0 +0 -1
- data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
- data/lib/ruby_xnd.so +0 -0
- data/lib/xnd/monkeys.rb +0 -29
- data/spec/debug_spec.rb +0 -9
- data/spec/gc_guard_spec.rb +0 -10
- data/spec/leakcheck.rb +0 -9
- data/spec/spec_helper.rb +0 -877
- data/spec/type_inference_spec.rb +0 -81
- data/spec/xnd_spec.rb +0 -2921
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 536c884cecfd158e1e01e9aff7064f4d0e2e676c
|
4
|
+
data.tar.gz: 3021eac9e7c2432bd1a1442370eee8d606499377
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9c5d29e4dd7da6d5004f1dfbb2cbbadd79c096f7cf7b1e4c61f33eb1781c8af9e4e246caf67f53b106428a3544f18e72aa9ed0a7b54c7376f114c8b16fac272
|
7
|
+
data.tar.gz: '097f3df97bb4fa565f3d499329f6c8359759427b364e579689eee4fb8efc503036f49fa11ee6aa0c93cfe7ddff6080f6d2c8c06e7efc83cd08887495d79f11b1'
|
data/README.md
CHANGED
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
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
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 +=
|
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",
|
data/ext/ruby_xnd/extconf.rb
CHANGED
@@ -14,7 +14,7 @@ end
|
|
14
14
|
|
15
15
|
# libndtypes config
|
16
16
|
|
17
|
-
ndtypes_version = ">= 0.2.
|
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
|
data/ext/ruby_xnd/ruby_xnd.c
CHANGED
@@ -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(
|
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 -
|
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
|
-
|
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
|
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
|
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);
|
data/ext/ruby_xnd/util.c
ADDED
@@ -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
|
+
}
|