cumo 0.5.3 → 0.5.5
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 +4 -4
- data/3rd_party/mkmf-cu/lib/mkmf-cu/cli.rb +5 -2
- data/3rd_party/mkmf-cu/lib/mkmf-cu/nvcc.rb +1 -1
- data/CHANGELOG.md +39 -0
- data/ext/cumo/include/cumo/narray.h +4 -0
- data/ext/cumo/include/cumo/reduce_kernel.h +84 -0
- data/ext/cumo/include/cumo/types/int16.h +5 -2
- data/ext/cumo/include/cumo/types/int32.h +0 -1
- data/ext/cumo/include/cumo/types/int64.h +0 -1
- data/ext/cumo/include/cumo/types/int8.h +1 -2
- data/ext/cumo/include/cumo/types/uint16.h +5 -2
- data/ext/cumo/include/cumo/types/uint32.h +0 -1
- data/ext/cumo/include/cumo/types/uint64.h +0 -1
- data/ext/cumo/include/cumo/types/uint8.h +1 -2
- data/ext/cumo/include/cumo/types/xint_macro.h +2 -0
- data/ext/cumo/include/cumo.h +1 -1
- data/ext/cumo/narray/array.c +18 -24
- data/ext/cumo/narray/data.c +1 -7
- data/ext/cumo/narray/gen/cogen.rb +1 -1
- data/ext/cumo/narray/gen/narray_def.rb +4 -0
- data/ext/cumo/narray/gen/spec.rb +14 -6
- data/ext/cumo/narray/gen/tmpl/accum_arg.c +120 -0
- data/ext/cumo/narray/gen/tmpl/accum_arg_kernel.cu +66 -0
- data/ext/cumo/narray/gen/tmpl/accum_binary.c +4 -0
- data/ext/cumo/narray/gen/tmpl/cast.c +7 -0
- data/ext/cumo/narray/gen/tmpl_bit/binary.c +6 -0
- data/ext/cumo/narray/gen/tmpl_bit/bit_count_cpu.c +6 -0
- data/ext/cumo/narray/gen/tmpl_bit/bit_reduce.c +1 -1
- data/ext/cumo/narray/gen/tmpl_bit/store_bit.c +7 -2
- data/ext/cumo/narray/gen/tmpl_bit/unary.c +4 -0
- data/ext/cumo/narray/index.c +9 -0
- data/ext/cumo/narray/narray.c +2 -2
- data/ext/cumo/narray/ndloop.c +2 -2
- data/lib/cumo/narray/extra.rb +54 -7
- data/test/bit_test.rb +37 -0
- data/test/narray_test.rb +65 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 96a38fa0ad4be223020cef21720e30e9a32fcd2901798279293924df8bfd0f92
|
|
4
|
+
data.tar.gz: c826e49bea46001d6764c7d0f8ad124e5b6072543eb97a07990a26453dd71bf7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1dba1ea3cb5a9c93044d222a9d03c975809c5b03d7925702aa3357a0244752d532cb9421b0632e71808944685c3ca44e7a0fc6032ca8c39d8083c279596dce61
|
|
7
|
+
data.tar.gz: 81c933a8f07f862b22a0c6be5e397000d4ea9476139203353907ba7de21a7aae418264fa8425b197d6302861a2788d262af2d2ecd2e34100900d2293706439f4
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "English"
|
|
3
4
|
require "mkmf"
|
|
4
5
|
require "open3"
|
|
5
6
|
require_relative "nvcc"
|
|
@@ -28,8 +29,10 @@ module MakeMakefileCuda
|
|
|
28
29
|
# private
|
|
29
30
|
|
|
30
31
|
def run_command!(*args)
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
command = args.join(' ')
|
|
33
|
+
puts colorize(:green, command)
|
|
34
|
+
system(command)
|
|
35
|
+
exit($CHILD_STATUS.exitstatus)
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
# TODO(sonots): Make it possible to configure "nvcc" and additional arguments
|
|
@@ -114,7 +114,7 @@ module MakeMakefileCuda
|
|
|
114
114
|
if opt_h["--mkmf-cu-ext"][0] == "c"
|
|
115
115
|
" --compiler-bindir " + ENV.fetch("NVCC_CCBIN", RbConfig::CONFIG["CC"])
|
|
116
116
|
elsif opt_h["--mkmf-cu-ext"][0] == "cxx"
|
|
117
|
-
" --compiler-bindir " + ENV.fetch("NVCC_CCBIN", RbConfig::CONFIG["CXX"])
|
|
117
|
+
" --compiler-bindir " + ENV.fetch("NVCC_CCBIN", RbConfig::CONFIG["CXX"]).split.first
|
|
118
118
|
end
|
|
119
119
|
end
|
|
120
120
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
|
+
# 0.5.5 (2026/07/11)
|
|
2
|
+
|
|
3
|
+
Fixes:
|
|
4
|
+
|
|
5
|
+
* Backport: rename method: min_arg, max_arg => argmin, argmax
|
|
6
|
+
* Backport: fix NArray#concatenate: avoid exception when concatenating empty arrays
|
|
7
|
+
* Backport: fix boolean indexing in each axis
|
|
8
|
+
|
|
9
|
+
# 0.5.4 (2026/05/30)
|
|
10
|
+
|
|
11
|
+
Fixes:
|
|
12
|
+
|
|
13
|
+
* Backport: Fix to use rb_funcallv_kw in Ruby 2.7 and later
|
|
14
|
+
* Backport: define id_pow as "**" for all types except Bit
|
|
15
|
+
* Backport: define id_minus as "-@" for RObject
|
|
16
|
+
* Backport: duplicated id_eq and id_ne for RObject
|
|
17
|
+
* Backport: follow the change of INIT_PTR_BIT_IDX
|
|
18
|
+
* Backport: add test for empty bit array
|
|
19
|
+
* Backport: fix NArray::Bit#count_true/false: empty array should return zero
|
|
20
|
+
* Fix backport error
|
|
21
|
+
* Backport: minor fixes
|
|
22
|
+
* Backport: fix RObject#sum,prod
|
|
23
|
+
* Backport: NArray#from_binary: allow zero dimension
|
|
24
|
+
* Backport: Added test cases
|
|
25
|
+
* Backport: fix NArray#store: drop automatic 'to_a' conversion
|
|
26
|
+
* Backport: Numo::NArray.cast tries to convert to Array when it has to_a method
|
|
27
|
+
* Backport: use rb_respond_to()
|
|
28
|
+
* Backport: improve discrimination between int32/64
|
|
29
|
+
* Backport: missing declaration of id_ge
|
|
30
|
+
* Backport: support casting any object that responds to 'to_a'
|
|
31
|
+
* Backport: fix the range of int32 as -2**31 .. 2**31-1
|
|
32
|
+
* Backport: if int32_max is Bignum, it should be protected from GC
|
|
33
|
+
* fix: handle compiler flags included in RbConfig::CONFIG properly (#157)
|
|
34
|
+
* Backport: Added more percentile tests
|
|
35
|
+
* Backport: Use File.write in cogen to ensure file is closed
|
|
36
|
+
* Backport: Added percentile method
|
|
37
|
+
* Backport: Use INT2FIX to define m_data_to_num for 8 or 16-bit Int.
|
|
38
|
+
* Backport: raise error if compiler does not support 8 or 4-byte integer
|
|
39
|
+
|
|
1
40
|
# 0.5.3 (2026/04/26)
|
|
2
41
|
|
|
3
42
|
Fixes:
|
|
@@ -99,6 +99,8 @@ extern "C" {
|
|
|
99
99
|
# ifndef PRIu64
|
|
100
100
|
# define PRIu64 "llu"
|
|
101
101
|
# endif
|
|
102
|
+
#else
|
|
103
|
+
# error ---->> numo/narray requires 8-byte integer. <<----
|
|
102
104
|
#endif
|
|
103
105
|
|
|
104
106
|
#if SIZEOF_LONG==4
|
|
@@ -139,6 +141,8 @@ extern "C" {
|
|
|
139
141
|
# ifndef PRIu32
|
|
140
142
|
# define PRIu32 "u"
|
|
141
143
|
# endif
|
|
144
|
+
#else
|
|
145
|
+
# error ---->> numo/narray requires 4-byte integer. <<----
|
|
142
146
|
#endif
|
|
143
147
|
|
|
144
148
|
#if SIZEOF_LONG > 4
|
|
@@ -86,6 +86,67 @@ __global__ static void reduction_kernel(cumo_na_reduction_arg_t arg, int out_blo
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
// Variant of reduction_kernel for arg-reductions (argmax/argmin).
|
|
90
|
+
//
|
|
91
|
+
// Unlike reduction_kernel, which passes the flat 1-d index of an input element
|
|
92
|
+
// (i.e. index of input elements, same as (min|max)_index), this passes the
|
|
93
|
+
// index along the reduction axis (i_reduce) to the reduction impl. This matches
|
|
94
|
+
// the spec of arg(min|max) which returns indices along the axis.
|
|
95
|
+
template <typename TypeIn, typename TypeOut, typename ReductionImpl>
|
|
96
|
+
__global__ static void reduction_arg_kernel(cumo_na_reduction_arg_t arg, int out_block_size, int reduce_block_size, ReductionImpl impl) {
|
|
97
|
+
cumo_na_iarray_t& in_iarray = arg.in;
|
|
98
|
+
cumo_na_iarray_t& out_iarray = arg.out;
|
|
99
|
+
cumo_na_indexer_t& in_indexer = arg.in_indexer;
|
|
100
|
+
cumo_na_indexer_t& out_indexer = arg.out_indexer;
|
|
101
|
+
|
|
102
|
+
using TypeReduce = decltype(impl.Identity(0));
|
|
103
|
+
|
|
104
|
+
extern __shared__ __align__(8) char sdata_raw[];
|
|
105
|
+
TypeReduce* sdata = reinterpret_cast<TypeReduce*>(sdata_raw);
|
|
106
|
+
unsigned int tid = threadIdx.x;
|
|
107
|
+
|
|
108
|
+
int64_t reduce_indexer_total_size = in_indexer.total_size / out_indexer.total_size;
|
|
109
|
+
int64_t reduce_offset = tid / out_block_size; // # of cols == # of elems
|
|
110
|
+
|
|
111
|
+
int64_t out_offset = tid % out_block_size; // # of rows
|
|
112
|
+
int64_t out_base = blockIdx.x * out_block_size; // # of rows
|
|
113
|
+
int64_t out_stride = gridDim.x * out_block_size; // # of rows
|
|
114
|
+
|
|
115
|
+
for (int64_t i_out = out_base + out_offset; i_out < out_indexer.total_size; i_out += out_stride) {
|
|
116
|
+
cumo_na_indexer_set_dim(&out_indexer, i_out);
|
|
117
|
+
int64_t i_in = i_out * reduce_indexer_total_size + reduce_offset;
|
|
118
|
+
|
|
119
|
+
// Note that arg(min|max) returns the index along the reduction axis.
|
|
120
|
+
TypeReduce accum = impl.Identity(reduce_offset);
|
|
121
|
+
|
|
122
|
+
for (int64_t i_reduce = reduce_offset; i_reduce < reduce_indexer_total_size; i_reduce += reduce_block_size, i_in += reduce_block_size) {
|
|
123
|
+
cumo_na_indexer_set_dim(&in_indexer, i_in);
|
|
124
|
+
TypeIn* in_ptr = reinterpret_cast<TypeIn*>(cumo_na_iarray_at_dim(&in_iarray, &in_indexer));
|
|
125
|
+
impl.Reduce(impl.MapIn(*in_ptr, i_reduce), accum);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (out_block_size <= max_block_size / 2) {
|
|
129
|
+
sdata[tid] = accum;
|
|
130
|
+
__syncthreads();
|
|
131
|
+
// NOTE: Compiler optimizes to unroll this loop
|
|
132
|
+
for (int stride = max_block_size / 2; stride > 0; stride >>= 1) {
|
|
133
|
+
if (out_block_size <= stride) {
|
|
134
|
+
if (tid < stride) {
|
|
135
|
+
impl.Reduce(sdata[tid + stride], sdata[tid]);
|
|
136
|
+
}
|
|
137
|
+
__syncthreads();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
accum = sdata[tid];
|
|
141
|
+
__syncthreads();
|
|
142
|
+
}
|
|
143
|
+
if (reduce_offset == 0 && i_out < out_indexer.total_size) {
|
|
144
|
+
TypeOut* out_ptr = reinterpret_cast<TypeOut*>(cumo_na_iarray_at_dim(&out_iarray, &out_indexer));
|
|
145
|
+
*out_ptr = impl.MapOut(accum);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
89
150
|
} // cumo_detail
|
|
90
151
|
|
|
91
152
|
// TODO(sonots): Optimize indexer by squashing (or reducing) dimensions
|
|
@@ -110,4 +171,27 @@ void cumo_reduce(cumo_na_reduction_arg_t arg, ReductionImpl&& impl) {
|
|
|
110
171
|
cumo_detail::reduction_kernel<TypeIn,TypeOut,ReductionImpl><<<grid_size, block_size, shared_mem_size>>>(arg, out_block_size, reduce_block_size, impl);
|
|
111
172
|
}
|
|
112
173
|
|
|
174
|
+
// Variant of cumo_reduce for arg-reductions (argmax/argmin), which returns
|
|
175
|
+
// indices along the reduction axis. See reduction_arg_kernel above.
|
|
176
|
+
template <typename TypeIn, typename TypeOut, typename ReductionImpl>
|
|
177
|
+
void cumo_reduce_arg(cumo_na_reduction_arg_t arg, ReductionImpl&& impl) {
|
|
178
|
+
cumo_na_indexer_t& in_indexer = arg.in_indexer;
|
|
179
|
+
cumo_na_indexer_t& out_indexer = arg.out_indexer;
|
|
180
|
+
|
|
181
|
+
if (out_indexer.total_size == 0) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
int64_t reduce_total_size_pow2 = cumo_detail::round_up_to_power_of_2(std::max(size_t{1}, in_indexer.total_size / out_indexer.total_size));
|
|
186
|
+
int64_t reduce_block_size = std::min(cumo_detail::max_block_size, reduce_total_size_pow2);
|
|
187
|
+
int64_t out_block_size = cumo_detail::max_block_size / reduce_block_size;
|
|
188
|
+
int64_t out_block_num = (out_indexer.total_size + out_block_size - 1) / out_block_size;
|
|
189
|
+
|
|
190
|
+
int64_t block_size = cumo_detail::max_block_size;
|
|
191
|
+
int64_t grid_size = std::min(cumo_detail::max_grid_size, out_block_num);
|
|
192
|
+
int64_t shared_mem_size = sizeof(decltype(impl.Identity(0))) * block_size;
|
|
193
|
+
|
|
194
|
+
cumo_detail::reduction_arg_kernel<TypeIn,TypeOut,ReductionImpl><<<grid_size, block_size, shared_mem_size>>>(arg, out_block_size, reduce_block_size, impl);
|
|
195
|
+
}
|
|
196
|
+
|
|
113
197
|
#endif // CUMO_REDUCE_KERNEL_H
|
|
@@ -4,8 +4,11 @@ typedef int16_t rtype;
|
|
|
4
4
|
#define cRT cT
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2INT(x))
|
|
7
|
-
#
|
|
8
|
-
#define
|
|
7
|
+
#if SIZEOF_INT > 2
|
|
8
|
+
#define m_data_to_num(x) INT2FIX(x)
|
|
9
|
+
#else
|
|
10
|
+
#define m_data_to_num(x) INT2NUM(x)
|
|
11
|
+
#endif
|
|
9
12
|
#define m_sprintf(s,x) sprintf(s,"%d",(int)(x))
|
|
10
13
|
|
|
11
14
|
#ifndef INT16_MIN
|
|
@@ -4,8 +4,7 @@ typedef int8_t rtype;
|
|
|
4
4
|
#define cRT cT
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2INT(x))
|
|
7
|
-
#define m_data_to_num(x)
|
|
8
|
-
#define m_extract(x) INT2NUM((int)*(dtype*)(x))
|
|
7
|
+
#define m_data_to_num(x) INT2FIX(x)
|
|
9
8
|
#define m_sprintf(s,x) sprintf(s,"%d",(int)(x))
|
|
10
9
|
|
|
11
10
|
#ifndef INT8_MIN
|
|
@@ -4,8 +4,11 @@ typedef u_int16_t rtype;
|
|
|
4
4
|
#define cRT cT
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2UINT(x))
|
|
7
|
-
#
|
|
8
|
-
#define
|
|
7
|
+
#if SIZEOF_INT > 2
|
|
8
|
+
#define m_data_to_num(x) INT2FIX(x)
|
|
9
|
+
#else
|
|
10
|
+
#define m_data_to_num(x) UINT2NUM(x)
|
|
11
|
+
#endif
|
|
9
12
|
#define m_sprintf(s,x) sprintf(s,"%u",(unsigned int)(x))
|
|
10
13
|
|
|
11
14
|
#ifndef UINT16_MIN
|
|
@@ -5,7 +5,6 @@ typedef u_int32_t rtype;
|
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2UINT32(x))
|
|
7
7
|
#define m_data_to_num(x) UINT322NUM((u_int32_t)(x))
|
|
8
|
-
#define m_extract(x) UINT322NUM((u_int32_t)*(dtype*)(x))
|
|
9
8
|
#define m_sprintf(s,x) sprintf(s,"%"PRIu32,(u_int32_t)(x))
|
|
10
9
|
|
|
11
10
|
#ifndef UINT32_MIN
|
|
@@ -5,7 +5,6 @@ typedef u_int64_t rtype;
|
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2UINT64(x))
|
|
7
7
|
#define m_data_to_num(x) UINT642NUM((u_int64_t)(x))
|
|
8
|
-
#define m_extract(x) UINT642NUM((u_int64_t)*(dtype*)(x))
|
|
9
8
|
#define m_sprintf(s,x) sprintf(s,"%"PRIu64,(u_int64_t)(x))
|
|
10
9
|
|
|
11
10
|
#ifndef UINT64_MIN
|
|
@@ -4,8 +4,7 @@ typedef u_int8_t rtype;
|
|
|
4
4
|
#define cRT cT
|
|
5
5
|
|
|
6
6
|
#define m_num_to_data(x) ((dtype)NUM2UINT(x))
|
|
7
|
-
#define m_data_to_num(x)
|
|
8
|
-
#define m_extract(x) UINT2NUM((unsigned int)*(dtype*)(x))
|
|
7
|
+
#define m_data_to_num(x) INT2FIX(x)
|
|
9
8
|
#define m_sprintf(s,x) sprintf(s,"%u",(unsigned int)(x))
|
|
10
9
|
|
|
11
10
|
#ifndef UINT8_MIN
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#define m_zero 0
|
|
2
2
|
#define m_one 1
|
|
3
3
|
|
|
4
|
+
#define m_extract(x) m_data_to_num(*(dtype*)(x))
|
|
5
|
+
|
|
4
6
|
/* Handle negative values consistently across platforms for unsigned integer types */
|
|
5
7
|
#define m_from_double(x) ((x) < 0 ? (dtype)((long long)(x)) : (dtype)(x))
|
|
6
8
|
#define m_from_real(x) ((x) < 0 ? (dtype)((long long)(x)) : (dtype)(x))
|
data/ext/cumo/include/cumo.h
CHANGED
data/ext/cumo/narray/array.c
CHANGED
|
@@ -25,16 +25,16 @@ static ID cumo_id_step;
|
|
|
25
25
|
static ID cumo_id_abs;
|
|
26
26
|
static ID cumo_id_cast;
|
|
27
27
|
static ID cumo_id_le;
|
|
28
|
+
#if SIZEOF_LONG <= 4
|
|
29
|
+
static ID cumo_id_ge;
|
|
30
|
+
#endif
|
|
28
31
|
static ID cumo_id_Complex;
|
|
29
|
-
|
|
32
|
+
static VALUE cumo_int32_max = Qnil;
|
|
33
|
+
static VALUE cumo_int32_min = Qnil;
|
|
30
34
|
|
|
31
35
|
static VALUE
|
|
32
36
|
cumo_na_object_type(int type, VALUE v)
|
|
33
37
|
{
|
|
34
|
-
static VALUE int32_max = Qnil;
|
|
35
|
-
if (NIL_P(int32_max))
|
|
36
|
-
int32_max = ULONG2NUM(2147483647);
|
|
37
|
-
|
|
38
38
|
switch(TYPE(v)) {
|
|
39
39
|
|
|
40
40
|
case T_TRUE:
|
|
@@ -43,15 +43,15 @@ static VALUE
|
|
|
43
43
|
return CUMO_NA_BIT;
|
|
44
44
|
return type;
|
|
45
45
|
|
|
46
|
-
#if SIZEOF_LONG
|
|
46
|
+
#if SIZEOF_LONG <= 4
|
|
47
47
|
case T_FIXNUM:
|
|
48
48
|
if (type<CUMO_NA_INT32)
|
|
49
49
|
return CUMO_NA_INT32;
|
|
50
50
|
return type;
|
|
51
51
|
case T_BIGNUM:
|
|
52
52
|
if (type<CUMO_NA_INT64) {
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
if (RTEST(rb_funcall(v,cumo_id_le,1,int32_max)) &&
|
|
54
|
+
RTEST(rb_funcall(v,cumo_id_ge,1,int32_min))) {
|
|
55
55
|
if (type<CUMO_NA_INT32)
|
|
56
56
|
return CUMO_NA_INT32;
|
|
57
57
|
} else {
|
|
@@ -59,13 +59,12 @@ static VALUE
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
return type;
|
|
62
|
-
|
|
63
|
-
#elif SIZEOF_LONG == 8
|
|
62
|
+
#else
|
|
64
63
|
case T_FIXNUM:
|
|
65
64
|
if (type<CUMO_NA_INT64) {
|
|
66
65
|
long x = NUM2LONG(v);
|
|
67
66
|
if (x<0) x=-x;
|
|
68
|
-
if (x<=
|
|
67
|
+
if (x<=2147483647L && x>=-2147483648L) {
|
|
69
68
|
if (type<CUMO_NA_INT32)
|
|
70
69
|
return CUMO_NA_INT32;
|
|
71
70
|
} else {
|
|
@@ -77,19 +76,6 @@ static VALUE
|
|
|
77
76
|
if (type<CUMO_NA_INT64)
|
|
78
77
|
return CUMO_NA_INT64;
|
|
79
78
|
return type;
|
|
80
|
-
#else
|
|
81
|
-
case T_FIXNUM:
|
|
82
|
-
case T_BIGNUM:
|
|
83
|
-
if (type<CUMO_NA_INT64) {
|
|
84
|
-
v = rb_funcall(v,cumo_id_abs,0);
|
|
85
|
-
if (RTEST(rb_funcall(v,cumo_id_le,1,int32_max))) {
|
|
86
|
-
if (type<CUMO_NA_INT32)
|
|
87
|
-
return CUMO_NA_INT32;
|
|
88
|
-
} else {
|
|
89
|
-
return CUMO_NA_INT64;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return type;
|
|
93
79
|
#endif
|
|
94
80
|
|
|
95
81
|
case T_FLOAT:
|
|
@@ -642,5 +628,13 @@ Init_cumo_na_array(void)
|
|
|
642
628
|
cumo_id_cast = rb_intern("cast");
|
|
643
629
|
cumo_id_abs = rb_intern("abs");
|
|
644
630
|
cumo_id_le = rb_intern("<=");
|
|
631
|
+
#if SIZEOF_LONG <= 4
|
|
632
|
+
cumo_id_ge = rb_intern(">=");
|
|
633
|
+
#endif
|
|
645
634
|
cumo_id_Complex = rb_intern("Complex");
|
|
635
|
+
|
|
636
|
+
rb_global_variable(&cumo_int32_max);
|
|
637
|
+
cumo_int32_max = INT2NUM(2147483647);
|
|
638
|
+
rb_global_variable(&cumo_int32_min);
|
|
639
|
+
cumo_int32_min = INT2NUM(-2147483648);
|
|
646
640
|
}
|
data/ext/cumo/narray/data.c
CHANGED
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
#include "cumo/narray.h"
|
|
6
6
|
#include "cumo/template.h"
|
|
7
7
|
|
|
8
|
-
static VALUE cumo_sym_mulsum;
|
|
9
8
|
static ID cumo_id_mulsum;
|
|
10
|
-
static ID cumo_id_respond_to_p;
|
|
11
9
|
static ID cumo_id_store;
|
|
12
10
|
static ID cumo_id_swap_byte;
|
|
13
11
|
|
|
@@ -932,12 +930,10 @@ cumo_na_new_dimension_for_dot(VALUE self, int pos, int len, bool transpose)
|
|
|
932
930
|
static VALUE
|
|
933
931
|
cumo_na_dot(VALUE self, VALUE other)
|
|
934
932
|
{
|
|
935
|
-
VALUE test;
|
|
936
933
|
volatile VALUE a1=self, a2=other;
|
|
937
934
|
cumo_narray_t *na1, *na2;
|
|
938
935
|
|
|
939
|
-
|
|
940
|
-
if (!RTEST(test)) {
|
|
936
|
+
if (!rb_respond_to(a1, cumo_id_mulsum)) {
|
|
941
937
|
rb_raise(rb_eNoMethodError,"requires mulsum method for dot method");
|
|
942
938
|
}
|
|
943
939
|
CumoGetNArray(a1,na1);
|
|
@@ -994,8 +990,6 @@ Init_cumo_na_data(void)
|
|
|
994
990
|
//rb_define_method(cNArray, "dot", cumo_na_dot, 1);
|
|
995
991
|
|
|
996
992
|
cumo_id_mulsum = rb_intern("mulsum");
|
|
997
|
-
cumo_sym_mulsum = ID2SYM(cumo_id_mulsum);
|
|
998
|
-
cumo_id_respond_to_p = rb_intern("respond_to?");
|
|
999
993
|
cumo_id_store = rb_intern("store");
|
|
1000
994
|
cumo_id_swap_byte = rb_intern("swap_byte");
|
|
1001
995
|
}
|
data/ext/cumo/narray/gen/spec.rb
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
def_id "cast"
|
|
4
|
-
def_id "eq"
|
|
5
|
-
def_id "ne"
|
|
6
|
-
def_id "pow"
|
|
7
4
|
def_id "mulsum"
|
|
5
|
+
def_id "to_a"
|
|
8
6
|
if is_complex
|
|
9
7
|
def_id "real"
|
|
10
8
|
def_id "imag"
|
|
@@ -34,7 +32,6 @@ if is_object
|
|
|
34
32
|
def_id "bit_xor"
|
|
35
33
|
def_id "bit_not"
|
|
36
34
|
def_id "abs"
|
|
37
|
-
def_id "minus"
|
|
38
35
|
def_id "reciprocal"
|
|
39
36
|
def_id "square"
|
|
40
37
|
def_id "floor"
|
|
@@ -44,6 +41,7 @@ if is_object
|
|
|
44
41
|
def_id "nan?"
|
|
45
42
|
def_id "infinite?"
|
|
46
43
|
def_id "finite?"
|
|
44
|
+
def_id "-@", "minus"
|
|
47
45
|
def_id "==", "eq"
|
|
48
46
|
def_id "!=", "ne"
|
|
49
47
|
def_id ">" , "gt"
|
|
@@ -51,6 +49,9 @@ if is_object
|
|
|
51
49
|
def_id "<" , "lt"
|
|
52
50
|
def_id "<=", "le"
|
|
53
51
|
def_id "<=>", "ufo"
|
|
52
|
+
else
|
|
53
|
+
def_id "eq"
|
|
54
|
+
def_id "ne"
|
|
54
55
|
end
|
|
55
56
|
if (is_float || is_complex) && !is_object
|
|
56
57
|
def_id "gemm"
|
|
@@ -203,7 +204,12 @@ if !is_complex
|
|
|
203
204
|
binary2 "divmod"
|
|
204
205
|
end
|
|
205
206
|
|
|
206
|
-
|
|
207
|
+
|
|
208
|
+
if !is_bit
|
|
209
|
+
pow
|
|
210
|
+
def_id "**","pow"
|
|
211
|
+
def_alias "pow","**"
|
|
212
|
+
end
|
|
207
213
|
|
|
208
214
|
unary "minus", "-@"
|
|
209
215
|
unary "reciprocal"
|
|
@@ -297,7 +303,7 @@ if is_float
|
|
|
297
303
|
cond_unary "isfinite"
|
|
298
304
|
end
|
|
299
305
|
|
|
300
|
-
if is_int
|
|
306
|
+
if is_int && !is_object
|
|
301
307
|
if is_unsigned
|
|
302
308
|
accum "sum", "u_int64_t", "cumo_cUInt64"
|
|
303
309
|
accum "prod", "u_int64_t", "cumo_cUInt64"
|
|
@@ -327,6 +333,8 @@ if is_comparable
|
|
|
327
333
|
accum "ptp", "dtype", "cT"
|
|
328
334
|
accum_index "max_index"
|
|
329
335
|
accum_index "min_index"
|
|
336
|
+
accum_arg "argmax"
|
|
337
|
+
accum_arg "argmin"
|
|
330
338
|
def_method "minmax"
|
|
331
339
|
def_module_function "maximum", "ewcomp", n_arg:2
|
|
332
340
|
def_module_function "minimum", "ewcomp", n_arg:2
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<% (is_float ? ["","_nan"] : [""]).each do |nan| %>
|
|
2
|
+
|
|
3
|
+
<% [64,32].each do |i| %>
|
|
4
|
+
<% unless type_name == 'robject' %>
|
|
5
|
+
void cumo_<%=type_name%>_<%=name%>_int<%=i%>_kernel_launch(cumo_na_reduction_arg_t* arg);
|
|
6
|
+
<% end %>
|
|
7
|
+
|
|
8
|
+
#define idx_t int<%=i%>_t
|
|
9
|
+
static void
|
|
10
|
+
<%=c_iter%>_arg<%=i%><%=nan%>(cumo_na_loop_t *const lp)
|
|
11
|
+
{
|
|
12
|
+
// TODO(sonots): Support nan in CUDA
|
|
13
|
+
<% if type_name == 'robject' || nan == '_nan' %>
|
|
14
|
+
{
|
|
15
|
+
size_t n, idx;
|
|
16
|
+
char *d_ptr, *o_ptr;
|
|
17
|
+
ssize_t d_step;
|
|
18
|
+
|
|
19
|
+
CUMO_INIT_COUNTER(lp, n);
|
|
20
|
+
CUMO_INIT_PTR(lp, 0, d_ptr, d_step);
|
|
21
|
+
o_ptr = CUMO_NDL_PTR(lp,1);
|
|
22
|
+
|
|
23
|
+
CUMO_SHOW_SYNCHRONIZE_FIXME_WARNING_ONCE("<%=name%><%=nan%>", "<%=type_name%>");
|
|
24
|
+
idx = f_<%=name[3..5]%>_index<%=nan%>(n,d_ptr,d_step);
|
|
25
|
+
*(idx_t*)o_ptr = (idx_t)idx;
|
|
26
|
+
}
|
|
27
|
+
<% else %>
|
|
28
|
+
{
|
|
29
|
+
cumo_na_reduction_arg_t arg = cumo_na_make_reduction_arg(lp);
|
|
30
|
+
cumo_<%=type_name%>_<%=name%>_int<%=i%>_kernel_launch(&arg);
|
|
31
|
+
}
|
|
32
|
+
<% end %>
|
|
33
|
+
}
|
|
34
|
+
#undef idx_t
|
|
35
|
+
<% end;end %>
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
<%=name%>. Returns an index of the <%=name[3..5]%>imum value along the axis. See also `<%=name[3..5]%>_index`.
|
|
39
|
+
<% if is_float %>
|
|
40
|
+
@overload <%=name%>(axis:nil, nan:false)
|
|
41
|
+
@param [TrueClass] nan If true, apply NaN-aware algorithm (return NaN posision if exist).
|
|
42
|
+
<% else %>
|
|
43
|
+
@overload <%=name%>(axis:nil)
|
|
44
|
+
<% end %>
|
|
45
|
+
@param [Numeric,Array,Range] axis Finds <%=name[3..5]%>imum values along the axis and returns indices along the axis.
|
|
46
|
+
@return [Integer,Cumo::Int] returns result indices.
|
|
47
|
+
@example
|
|
48
|
+
Cumo::NArray[3,4,1,2].<%=name%> => <% if name == 'argmin' %>2<% else %>1<% end %>
|
|
49
|
+
*/
|
|
50
|
+
static VALUE
|
|
51
|
+
<%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
|
|
52
|
+
{
|
|
53
|
+
<% if type_name == 'robject' %>
|
|
54
|
+
{
|
|
55
|
+
cumo_narray_t *na;
|
|
56
|
+
VALUE reduce;
|
|
57
|
+
cumo_ndfunc_arg_in_t ain[2] = {{Qnil,0},{cumo_sym_reduce,0}};
|
|
58
|
+
cumo_ndfunc_arg_out_t aout[1] = {{0,0,0}};
|
|
59
|
+
cumo_ndfunc_t ndf = {0, CUMO_STRIDE_LOOP_NIP|CUMO_NDF_FLAT_REDUCE|CUMO_NDF_EXTRACT, 2,1, ain,aout};
|
|
60
|
+
|
|
61
|
+
CumoGetNArray(self,na);
|
|
62
|
+
if (na->ndim==0) {
|
|
63
|
+
return INT2FIX(0);
|
|
64
|
+
}
|
|
65
|
+
if (na->size > (~(u_int32_t)0)) {
|
|
66
|
+
aout[0].type = cumo_cInt64;
|
|
67
|
+
ndf.func = <%=c_iter%>_arg64;
|
|
68
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
69
|
+
} else {
|
|
70
|
+
aout[0].type = cumo_cInt32;
|
|
71
|
+
ndf.func = <%=c_iter%>_arg32;
|
|
72
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return cumo_na_ndloop(&ndf, 2, self, reduce);
|
|
76
|
+
}
|
|
77
|
+
<% else %>
|
|
78
|
+
{
|
|
79
|
+
cumo_narray_t *na;
|
|
80
|
+
VALUE reduce, ret;
|
|
81
|
+
cumo_ndfunc_arg_in_t ain[2] = {{Qnil,0},{cumo_sym_reduce,0}};
|
|
82
|
+
cumo_ndfunc_arg_out_t aout[1] = {{0,0,0}};
|
|
83
|
+
cumo_ndfunc_t ndf = {0, CUMO_STRIDE_LOOP_NIP|CUMO_NDF_FLAT_REDUCE|CUMO_NDF_EXTRACT|CUMO_NDF_INDEXER_LOOP, 2,1, ain,aout};
|
|
84
|
+
|
|
85
|
+
CumoGetNArray(self,na);
|
|
86
|
+
if (na->ndim==0) {
|
|
87
|
+
return INT2FIX(0);
|
|
88
|
+
}
|
|
89
|
+
if (na->size > (~(u_int32_t)0)) {
|
|
90
|
+
aout[0].type = cumo_cInt64;
|
|
91
|
+
ndf.func = <%=c_iter%>_arg64;
|
|
92
|
+
<% if is_float %>
|
|
93
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, <%=c_iter%>_arg64_nan);
|
|
94
|
+
<% else %>
|
|
95
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
96
|
+
<% end %>
|
|
97
|
+
} else {
|
|
98
|
+
aout[0].type = cumo_cInt32;
|
|
99
|
+
ndf.func = <%=c_iter%>_arg32;
|
|
100
|
+
<% if is_float %>
|
|
101
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, <%=c_iter%>_arg32_nan);
|
|
102
|
+
<% else %>
|
|
103
|
+
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
104
|
+
<% end %>
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (cumo_na_has_idx_p(self)) {
|
|
108
|
+
VALUE copy = cumo_na_copy(self); // reduction does not support idx, make contiguous
|
|
109
|
+
ret = cumo_na_ndloop(&ndf, 2, copy, reduce);
|
|
110
|
+
} else {
|
|
111
|
+
ret = cumo_na_ndloop(&ndf, 2, self, reduce);
|
|
112
|
+
}
|
|
113
|
+
if (cumo_compatible_mode_enabled_p()) {
|
|
114
|
+
return rb_funcall(ret, rb_intern("extract_cpu"), 0);
|
|
115
|
+
} else {
|
|
116
|
+
return ret;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
<% end %>
|
|
120
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<% unless defined?($cumo_narray_gen_tmpl_accum_arg_kernel_included) %>
|
|
2
|
+
<% $cumo_narray_gen_tmpl_accum_arg_kernel_included = 1 %>
|
|
3
|
+
<% unless type_name == 'robject' %>
|
|
4
|
+
|
|
5
|
+
<% [64,32].each do |i| %>
|
|
6
|
+
#define idx_t int<%=i%>_t
|
|
7
|
+
|
|
8
|
+
#if defined(__cplusplus)
|
|
9
|
+
#if 0
|
|
10
|
+
{ /* satisfy cc-mode */
|
|
11
|
+
#endif
|
|
12
|
+
} /* extern "C" { */
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
struct cumo_<%=type_name%>_argmin_int<%=i%>_impl {
|
|
16
|
+
struct MinAndArgMin {
|
|
17
|
+
dtype min;
|
|
18
|
+
idx_t argmin;
|
|
19
|
+
};
|
|
20
|
+
__device__ MinAndArgMin Identity(idx_t index) { return {DATA_MAX, index}; }
|
|
21
|
+
__device__ MinAndArgMin MapIn(dtype in, idx_t index) { return {in, index}; }
|
|
22
|
+
__device__ void Reduce(MinAndArgMin next, MinAndArgMin& accum) {
|
|
23
|
+
if (accum.min > next.min) {
|
|
24
|
+
accum = next;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
__device__ idx_t MapOut(MinAndArgMin accum) { return accum.argmin; }
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
struct cumo_<%=type_name%>_argmax_int<%=i%>_impl {
|
|
31
|
+
struct MaxAndArgMax {
|
|
32
|
+
dtype max;
|
|
33
|
+
idx_t argmax;
|
|
34
|
+
};
|
|
35
|
+
__device__ MaxAndArgMax Identity(idx_t index) { return {DATA_MIN, index}; }
|
|
36
|
+
__device__ MaxAndArgMax MapIn(dtype in, idx_t index) { return {in, index}; }
|
|
37
|
+
__device__ void Reduce(MaxAndArgMax next, MaxAndArgMax& accum) {
|
|
38
|
+
if (accum.max < next.max) {
|
|
39
|
+
accum = next;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
__device__ idx_t MapOut(MaxAndArgMax accum) { return accum.argmax; }
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
#if defined(__cplusplus)
|
|
46
|
+
extern "C" {
|
|
47
|
+
#if 0
|
|
48
|
+
} /* satisfy cc-mode */
|
|
49
|
+
#endif
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
void cumo_<%=type_name%>_argmin_int<%=i%>_kernel_launch(cumo_na_reduction_arg_t* arg)
|
|
53
|
+
{
|
|
54
|
+
cumo_reduce_arg<dtype, idx_t, cumo_<%=type_name%>_argmin_int<%=i%>_impl>(*arg, cumo_<%=type_name%>_argmin_int<%=i%>_impl{});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void cumo_<%=type_name%>_argmax_int<%=i%>_kernel_launch(cumo_na_reduction_arg_t* arg)
|
|
58
|
+
{
|
|
59
|
+
cumo_reduce_arg<dtype, idx_t, cumo_<%=type_name%>_argmax_int<%=i%>_impl>(*arg, cumo_<%=type_name%>_argmax_int<%=i%>_impl{});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#undef idx_t
|
|
63
|
+
<% end %>
|
|
64
|
+
|
|
65
|
+
<% end %>
|
|
66
|
+
<% end %>
|
|
@@ -115,7 +115,11 @@ static VALUE
|
|
|
115
115
|
return <%=c_func%>_self(argc, argv, self);
|
|
116
116
|
} else {
|
|
117
117
|
v = rb_funcall(klass, cumo_id_cast, 1, self);
|
|
118
|
+
//<% if Gem::Version.create(RUBY_VERSION) < Gem::Version.create('2.7.0') %>
|
|
118
119
|
return rb_funcall2(v, rb_intern("<%=name%>"), argc, argv);
|
|
120
|
+
//<% else %>
|
|
121
|
+
return rb_funcallv_kw(v, rb_intern("<%=name%>"), argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
122
|
+
//<% end %>
|
|
119
123
|
}
|
|
120
124
|
//<% end %>
|
|
121
125
|
}
|
|
@@ -35,6 +35,13 @@ static VALUE
|
|
|
35
35
|
}
|
|
36
36
|
return v;
|
|
37
37
|
}
|
|
38
|
+
if (rb_respond_to(obj,cumo_id_to_a)) {
|
|
39
|
+
obj = rb_funcall(obj,cumo_id_to_a,0);
|
|
40
|
+
if (TYPE(obj)!=T_ARRAY) {
|
|
41
|
+
rb_raise(rb_eTypeError, "`to_a' did not return Array");
|
|
42
|
+
}
|
|
43
|
+
return <%=find_tmpl("cast_array").c_func%>(obj);
|
|
44
|
+
}
|
|
38
45
|
<% if is_object %>
|
|
39
46
|
return robject_new_dim0(obj);
|
|
40
47
|
<% else %>
|
|
@@ -78,10 +78,16 @@ static VALUE
|
|
|
78
78
|
<%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
|
|
79
79
|
{
|
|
80
80
|
VALUE v, reduce;
|
|
81
|
+
cumo_narray_t *na;
|
|
82
|
+
|
|
81
83
|
cumo_ndfunc_arg_in_t ain[3] = {{cT,0},{cumo_sym_reduce,0},{cumo_sym_init,0}};
|
|
82
84
|
cumo_ndfunc_arg_out_t aout[1] = {{cumo_cInt64,0}};
|
|
83
85
|
cumo_ndfunc_t ndf = { <%=c_iter%>, CUMO_FULL_LOOP_NIP, 3, 1, ain, aout };
|
|
84
86
|
|
|
87
|
+
CumoGetNArray(self,na);
|
|
88
|
+
if (CUMO_NA_SIZE(na)==0) {
|
|
89
|
+
return INT2FIX(0);
|
|
90
|
+
}
|
|
85
91
|
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
86
92
|
v = cumo_na_ndloop(&ndf, 3, self, reduce, INT2FIX(0));
|
|
87
93
|
return rb_funcall(v,rb_intern("extract_cpu"),0);
|
|
@@ -118,7 +118,7 @@ static VALUE
|
|
|
118
118
|
|
|
119
119
|
CumoGetNArray(self,na);
|
|
120
120
|
if (CUMO_NA_SIZE(na)==0) {
|
|
121
|
-
return
|
|
121
|
+
return Qfalse;
|
|
122
122
|
}
|
|
123
123
|
reduce = cumo_na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
|
|
124
124
|
v = cumo_na_ndloop(&ndf, 3, self, reduce, INT2FIX(<%=init_bit%>));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
1
2
|
static void
|
|
2
3
|
<%=c_iter%>(cumo_na_loop_t *const lp)
|
|
3
4
|
{
|
|
4
5
|
size_t n;
|
|
5
|
-
|
|
6
|
+
ssize_t p1, p3;
|
|
6
7
|
ssize_t s1, s3;
|
|
7
8
|
size_t *idx1, *idx3;
|
|
8
9
|
int o1, l1, r1, len;
|
|
@@ -22,6 +23,10 @@ static void
|
|
|
22
23
|
CUMO_STORE_BIT_STEP(a3, p3, s3, idx3, x);
|
|
23
24
|
}
|
|
24
25
|
} else {
|
|
26
|
+
a1 += p1/CUMO_NB;
|
|
27
|
+
p1 %= CUMO_NB;
|
|
28
|
+
a3 += p3/CUMO_NB;
|
|
29
|
+
p3 %= CUMO_NB;
|
|
25
30
|
o1 = p1-p3;
|
|
26
31
|
l1 = CUMO_NB+o1;
|
|
27
32
|
r1 = CUMO_NB-o1;
|
|
@@ -30,7 +35,7 @@ static void
|
|
|
30
35
|
if ((int)n<len) len=n;
|
|
31
36
|
if (o1>=0) x = *a1>>o1;
|
|
32
37
|
else x = *a1<<-o1;
|
|
33
|
-
if (p1+len>CUMO_NB) x |= *(a1+1)<<r1;
|
|
38
|
+
if (p1+len>(ssize_t)CUMO_NB) x |= *(a1+1)<<r1;
|
|
34
39
|
a1++;
|
|
35
40
|
*a3 = (x & (CUMO_SLB(len)<<p3)) | (*a3 & ~(CUMO_SLB(len)<<p3));
|
|
36
41
|
a3++;
|
data/ext/cumo/narray/index.c
CHANGED
|
@@ -63,6 +63,7 @@ static ID cumo_id_dup;
|
|
|
63
63
|
static ID cumo_id_bracket;
|
|
64
64
|
static ID cumo_id_shift_left;
|
|
65
65
|
static ID cumo_id_mask;
|
|
66
|
+
static ID cumo_id_where;
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
static void
|
|
@@ -159,6 +160,13 @@ cumo_na_parse_narray_index(VALUE a, int orig_dim, ssize_t size, cumo_na_index_ar
|
|
|
159
160
|
if (CUMO_NA_NDIM(na) != 1) {
|
|
160
161
|
rb_raise(rb_eIndexError, "should be 1-d NArray");
|
|
161
162
|
}
|
|
163
|
+
if (rb_obj_class(a) == cumo_cBit) {
|
|
164
|
+
if (CUMO_NA_SIZE(na) != (size_t)size) {
|
|
165
|
+
rb_raise(rb_eIndexError, "Bit-NArray size mismatch");
|
|
166
|
+
}
|
|
167
|
+
a = rb_funcall(a, cumo_id_where, 0);
|
|
168
|
+
CumoGetNArray(a,na);
|
|
169
|
+
}
|
|
162
170
|
n = CUMO_NA_SIZE(na);
|
|
163
171
|
idx = cumo_na_new(cIndex,1,&n);
|
|
164
172
|
cumo_na_store(idx,a);
|
|
@@ -1138,4 +1146,5 @@ Init_cumo_na_index()
|
|
|
1138
1146
|
cumo_id_bracket = rb_intern("[]");
|
|
1139
1147
|
cumo_id_shift_left = rb_intern("<<");
|
|
1140
1148
|
cumo_id_mask = rb_intern("mask");
|
|
1149
|
+
cumo_id_where = rb_intern("where");
|
|
1141
1150
|
}
|
data/ext/cumo/narray/narray.c
CHANGED
|
@@ -1346,8 +1346,8 @@ cumo_na_s_from_binary(int argc, VALUE *argv, VALUE type)
|
|
|
1346
1346
|
break;
|
|
1347
1347
|
case T_ARRAY:
|
|
1348
1348
|
nd = RARRAY_LEN(vshape);
|
|
1349
|
-
if (nd
|
|
1350
|
-
|
|
1349
|
+
if (nd > CUMO_NA_MAX_DIMENSION) {
|
|
1350
|
+
rb_raise(cumo_na_eDimensionError,"shape exceeds max dimension");
|
|
1351
1351
|
}
|
|
1352
1352
|
shape = ALLOCA_N(size_t,nd);
|
|
1353
1353
|
len = 1;
|
data/ext/cumo/narray/ndloop.c
CHANGED
|
@@ -164,7 +164,7 @@ print_ndloop(cumo_na_md_loop_t *lp) {
|
|
|
164
164
|
for (i=0; i<lp->user.ndim; i++) {
|
|
165
165
|
printf(" &user.args[%d].iter[%d] = 0x%"SZF"x\n", j,i, (size_t)&lp->user.args[j].iter[i]);
|
|
166
166
|
printf(" user.args[%d].iter[%d].pos = %"SZF"u\n", j,i, lp->user.args[j].iter[i].pos);
|
|
167
|
-
printf(" user.args[%d].iter[%d].step = %"SZF"
|
|
167
|
+
printf(" user.args[%d].iter[%d].step = %"SZF"d\n", j,i, lp->user.args[j].iter[i].step);
|
|
168
168
|
printf(" user.args[%d].iter[%d].idx = 0x%"SZF"x (cuda:%d)\n", j,i, (size_t)lp->user.args[j].iter[i].idx, cumo_cuda_runtime_is_device_memory(lp->user.args[j].iter[i].idx));
|
|
169
169
|
// printf(" user.args[%d].iter[%d].idx = 0x%"SZF"x\n", j,i, (size_t)lp->user.args[j].iter[i].idx);
|
|
170
170
|
}
|
|
@@ -175,7 +175,7 @@ print_ndloop(cumo_na_md_loop_t *lp) {
|
|
|
175
175
|
for (i=0; i<=nd; i++) {
|
|
176
176
|
printf(" &xargs[%d].iter[%d] = 0x%"SZF"x\n", j,i, (size_t)&LITER(lp,i,j));
|
|
177
177
|
printf(" xargs[%d].iter[%d].pos = %"SZF"u\n", j,i, LITER(lp,i,j).pos);
|
|
178
|
-
printf(" xargs[%d].iter[%d].step = %"SZF"
|
|
178
|
+
printf(" xargs[%d].iter[%d].step = %"SZF"d\n", j,i, LITER(lp,i,j).step);
|
|
179
179
|
printf(" xargs[%d].iter[%d].idx = 0x%"SZF"x (cuda:%d)\n", j,i, (size_t)LITER(lp,i,j).idx, cumo_cuda_runtime_is_device_memory(LITER(lp,i,j).idx));
|
|
180
180
|
// printf(" xargs[%d].iter[%d].idx = 0x%"SZF"x\n", j,i, (size_t)LITER(lp,i,j).idx);
|
|
181
181
|
}
|
data/lib/cumo/narray/extra.rb
CHANGED
|
@@ -108,7 +108,19 @@ module Cumo
|
|
|
108
108
|
|
|
109
109
|
# Convert the argument to an narray if not an narray.
|
|
110
110
|
def self.cast(a)
|
|
111
|
-
|
|
111
|
+
case a
|
|
112
|
+
when NArray
|
|
113
|
+
a
|
|
114
|
+
when Array,Numeric
|
|
115
|
+
NArray.array_type(a).cast(a)
|
|
116
|
+
else
|
|
117
|
+
if a.respond_to?(:to_a)
|
|
118
|
+
a = a.to_a
|
|
119
|
+
NArray.array_type(a).cast(a)
|
|
120
|
+
else
|
|
121
|
+
raise TypeError,"invalid type for NArray"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
112
124
|
end
|
|
113
125
|
|
|
114
126
|
def self.asarray(a)
|
|
@@ -461,8 +473,10 @@ module Cumo
|
|
|
461
473
|
arrays.each do |a|
|
|
462
474
|
fst = lst
|
|
463
475
|
lst = fst + (a.shape[axis - nd] || 1)
|
|
464
|
-
|
|
465
|
-
|
|
476
|
+
if lst > fst
|
|
477
|
+
refs[axis] = fst...lst
|
|
478
|
+
result[*refs] = a
|
|
479
|
+
end
|
|
466
480
|
end
|
|
467
481
|
result
|
|
468
482
|
end
|
|
@@ -642,13 +656,17 @@ module Cumo
|
|
|
642
656
|
result = self.class.zeros(*self_shape)
|
|
643
657
|
lst = shape[axis]
|
|
644
658
|
refs = [true] * ndim
|
|
645
|
-
|
|
646
|
-
|
|
659
|
+
if lst > 0
|
|
660
|
+
refs[axis] = 0...lst
|
|
661
|
+
result[*refs] = self
|
|
662
|
+
end
|
|
647
663
|
arrays.each do |a|
|
|
648
664
|
fst = lst
|
|
649
665
|
lst = fst + (a.shape[axis - ndim] || 1)
|
|
650
|
-
|
|
651
|
-
|
|
666
|
+
if lst > fst
|
|
667
|
+
refs[axis] = fst...lst
|
|
668
|
+
result[*refs] = a
|
|
669
|
+
end
|
|
652
670
|
end
|
|
653
671
|
result
|
|
654
672
|
end
|
|
@@ -1186,6 +1204,35 @@ module Cumo
|
|
|
1186
1204
|
end
|
|
1187
1205
|
end
|
|
1188
1206
|
|
|
1207
|
+
# Percentile
|
|
1208
|
+
#
|
|
1209
|
+
# @param q [Numo::NArray]
|
|
1210
|
+
# @param axis [Integer] applied axis
|
|
1211
|
+
# @return [Numo::NArray] return percentile
|
|
1212
|
+
def percentile(q, axis: nil)
|
|
1213
|
+
raise ArgumentError, "q is out of range" if q < 0 || q > 100
|
|
1214
|
+
|
|
1215
|
+
x = self
|
|
1216
|
+
unless axis
|
|
1217
|
+
axis = 0
|
|
1218
|
+
x = x.flatten
|
|
1219
|
+
end
|
|
1220
|
+
|
|
1221
|
+
sorted = x.sort(axis: axis)
|
|
1222
|
+
x = q / 100.0 * (sorted.shape[axis] - 1)
|
|
1223
|
+
r = x % 1
|
|
1224
|
+
i = x.floor
|
|
1225
|
+
refs = [true] * sorted.ndim
|
|
1226
|
+
refs[axis] = i
|
|
1227
|
+
if i == sorted.shape[axis] - 1
|
|
1228
|
+
sorted[*refs]
|
|
1229
|
+
else
|
|
1230
|
+
refs_upper = refs.dup
|
|
1231
|
+
refs_upper[axis] = i + 1
|
|
1232
|
+
sorted[*refs] + r * (sorted[*refs_upper] - sorted[*refs])
|
|
1233
|
+
end
|
|
1234
|
+
end
|
|
1235
|
+
|
|
1189
1236
|
# Kronecker product of two arrays.
|
|
1190
1237
|
#
|
|
1191
1238
|
# kron(a,b)[k_0, k_1, ...] = a[i_0, i_1, ...] * b[j_0, j_1, ...]
|
data/test/bit_test.rb
CHANGED
|
@@ -139,6 +139,37 @@ class BitTest < Test::Unit::TestCase
|
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
+
procs = [
|
|
143
|
+
[proc{|tp,a| tp[*a] },""],
|
|
144
|
+
]
|
|
145
|
+
procs.each do |init, ref|
|
|
146
|
+
|
|
147
|
+
test "#{dtype},[]#{ref}" do
|
|
148
|
+
src = []
|
|
149
|
+
n = src.size
|
|
150
|
+
a = init.call(dtype, src)
|
|
151
|
+
|
|
152
|
+
assert { a == src }
|
|
153
|
+
assert { (a & 0) == [0] * n }
|
|
154
|
+
assert { (a & 1) == src }
|
|
155
|
+
assert { (a | 0) == src }
|
|
156
|
+
assert { (a | 1) == [1] * n }
|
|
157
|
+
assert { (a ^ 0) == src.map {|x| x ^ 0 } }
|
|
158
|
+
assert { (a ^ 1) == src.map {|x| x ^ 1 } }
|
|
159
|
+
assert { ~a == src.map {|x| 1 - x } }
|
|
160
|
+
|
|
161
|
+
assert { a.count_true == 0 }
|
|
162
|
+
assert { a.count_false == 0 }
|
|
163
|
+
assert { a.where == [] }
|
|
164
|
+
assert { a.where2 == [[], []] }
|
|
165
|
+
assert { a.mask(Cumo::DFloat[]) == [] }
|
|
166
|
+
assert { !a.all? }
|
|
167
|
+
assert { !a.any? }
|
|
168
|
+
assert { a.none? }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
end
|
|
172
|
+
|
|
142
173
|
test "store to view" do
|
|
143
174
|
n = 14
|
|
144
175
|
x = Cumo::Bit.zeros(n + 2, n + 2, 3)
|
|
@@ -154,4 +185,10 @@ class BitTest < Test::Unit::TestCase
|
|
|
154
185
|
assert { (~y[1..-2, 1..-2, 0]).where.size == 0 }
|
|
155
186
|
assert { y[true, true, 1].where.size == 0 }
|
|
156
187
|
end
|
|
188
|
+
|
|
189
|
+
test "assign nil" do
|
|
190
|
+
x = Cumo::RObject.cast([1, 2, 3])
|
|
191
|
+
x[Cumo::Bit.cast([0, 1, 0])] = nil
|
|
192
|
+
assert { x.to_a == [1, nil, 3] }
|
|
193
|
+
end
|
|
157
194
|
end
|
data/test/narray_test.rb
CHANGED
|
@@ -344,13 +344,35 @@ class NArrayTest < Test::Unit::TestCase
|
|
|
344
344
|
assert { a.min_index(axis: 0) == [0, 1, 2] }
|
|
345
345
|
assert { a.max_index(axis: 1) == [2, 5] }
|
|
346
346
|
assert { a.max_index(axis: 0) == [3, 4, 5] }
|
|
347
|
+
assert { a.argmin == 0 }
|
|
348
|
+
assert { a.argmax == 5 }
|
|
349
|
+
assert { a.argmin(axis: 1) == [0, 0] }
|
|
350
|
+
assert { a.argmin(axis: 0) == [0, 0, 0] }
|
|
351
|
+
assert { a.argmax(axis: 1) == [2, 2] }
|
|
352
|
+
assert { a.argmax(axis: 0) == [1, 1, 1] }
|
|
347
353
|
assert { (a >= 3) == [[0, 0, 1], [1, 1, 1]] }
|
|
348
354
|
assert { (a > 3) == [[0, 0, 0], [1, 1, 1]] }
|
|
349
355
|
assert { (a <= 3) == [[1, 1, 1], [0, 0, 0]] }
|
|
350
356
|
assert { (a < 3) == [[1, 1, 0], [0, 0, 0]] }
|
|
351
357
|
assert { (a.eq 3) == [[0, 0, 1], [0, 0, 0]] }
|
|
358
|
+
assert { a[a.ne 3] == [1, 2, 5, 7, 11] }
|
|
359
|
+
assert { a[a[true, 2] < 5, true] == [[1, 2, 3]] }
|
|
360
|
+
assert { a[true, a[1, true] > 5] == [[2, 3], [7, 11]] }
|
|
361
|
+
assert { a[:*, (a[0, :*] % 2).eq(1)] == [[1, 3], [5, 11]] }
|
|
352
362
|
assert { a.sort == src }
|
|
353
363
|
assert { a.sort_index == [[0, 1, 2], [3, 4, 5]] }
|
|
364
|
+
assert { a.percentile(0) == 1.0 }
|
|
365
|
+
assert { a.percentile(50) == 4.0 }
|
|
366
|
+
assert { a.percentile(90) == 9.0 }
|
|
367
|
+
assert { a.percentile(100) == 11.0 }
|
|
368
|
+
assert { a.percentile(0, axis: 0) == [1, 2, 3] }
|
|
369
|
+
assert { a.percentile(50, axis: 0) == [3, 4.5, 7] }
|
|
370
|
+
assert { a.percentile(90, axis: 0) == [4.6, 6.5, 10.2] }
|
|
371
|
+
assert { a.percentile(100, axis: 0) == [5, 7, 11] }
|
|
372
|
+
assert { a.percentile(0, axis: 1) == [1, 5] }
|
|
373
|
+
assert { a.percentile(50, axis: 1) == [2, 7] }
|
|
374
|
+
assert { a.percentile(90, axis: 1) == [2.8, 10.2] }
|
|
375
|
+
assert { a.percentile(100, axis: 1) == [3, 11] }
|
|
354
376
|
end
|
|
355
377
|
assert { a.dup.fill(12) == [[12] * 3] * 2 }
|
|
356
378
|
assert { (a + 1) == [[2, 3, 4], [6, 8, 12]] }
|
|
@@ -704,6 +726,8 @@ class NArrayTest < Test::Unit::TestCase
|
|
|
704
726
|
[4, 1, 6]]]
|
|
705
727
|
assert { a.max_index(2) == [[1, 5, 8], [9, 12, 17]] }
|
|
706
728
|
assert { a.max(2) == [[8, 6, 5], [7, 9, 6]] }
|
|
729
|
+
assert { a.argmax(2) == [[1, 2, 2], [0, 0, 2]] }
|
|
730
|
+
assert { a.argmin(2) == [[2, 0, 0], [2, 2, 1]] }
|
|
707
731
|
|
|
708
732
|
unless [Cumo::UInt64, Cumo::UInt32, Cumo::UInt16, Cumo::UInt8].include?(dtype)
|
|
709
733
|
a = dtype[[[-6, -8, -5],
|
|
@@ -796,6 +820,11 @@ class NArrayTest < Test::Unit::TestCase
|
|
|
796
820
|
end
|
|
797
821
|
end
|
|
798
822
|
|
|
823
|
+
test "cast any object that responds to to_a" do
|
|
824
|
+
object = Struct.new(:to_a).new([1, 2, 3])
|
|
825
|
+
assert { Cumo::NArray.cast(object) == [1, 2, 3] }
|
|
826
|
+
end
|
|
827
|
+
|
|
799
828
|
test "Cumo::DFloat.cast(Cumo::RObject[1, nil, 3])" do
|
|
800
829
|
assert_equal(Cumo::DFloat[1, Float::NAN, 3].format_to_a,
|
|
801
830
|
Cumo::DFloat.cast(Cumo::RObject[1, nil, 3]).format_to_a)
|
|
@@ -822,4 +851,40 @@ class NArrayTest < Test::Unit::TestCase
|
|
|
822
851
|
assert { Cumo::SComplex[1].rms == 1.0 }
|
|
823
852
|
assert { Cumo::DComplex[1].rms == 1.0 }
|
|
824
853
|
end
|
|
854
|
+
|
|
855
|
+
test "concatenate with empty arrays" do
|
|
856
|
+
a = Cumo::DFloat[1, 2, 3]
|
|
857
|
+
empty = Cumo::DFloat[]
|
|
858
|
+
assert { Cumo::NArray.concatenate([empty, a]) == [1, 2, 3] }
|
|
859
|
+
assert { Cumo::NArray.concatenate([a, empty]) == [1, 2, 3] }
|
|
860
|
+
assert { Cumo::NArray.concatenate([empty, empty]) == [] }
|
|
861
|
+
assert { a.concatenate(empty) == [1, 2, 3] }
|
|
862
|
+
assert { empty.concatenate(a) == [1, 2, 3] }
|
|
863
|
+
assert { empty.concatenate(empty) == [] }
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
test "argmax/argmin" do
|
|
867
|
+
[Cumo::DFloat, Cumo::Int32, Cumo::UInt8].each do |dtype|
|
|
868
|
+
a = dtype[3, 4, 1, 2]
|
|
869
|
+
assert { a.argmax == 1 }
|
|
870
|
+
assert { a.argmin == 2 }
|
|
871
|
+
|
|
872
|
+
b = dtype[[3, 4, 1], [2, 0, 5]]
|
|
873
|
+
assert { b.argmax == 5 }
|
|
874
|
+
assert { b.argmin == 4 }
|
|
875
|
+
assert { b.argmax(axis: 1) == [1, 2] }
|
|
876
|
+
assert { b.argmax(axis: 0) == [0, 0, 1] }
|
|
877
|
+
assert { b.argmin(axis: 1) == [2, 1] }
|
|
878
|
+
assert { b.argmin(axis: 0) == [1, 1, 0] }
|
|
879
|
+
assert { b.at(b.argmax(axis: 0), 0..-1) == [3, 4, 5] }
|
|
880
|
+
assert { b.at(b.argmin(axis: 0), 0..-1) == [2, 0, 1] }
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
# NaN-aware (nan:true returns the NaN position; nan:false ignores NaN)
|
|
884
|
+
c = Cumo::DFloat[3.0, Float::NAN, 1.0, 5.0]
|
|
885
|
+
assert { c.argmax == 3 }
|
|
886
|
+
assert { c.argmax(nan: true) == 1 }
|
|
887
|
+
assert { c.argmin == 2 }
|
|
888
|
+
assert { c.argmin(nan: true) == 1 }
|
|
889
|
+
end
|
|
825
890
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cumo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Naotoshi Seo
|
|
@@ -157,6 +157,8 @@ files:
|
|
|
157
157
|
- ext/cumo/narray/gen/narray_def.rb
|
|
158
158
|
- ext/cumo/narray/gen/spec.rb
|
|
159
159
|
- ext/cumo/narray/gen/tmpl/accum.c
|
|
160
|
+
- ext/cumo/narray/gen/tmpl/accum_arg.c
|
|
161
|
+
- ext/cumo/narray/gen/tmpl/accum_arg_kernel.cu
|
|
160
162
|
- ext/cumo/narray/gen/tmpl/accum_binary.c
|
|
161
163
|
- ext/cumo/narray/gen/tmpl/accum_binary_kernel.cu
|
|
162
164
|
- ext/cumo/narray/gen/tmpl/accum_index.c
|
|
@@ -331,7 +333,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
331
333
|
- !ruby/object:Gem::Version
|
|
332
334
|
version: '0'
|
|
333
335
|
requirements: []
|
|
334
|
-
rubygems_version: 4.0.
|
|
336
|
+
rubygems_version: 4.0.15
|
|
335
337
|
specification_version: 4
|
|
336
338
|
summary: Cumo is CUDA aware numerical library whose interface is highly compatible
|
|
337
339
|
with Ruby Numo
|