numo-narray-alt 0.10.6 → 0.10.8

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
  SHA256:
3
- metadata.gz: ad0c7d628c79e849dab290f3143d45bd4a1f755b1abd62851937f7ed7d894e93
4
- data.tar.gz: 3643e1b645a95a1815237599543aa73735d0e19afa4ad7c10d4b95a902bd2df9
3
+ metadata.gz: cf8873637141f0256dbedbc1ada30646faef0f119af6a5a70e69676581bf610f
4
+ data.tar.gz: 7c9f38d861bcfa39ad544265ac205b33552c4139e5740524165d7cc057f0ccf2
5
5
  SHA512:
6
- metadata.gz: e46752c80f12517f896253dbf2756b1b170c25032d4680fb71806f5157e00a565590118b31ea91208b10654fe68699acaf3e93b85adb174e35e03e83cadcc753
7
- data.tar.gz: 646d182241adac8f628de8c18611cce09c44b1800737d9a1df10548ad99978ab96208f7efd5bb2ab57ba07f961785a1b42118ff7498b4a66f1fc6ea2838b5b8f
6
+ metadata.gz: afe8bb36cbf569f121565d952b4a0f7120f65b3f9b566d438747f17777cb2e28b66b268e4400866a69fd8009b7215c7f2501fef66ebaa5af32c2cf49060363d5
7
+ data.tar.gz: af4a5b9071ae98832f48e038134a9d658531bada286fefc312f9d08c3eba9752b1937eaeba6643e89d82295fa31222e705de76deb58be5841e24c9044ef685e5
@@ -8,6 +8,7 @@
8
8
  #include "numo/narray.h"
9
9
  #include "numo/template.h"
10
10
 
11
+ static ID id_copy;
11
12
  static ID id_mulsum;
12
13
  static ID id_store;
13
14
  static ID id_swap_byte;
@@ -105,7 +106,11 @@ static VALUE nary_swap_byte(VALUE self) {
105
106
  ndfunc_arg_out_t aout[1] = { { INT2FIX(0), 0 } };
106
107
  ndfunc_t ndf = { iter_swap_byte, FULL_LOOP | NDF_ACCEPT_BYTESWAP, 1, 1, ain, aout };
107
108
 
108
- v = na_ndloop(&ndf, 1, self);
109
+ if (RTEST(rb_obj_is_kind_of(self, numo_cBit))) {
110
+ v = TEST_INPLACE(self) ? self : rb_funcall(self, id_copy, 0);
111
+ } else {
112
+ v = na_ndloop(&ndf, 1, self);
113
+ }
109
114
  if (self != v) {
110
115
  na_copy_flags(self, v);
111
116
  }
@@ -359,6 +364,10 @@ static void na_check_reshape(int argc, VALUE* argv, VALUE self, size_t* shape) {
359
364
  } else if (total != NA_SIZE(na)) {
360
365
  rb_raise(rb_eArgError, "Total size must be same");
361
366
  }
367
+
368
+ if (argc > NA_MAX_DIMENSION) {
369
+ rb_raise(nary_eDimensionError, "ndim=%d is too many", argc);
370
+ }
362
371
  }
363
372
 
364
373
  /*
@@ -376,11 +385,15 @@ static VALUE na_reshape_bang(int argc, VALUE* argv, VALUE self) {
376
385
  ssize_t stride;
377
386
  stridx_t* stridx;
378
387
  int i;
388
+ VALUE tmp;
379
389
 
390
+ if (OBJ_FROZEN(self)) {
391
+ rb_raise(rb_eRuntimeError, "cannot write to frozen NArray.");
392
+ }
380
393
  if (na_check_contiguous(self) == Qfalse) {
381
394
  rb_raise(rb_eStandardError, "cannot change shape of non-contiguous NArray");
382
395
  }
383
- shape = ALLOCA_N(size_t, argc);
396
+ shape = RB_ALLOCV_N(size_t, tmp, argc);
384
397
  na_check_reshape(argc, argv, self, shape);
385
398
 
386
399
  GetNArray(self, na);
@@ -391,7 +404,11 @@ static VALUE na_reshape_bang(int argc, VALUE* argv, VALUE self) {
391
404
  } else {
392
405
  stridx = na2->stridx;
393
406
  }
394
- stride = SDX_GET_STRIDE(na2->stridx[na->ndim - 1]);
407
+ if (na->ndim == 0) {
408
+ stride = nary_element_stride(self);
409
+ } else {
410
+ stride = SDX_GET_STRIDE(na2->stridx[na->ndim - 1]);
411
+ }
395
412
  for (i = argc; i--;) {
396
413
  SDX_SET_STRIDE(stridx[i], stride);
397
414
  stride *= shape[i];
@@ -402,6 +419,7 @@ static VALUE na_reshape_bang(int argc, VALUE* argv, VALUE self) {
402
419
  }
403
420
  }
404
421
  na_setup_shape(na, argc, shape);
422
+ RB_ALLOCV_END(tmp);
405
423
  return self;
406
424
  }
407
425
 
@@ -416,14 +434,15 @@ static VALUE na_reshape_bang(int argc, VALUE* argv, VALUE self) {
416
434
  static VALUE na_reshape(int argc, VALUE* argv, VALUE self) {
417
435
  size_t* shape;
418
436
  narray_t* na;
419
- VALUE copy;
437
+ VALUE copy, tmp;
420
438
 
421
- shape = ALLOCA_N(size_t, argc);
439
+ shape = RB_ALLOCV_N(size_t, tmp, argc);
422
440
  na_check_reshape(argc, argv, self, shape);
423
441
 
424
442
  copy = rb_funcall(self, rb_intern("dup"), 0);
425
443
  GetNArray(copy, na);
426
444
  na_setup_shape(na, argc, shape);
445
+ RB_ALLOCV_END(tmp);
427
446
  return copy;
428
447
  }
429
448
 
@@ -505,6 +524,9 @@ na_flatten_dim(VALUE self, int sd) {
505
524
  // set index
506
525
  idx2 = ALLOC_N(size_t, (shape[sd] == 0) ? 1 : shape[sd]);
507
526
  SDX_SET_INDEX(na2->stridx[sd], idx2);
527
+ if (shape[sd] == 0) {
528
+ return view;
529
+ }
508
530
  // init for md-loop
509
531
  fd = nd - sd;
510
532
  c = ALLOCA_N(size_t, fd);
@@ -965,6 +987,7 @@ void Init_nary_data(void) {
965
987
 
966
988
  // rb_define_method(cNArray, "dot", numo_na_dot, 1);
967
989
 
990
+ id_copy = rb_intern("copy");
968
991
  id_mulsum = rb_intern("mulsum");
969
992
  id_store = rb_intern("store");
970
993
  id_swap_byte = rb_intern("swap_byte");
@@ -439,7 +439,9 @@ static size_t na_index_parse_args(VALUE args, narray_t* na, na_index_arg_t* q, i
439
439
  }
440
440
  // new dimension
441
441
  else if (v == sym_new) {
442
- na_index_parse_each(v, 1, k, &q[j]);
442
+ // Past the last dimension, which is how the aref functions below tell
443
+ // a new axis from a real one.
444
+ na_index_parse_each(v, 1, na->ndim, &q[j]);
443
445
  j++;
444
446
  }
445
447
  // other dimension
@@ -465,6 +467,25 @@ static void na_get_strides_nadata(const narray_data_t* na, ssize_t* strides, ssi
465
467
  }
466
468
  }
467
469
 
470
+ // A new axis holds one element, so any stride addresses it. Give it the size of
471
+ // the block below it, to keep the chain na_check_ladder() walks: a break there
472
+ // costs contiguous?, and na_flatten_dim() takes the last dimension's stride as
473
+ // the flat one on the strength of that same chain.
474
+ static void na_index_set_newaxis_strides(
475
+ narray_view_t* na2, const int* newaxis, int n_newaxes, int ndim_new
476
+ ) {
477
+ int i, j;
478
+
479
+ for (i = n_newaxes - 1; i >= 0; i--) {
480
+ j = newaxis[i];
481
+ if (j + 1 < ndim_new && SDX_IS_STRIDE(na2->stridx[j + 1])) {
482
+ SDX_SET_STRIDE(
483
+ na2->stridx[j], SDX_GET_STRIDE(na2->stridx[j + 1]) * (ssize_t)na2->base.shape[j + 1]
484
+ );
485
+ }
486
+ }
487
+ }
488
+
468
489
  static void na_index_aref_nadata(
469
490
  narray_data_t* na1, narray_view_t* na2, na_index_arg_t* q, ssize_t elmsz, int ndim,
470
491
  int keep_dim
@@ -475,8 +496,11 @@ static void na_index_aref_nadata(
475
496
  ssize_t* strides_na1;
476
497
  size_t* index;
477
498
  ssize_t beg, step;
499
+ int* newaxis;
500
+ int n_newaxes = 0;
478
501
  VALUE m;
479
502
 
503
+ newaxis = ALLOCA_N(int, ndim);
480
504
  strides_na1 = ALLOCA_N(ssize_t, na1->base.ndim);
481
505
  na_get_strides_nadata(na1, strides_na1, elmsz);
482
506
 
@@ -503,6 +527,7 @@ static void na_index_aref_nadata(
503
527
 
504
528
  if (qi_orig_dim >= na1->base.ndim) {
505
529
  // new dimension
530
+ newaxis[n_newaxes++] = j;
506
531
  SDX_SET_STRIDE(na2->stridx[j], elmsz);
507
532
  } else if (q[i].idx != NULL) {
508
533
  // array index
@@ -521,6 +546,7 @@ static void na_index_aref_nadata(
521
546
  j++;
522
547
  total *= size;
523
548
  }
549
+ na_index_set_newaxis_strides(na2, newaxis, n_newaxes, j);
524
550
  na2->base.size = total;
525
551
  }
526
552
 
@@ -530,6 +556,10 @@ static void na_index_aref_naview(
530
556
  ) {
531
557
  int i, j;
532
558
  ssize_t total = 1;
559
+ int* newaxis;
560
+ int n_newaxes = 0;
561
+
562
+ newaxis = ALLOCA_N(int, ndim);
533
563
 
534
564
  for (i = j = 0; i < ndim; i++) {
535
565
  stridx_t sdx1;
@@ -560,6 +590,7 @@ static void na_index_aref_naview(
560
590
 
561
591
  if (qi_orig_dim >= na1->base.ndim) {
562
592
  // new dimension
593
+ newaxis[n_newaxes++] = j;
563
594
  SDX_SET_STRIDE(na2->stridx[j], elmsz);
564
595
  } else if (q[i].idx != NULL && SDX_IS_INDEX(sdx1)) {
565
596
  // index <- index
@@ -618,6 +649,7 @@ static void na_index_aref_naview(
618
649
  j++;
619
650
  total *= size;
620
651
  }
652
+ na_index_set_newaxis_strides(na2, newaxis, n_newaxes, j);
621
653
  na2->base.size = total;
622
654
  }
623
655
 
@@ -838,7 +870,10 @@ int na_get_result_dimension(
838
870
  }
839
871
 
840
872
  if (j != argc) {
841
- return check_index_count(argc, na->ndim, count_new, count_rest);
873
+ int nd = check_index_count(argc, na->ndim, count_new, count_rest);
874
+ if (nd != 0) {
875
+ return nd;
876
+ }
842
877
  }
843
878
 
844
879
  switch (na->type) {
@@ -275,7 +275,18 @@ void na_array_to_internal_shape(VALUE self, VALUE ary, size_t* shape) {
275
275
  }
276
276
  }
277
277
 
278
+ static void na_check_ndim(int ndim) {
279
+ if (ndim < 0) {
280
+ rb_raise(nary_eDimensionError, "ndim=%d is negative", ndim);
281
+ }
282
+ if (ndim > NA_MAX_DIMENSION) {
283
+ rb_raise(nary_eDimensionError, "ndim=%d is too many", ndim);
284
+ }
285
+ }
286
+
278
287
  void na_alloc_shape(narray_t* na, int ndim) {
288
+ na_check_ndim(ndim);
289
+
279
290
  na->ndim = ndim;
280
291
  na->size = 0;
281
292
  if (na->shape != NULL && na->shape != &(na->size)) {
@@ -288,12 +299,6 @@ void na_alloc_shape(narray_t* na, int ndim) {
288
299
  na->shape = &(na->size);
289
300
  break;
290
301
  default:
291
- if (ndim < 0) {
292
- rb_raise(nary_eDimensionError, "ndim=%d is negative", ndim);
293
- }
294
- if (ndim > NA_MAX_DIMENSION) {
295
- rb_raise(nary_eDimensionError, "ndim=%d is too many", ndim);
296
- }
297
302
  na->shape = ALLOC_N(size_t, ndim);
298
303
  }
299
304
  }
@@ -302,19 +307,23 @@ void na_setup_shape(narray_t* na, int ndim, size_t* shape) {
302
307
  int i;
303
308
  size_t size;
304
309
 
310
+ na_check_ndim(ndim);
311
+
312
+ for (i = 0, size = 1; i < ndim; i++) {
313
+ if (shape[i] != 0 && size > SIZE_MAX / shape[i]) {
314
+ rb_raise(rb_eRangeError, "total number of elements is too large");
315
+ }
316
+ size *= shape[i];
317
+ }
318
+
305
319
  na_alloc_shape(na, ndim);
306
320
 
307
- if (ndim == 0) {
308
- na->size = 1;
309
- } else if (ndim == 1) {
310
- na->size = shape[0];
311
- } else {
312
- for (i = 0, size = 1; i < ndim; i++) {
321
+ if (ndim > 1) {
322
+ for (i = 0; i < ndim; i++) {
313
323
  na->shape[i] = shape[i];
314
- size *= shape[i];
315
324
  }
316
- na->size = size;
317
325
  }
326
+ na->size = (ndim == 0) ? 1 : size;
318
327
  }
319
328
 
320
329
  static void na_setup(VALUE self, int ndim, size_t* shape) {
@@ -876,6 +885,9 @@ na_check_ladder(VALUE self, int start_dim) {
876
885
  narray_t* na;
877
886
  GetNArray(self, na);
878
887
 
888
+ if (na->ndim == 0) {
889
+ return Qtrue;
890
+ }
879
891
  if (start_dim < -na->ndim || start_dim >= na->ndim) {
880
892
  rb_bug("start_dim (%d) out of range", start_dim);
881
893
  }
@@ -920,6 +932,9 @@ na_check_contiguous(VALUE self) {
920
932
  if (NA_VIEW_STRIDX(na) == 0) {
921
933
  return Qtrue;
922
934
  }
935
+ if (NA_NDIM(na) == 0) {
936
+ return Qtrue;
937
+ }
923
938
  if (na_check_ladder(self, 0) == Qtrue) {
924
939
  elmsz = nary_element_stride(self);
925
940
  if (elmsz == NA_STRIDE_AT(na, NA_NDIM(na) - 1)) {
@@ -1043,6 +1058,7 @@ static VALUE na_expand_dims(VALUE self, VALUE vdim) {
1043
1058
 
1044
1059
  GetNArray(self, na);
1045
1060
  nd = na->ndim;
1061
+ na_check_ndim(nd + 1);
1046
1062
 
1047
1063
  dim = NUM2INT(vdim);
1048
1064
  if (dim < -nd - 1 || dim > nd) {
@@ -1272,7 +1288,11 @@ static VALUE nary_s_from_binary(int argc, VALUE* argv, VALUE type) {
1272
1288
  rb_raise(rb_eArgError, "second argument must be size or shape");
1273
1289
  }
1274
1290
  if (FIXNUM_P(velmsz)) {
1275
- byte_size = len * NUM2SIZET(velmsz);
1291
+ size_t elmsz = NUM2SIZET(velmsz);
1292
+ if (elmsz != 0 && len > SIZE_MAX / elmsz) {
1293
+ rb_raise(rb_eArgError, "specified size is too large");
1294
+ }
1295
+ byte_size = len * elmsz;
1276
1296
  } else {
1277
1297
  byte_size = ceil(len * NUM2DBL(velmsz));
1278
1298
  }
@@ -1315,7 +1335,7 @@ static VALUE nary_s_from_binary(int argc, VALUE* argv, VALUE type) {
1315
1335
  @return [Integer] stored length.
1316
1336
  */
1317
1337
  static VALUE nary_store_binary(int argc, VALUE* argv, VALUE self) {
1318
- size_t size, str_len, byte_size, offset;
1338
+ size_t size, str_len, byte_size, offset, view_offset = 0;
1319
1339
  int narg;
1320
1340
  VALUE vstr, voffset;
1321
1341
  VALUE velmsz;
@@ -1338,7 +1358,11 @@ static VALUE nary_store_binary(int argc, VALUE* argv, VALUE self) {
1338
1358
  size = NA_SIZE(na);
1339
1359
  velmsz = rb_const_get(rb_obj_class(self), id_element_byte_size);
1340
1360
  if (FIXNUM_P(velmsz)) {
1341
- byte_size = size * NUM2SIZET(velmsz);
1361
+ size_t elmsz = NUM2SIZET(velmsz);
1362
+ if (elmsz != 0 && size > SIZE_MAX / elmsz) {
1363
+ rb_raise(rb_eArgError, "string is too short to store");
1364
+ }
1365
+ byte_size = size * elmsz;
1342
1366
  } else {
1343
1367
  byte_size = ceil(size * NUM2DBL(velmsz));
1344
1368
  }
@@ -1346,12 +1370,34 @@ static VALUE nary_store_binary(int argc, VALUE* argv, VALUE self) {
1346
1370
  rb_raise(rb_eArgError, "string is too short to store");
1347
1371
  }
1348
1372
 
1349
- if (OBJ_FROZEN(vstr)) {
1373
+ if (na->type == NARRAY_VIEW_T) {
1374
+ narray_t* nab;
1375
+ size_t data_byte_size;
1376
+
1377
+ if (na_check_contiguous(self) == Qfalse) {
1378
+ rb_raise(rb_eStandardError, "cannot store binary data to non-contiguous NArray");
1379
+ }
1380
+ view_offset = NA_VIEW_OFFSET(na);
1381
+ if (!FIXNUM_P(velmsz) && view_offset != 0) {
1382
+ rb_raise(rb_eStandardError, "cannot store binary data to NArray view offset in bits");
1383
+ }
1384
+ GetNArray(NA_VIEW_DATA(na), nab);
1385
+ if (FIXNUM_P(velmsz)) {
1386
+ data_byte_size = NA_SIZE(nab) * NUM2SIZET(velmsz);
1387
+ } else {
1388
+ data_byte_size = ceil(NA_SIZE(nab) * NUM2DBL(velmsz));
1389
+ }
1390
+ if (view_offset > data_byte_size || byte_size > data_byte_size - view_offset) {
1391
+ rb_raise(rb_eArgError, "string is too long to store");
1392
+ }
1393
+ }
1394
+
1395
+ if (OBJ_FROZEN(vstr) && na->type != NARRAY_VIEW_T) {
1350
1396
  na_set_pointer(self, RSTRING_PTR(vstr) + offset, byte_size);
1351
1397
  rb_ivar_set(self, id_source, vstr);
1352
1398
  } else {
1353
- void* ptr = na_get_pointer_for_write(self);
1354
- memcpy(ptr, RSTRING_PTR(vstr) + offset, byte_size);
1399
+ char* ptr = na_get_pointer_for_write(self);
1400
+ memcpy(ptr + view_offset, RSTRING_PTR(vstr) + offset, byte_size);
1355
1401
  }
1356
1402
 
1357
1403
  return SIZET2NUM(byte_size);
@@ -1367,10 +1413,12 @@ static VALUE nary_to_binary(VALUE self) {
1367
1413
  char* ptr;
1368
1414
  VALUE str;
1369
1415
  narray_t* na;
1416
+ int offset_in_bits;
1370
1417
 
1371
1418
  GetNArray(self, na);
1372
1419
  if (na->type == NARRAY_VIEW_T) {
1373
- if (na_check_contiguous(self) == Qtrue) {
1420
+ offset_in_bits = RTEST(rb_obj_is_kind_of(self, numo_cBit)) && NA_VIEW_OFFSET(na) != 0;
1421
+ if (!offset_in_bits && na_check_contiguous(self) == Qtrue) {
1374
1422
  offset = NA_VIEW_OFFSET(na);
1375
1423
  } else {
1376
1424
  self = rb_funcall(self, id_dup, 0);
@@ -1402,7 +1450,7 @@ static VALUE nary_marshal_dump(VALUE self) {
1402
1450
  GetNArray(self, na);
1403
1451
  if (na->type == NARRAY_VIEW_T) {
1404
1452
  if (na_check_contiguous(self) == Qtrue) {
1405
- offset = NA_VIEW_OFFSET(na);
1453
+ offset = NA_VIEW_OFFSET(na) / sizeof(VALUE);
1406
1454
  } else {
1407
1455
  self = rb_funcall(self, id_dup, 0);
1408
1456
  }
@@ -1426,6 +1474,9 @@ static VALUE na_inplace(VALUE self);
1426
1474
  static VALUE nary_marshal_load(VALUE self, VALUE a) {
1427
1475
  VALUE v;
1428
1476
 
1477
+ if (OBJ_FROZEN(self)) {
1478
+ rb_raise(rb_eRuntimeError, "cannot write to frozen NArray.");
1479
+ }
1429
1480
  if (TYPE(a) != T_ARRAY) {
1430
1481
  rb_raise(rb_eArgError, "marshal argument should be array");
1431
1482
  }
@@ -1440,6 +1491,9 @@ static VALUE nary_marshal_load(VALUE self, VALUE a) {
1440
1491
  NUM2INT(RARRAY_AREF(a, 0))
1441
1492
  );
1442
1493
  }
1494
+ if (TYPE(RARRAY_AREF(a, 1)) != T_ARRAY) {
1495
+ rb_raise(rb_eArgError, "marshal shape should be array");
1496
+ }
1443
1497
  na_initialize(self, RARRAY_AREF(a, 1));
1444
1498
  NA_FL0_SET(self, FIX2INT(RARRAY_AREF(a, 2)));
1445
1499
  v = RARRAY_AREF(a, 3);
@@ -1456,6 +1510,7 @@ static VALUE nary_marshal_load(VALUE self, VALUE a) {
1456
1510
  ptr = na_get_pointer_for_write(self);
1457
1511
  memcpy(ptr, RARRAY_PTR(v), NA_SIZE(na) * sizeof(VALUE));
1458
1512
  } else {
1513
+ Check_Type(v, T_STRING);
1459
1514
  rb_str_freeze(v);
1460
1515
  nary_store_binary(1, &v, self);
1461
1516
  if (TEST_BYTE_SWAPPED(self)) {
@@ -520,7 +520,7 @@ static void ndloop_set_stepidx(na_md_loop_t* lp, int j, VALUE vna, int* dim_map,
520
520
  if (n > 1 || nd > 0) {
521
521
  i = dim_map[k];
522
522
  LITER(lp, i, j).step = s;
523
- // LITER(lp,i,j).idx = NULL;
523
+ LITER(lp, i, j).idx = NULL;
524
524
  }
525
525
  s *= n;
526
526
  nd--;
@@ -539,7 +539,7 @@ static void ndloop_set_stepidx(na_md_loop_t* lp, int j, VALUE vna, int* dim_map,
539
539
  LITER(lp, i, j).idx = SDX_GET_INDEX(sdx);
540
540
  } else {
541
541
  LITER(lp, i, j).step = SDX_GET_STRIDE(sdx);
542
- // LITER(lp,i,j).idx = NULL;
542
+ LITER(lp, i, j).idx = NULL;
543
543
  }
544
544
  } else if (n == 1) {
545
545
  if (SDX_IS_INDEX(sdx)) {
@@ -1540,6 +1540,7 @@ static void loop_store_subnarray(ndfunc_t* nf, na_md_loop_t* lp, int i0, size_t*
1540
1540
  dim_map[i] = lp->trans_map[i + i0];
1541
1541
  }
1542
1542
  ndloop_set_stepidx(lp, 1, a, dim_map, NDL_READ);
1543
+ LITER(lp, i0, 1).pos = LITER(lp, 0, 1).pos;
1543
1544
  LARG(lp, 1).shape = &(na->shape[na->ndim - 1]);
1544
1545
 
1545
1546
  // loop body
@@ -13,10 +13,10 @@ extern "C" {
13
13
  #endif
14
14
  #endif
15
15
 
16
- #define NARRAY_VERSION "0.10.6"
16
+ #define NARRAY_VERSION "0.10.8"
17
17
  #define NARRAY_VERSION_MAJOR 0
18
18
  #define NARRAY_VERSION_MINOR 10
19
- #define NARRAY_VERSION_PATCH 6
19
+ #define NARRAY_VERSION_PATCH 8
20
20
  #define NARRAY_VERSION_CODE \
21
21
  (NARRAY_VERSION_MAJOR * 10000 + NARRAY_VERSION_MINOR * 100 + NARRAY_VERSION_PATCH)
22
22
 
@@ -68,13 +68,6 @@
68
68
 
69
69
  #define m_mulsum_init INT2FIX(0)
70
70
 
71
- #define m_sprintf(s, x) robj_sprintf(s, x)
72
-
73
- static inline int robj_sprintf(char* s, VALUE x) {
74
- VALUE v = rb_funcall(x, rb_intern("to_s"), 0);
75
- return sprintf(s, "%s", StringValuePtr(v));
76
- }
77
-
78
71
  #define m_sqrt(x) \
79
72
  rb_funcall(rb_const_get(rb_mKernel, rb_intern("Math")), rb_intern("sqrt"), 1, x);
80
73
 
@@ -1,6 +1,16 @@
1
1
  #ifndef NUMO_NARRAY_MH_BINCOUNT_H
2
2
  #define NUMO_NARRAY_MH_BINCOUNT_H 1
3
3
 
4
+ /* The items below index the output, whose size was fixed by an earlier scan of
5
+ the same array. Ruby code can run in between, so the bound is rechecked. */
6
+ static inline void na_bincount_check_item(size_t x, size_t n) {
7
+ if (x >= n) {
8
+ rb_raise(
9
+ rb_eIndexError, "item %" SZF "u is out of range of the output(size:%" SZF "u)", x, n
10
+ );
11
+ }
12
+ }
13
+
4
14
  #define DEF_BINCOUNT_FUNCS(tDType, tNAryClass) \
5
15
  static void iter_##tDType##_bincount_32(na_loop_t* const lp) { \
6
16
  char* p1; \
@@ -21,11 +31,13 @@
21
31
  if (idx1) { \
22
32
  for (size_t i = 0; i < m; i++) { \
23
33
  GET_DATA_INDEX(p1, idx1, tDType, x); \
34
+ na_bincount_check_item(x, n); \
24
35
  (*(u_int32_t*)(p2 + s2 * x))++; \
25
36
  } \
26
37
  } else { \
27
38
  for (size_t i = 0; i < m; i++) { \
28
39
  GET_DATA_STRIDE(p1, s1, tDType, x); \
40
+ na_bincount_check_item(x, n); \
29
41
  (*(u_int32_t*)(p2 + s2 * x))++; \
30
42
  } \
31
43
  } \
@@ -60,11 +72,13 @@
60
72
  if (idx1) { \
61
73
  for (size_t i = 0; i < m; i++) { \
62
74
  GET_DATA_INDEX(p1, idx1, tDType, x); \
75
+ na_bincount_check_item(x, n); \
63
76
  (*(u_int64_t*)(p2 + s2 * x))++; \
64
77
  } \
65
78
  } else { \
66
79
  for (size_t i = 0; i < m; i++) { \
67
80
  GET_DATA_STRIDE(p1, s1, tDType, x); \
81
+ na_bincount_check_item(x, n); \
68
82
  (*(u_int64_t*)(p2 + s2 * x))++; \
69
83
  } \
70
84
  } \
@@ -106,6 +120,7 @@
106
120
  for (size_t i = 0; i < l; i++) { \
107
121
  GET_DATA_STRIDE(p1, s1, tDType, x); \
108
122
  GET_DATA_STRIDE(p2, s2, float, w); \
123
+ na_bincount_check_item(x, n); \
109
124
  (*(float*)(p3 + s3 * x)) += w; \
110
125
  } \
111
126
  } \
@@ -146,6 +161,7 @@
146
161
  for (size_t i = 0; i < l; i++) { \
147
162
  GET_DATA_STRIDE(p1, s1, tDType, x); \
148
163
  GET_DATA_STRIDE(p2, s2, double, w); \
164
+ na_bincount_check_item(x, n); \
149
165
  (*(double*)(p3 + s3 * x)) += w; \
150
166
  } \
151
167
  } \
@@ -170,6 +186,14 @@
170
186
  rb_scan_args(argc, argv, "01:", &weight, &kw); \
171
187
  rb_get_kwargs(kw, table, 0, 1, opts); \
172
188
  \
189
+ size_t minlength = 0; \
190
+ if (opts[0] != Qundef) { \
191
+ minlength = NUM2SIZET(opts[0]); \
192
+ } \
193
+ if (!NIL_P(weight) && rb_obj_class(weight) != numo_cSFloat) { \
194
+ weight = rb_funcall(numo_cDFloat, id_cast, 1, weight); \
195
+ } \
196
+ \
173
197
  VALUE v = tDType##_minmax(0, 0, self); \
174
198
  if (m_num_to_data(RARRAY_AREF(v, 0)) < 0) { \
175
199
  rb_raise(rb_eArgError, "array items must be non-netagive"); \
@@ -177,11 +201,8 @@
177
201
  v = RARRAY_AREF(v, 1); \
178
202
  \
179
203
  size_t length = NUM2SIZET(v) + 1; \
180
- if (opts[0] != Qundef) { \
181
- const size_t minlength = NUM2SIZET(opts[0]); \
182
- if (minlength > length) { \
183
- length = minlength; \
184
- } \
204
+ if (minlength > length) { \
205
+ length = minlength; \
185
206
  } \
186
207
  \
187
208
  if (NIL_P(weight)) { \
@@ -207,14 +228,23 @@
207
228
  rb_scan_args(argc, argv, "01:", &weight, &kw); \
208
229
  rb_get_kwargs(kw, table, 0, 1, opts); \
209
230
  \
231
+ size_t minlength = 0; \
232
+ if (opts[0] != Qundef) { \
233
+ minlength = NUM2SIZET(opts[0]); \
234
+ } \
235
+ if (!NIL_P(weight) && rb_obj_class(weight) != numo_cSFloat) { \
236
+ weight = rb_funcall(numo_cDFloat, id_cast, 1, weight); \
237
+ } \
238
+ \
210
239
  VALUE v = tDType##_max(0, 0, self); \
211
240
  \
212
- size_t length = NUM2SIZET(v) + 1; \
213
- if (opts[0] != Qundef) { \
214
- const size_t minlength = NUM2SIZET(opts[0]); \
215
- if (minlength > length) { \
216
- length = minlength; \
217
- } \
241
+ const size_t max = NUM2SIZET(v); \
242
+ if (max == SIZE_MAX) { \
243
+ rb_raise(rb_eRangeError, "maximum item %" SZF "u is too large to size the output", max); \
244
+ } \
245
+ size_t length = max + 1; \
246
+ if (minlength > length) { \
247
+ length = minlength; \
218
248
  } \
219
249
  \
220
250
  if (NIL_P(weight)) { \
@@ -1,7 +1,7 @@
1
1
  #ifndef NUMO_NARRAY_MH_FORMAT_H
2
2
  #define NUMO_NARRAY_MH_FORMAT_H 1
3
3
 
4
- #define DEF_NARRAY_FORMAT_METHOD_FUNC(tDType) \
4
+ #define DEF_NARRAY_FORMAT_ELEMENT_FUNC(tDType) \
5
5
  static VALUE format_##tDType(VALUE fmt, tDType* x) { \
6
6
  if (NIL_P(fmt)) { \
7
7
  char s[48]; \
@@ -9,8 +9,22 @@
9
9
  return rb_str_new(s, n); \
10
10
  } \
11
11
  return rb_funcall(fmt, '%', 1, m_data_to_num(*x)); \
12
- } \
13
- \
12
+ }
13
+
14
+ /* robject formats its element without the fixed buffer above: the element is an
15
+ arbitrary Ruby object, so the length of its to_s is not bounded by anything
16
+ this side controls. */
17
+ #define DEF_NARRAY_ROBJ_FORMAT_ELEMENT_FUNC() \
18
+ static VALUE format_robject(VALUE fmt, robject* x) { \
19
+ if (NIL_P(fmt)) { \
20
+ VALUE v = rb_funcall(*x, id_to_s, 0); \
21
+ StringValue(v); \
22
+ return rb_str_new(RSTRING_PTR(v), RSTRING_LEN(v)); \
23
+ } \
24
+ return rb_funcall(fmt, '%', 1, m_data_to_num(*x)); \
25
+ }
26
+
27
+ #define DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(tDType) \
14
28
  static void iter_##tDType##_format(na_loop_t* const lp) { \
15
29
  size_t n; \
16
30
  char* p1; \
@@ -52,4 +66,12 @@
52
66
  return na_ndloop(&ndf, 2, self, fmt); \
53
67
  }
54
68
 
69
+ #define DEF_NARRAY_FORMAT_METHOD_FUNC(tDType) \
70
+ DEF_NARRAY_FORMAT_ELEMENT_FUNC(tDType) \
71
+ DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(tDType)
72
+
73
+ #define DEF_NARRAY_ROBJ_FORMAT_METHOD_FUNC() \
74
+ DEF_NARRAY_ROBJ_FORMAT_ELEMENT_FUNC() \
75
+ DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(robject)
76
+
55
77
  #endif /* NUMO_NARRAY_MH_FORMAT_H */
@@ -321,9 +321,9 @@ static inline void swapfunc(char* a, char* b, size_t n, int swaptype) {
321
321
  rb_funcall(idx, rb_intern("seq"), 0); \
322
322
  size_t size = na->size * sizeof(void*); \
323
323
  VALUE tmp; \
324
- char* buf = rb_alloc_tmp_buffer(&tmp, size); \
324
+ char* buf = RB_ALLOCV(tmp, size); \
325
325
  VALUE res = na_ndloop3(&ndf, buf, 3, self, idx, reduce); \
326
- rb_free_tmp_buffer(&tmp); \
326
+ RB_ALLOCV_END(tmp); \
327
327
  return res; \
328
328
  }
329
329
 
@@ -475,9 +475,9 @@ static inline void swapfunc(char* a, char* b, size_t n, int swaptype) {
475
475
  rb_funcall(idx, rb_intern("seq"), 0); \
476
476
  size_t size = na->size * sizeof(void*); \
477
477
  VALUE tmp; \
478
- char* buf = rb_alloc_tmp_buffer(&tmp, size); \
478
+ char* buf = RB_ALLOCV(tmp, size); \
479
479
  VALUE res = na_ndloop3(&ndf, buf, 3, self, idx, reduce); \
480
- rb_free_tmp_buffer(&tmp); \
480
+ RB_ALLOCV_END(tmp); \
481
481
  return res; \
482
482
  }
483
483
 
@@ -1,6 +1,20 @@
1
1
  #ifndef NUMO_NARRAY_MH_STORE_H
2
2
  #define NUMO_NARRAY_MH_STORE_H 1
3
3
 
4
+ /* The store loops below run Ruby code for every element, which can reallocate or
5
+ shrink the array being read: its buffer and length do not survive one. */
6
+ static inline bool na_store_rary_fetch(VALUE ary, size_t i, VALUE* x) {
7
+ if (!RB_TYPE_P(ary, T_ARRAY)) {
8
+ *x = ary;
9
+ return true;
10
+ }
11
+ if (i >= (size_t)RARRAY_LEN(ary)) {
12
+ return false;
13
+ }
14
+ *x = RARRAY_AREF(ary, (long)i);
15
+ return true;
16
+ }
17
+
4
18
  #define DEF_STORE_NUMERIC_FUNC(tDType, tNAryClass) \
5
19
  static VALUE tDType##_store(VALUE, VALUE); \
6
20
  \
@@ -134,7 +148,6 @@
134
148
  size_t i1; \
135
149
  size_t n1; \
136
150
  VALUE v1; \
137
- VALUE* ptr; \
138
151
  VALUE x; \
139
152
  double y; \
140
153
  tDType z; \
@@ -152,8 +165,13 @@
152
165
  i = 0; \
153
166
  if (lp->args[1].ptr) { \
154
167
  if (v1 == Qtrue) { \
155
- iter_##tDType##_store_##tDType(lp); \
156
168
  i = lp->args[1].shape[0]; \
169
+ if (i > n) { \
170
+ i = n; \
171
+ } \
172
+ NDL_CNT(lp) = i; \
173
+ iter_##tDType##_store_##tDType(lp); \
174
+ NDL_CNT(lp) = n; \
157
175
  if (idx1) { \
158
176
  idx1 += i; \
159
177
  } else { \
@@ -162,11 +180,9 @@
162
180
  } \
163
181
  goto loop_end; \
164
182
  } \
165
- ptr = &v1; \
166
183
  switch (TYPE(v1)) { \
167
184
  case T_ARRAY: \
168
185
  n1 = RARRAY_LEN(v1); \
169
- ptr = RARRAY_PTR(v1); \
170
186
  break; \
171
187
  case T_NIL: \
172
188
  n1 = 0; \
@@ -175,8 +191,8 @@
175
191
  n1 = 1; \
176
192
  } \
177
193
  if (idx1) { \
178
- for (i = i1 = 0; i1 < n1 && i < n; i++, i1++) { \
179
- x = ptr[i1]; \
194
+ for (i = i1 = 0; i1 < n1 && i < n; i1++) { \
195
+ if (!na_store_rary_fetch(v1, i1, &x)) break; \
180
196
  if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, rb_cArithSeq)) { \
181
197
  nary_step_sequence(x, &len, &beg, &step); \
182
198
  for (c = 0; c < len && i < n; c++, i++) { \
@@ -187,11 +203,12 @@
187
203
  } else if (TYPE(x) != T_ARRAY) { \
188
204
  z = m_num_to_data(x); \
189
205
  SET_DATA_INDEX(p1, idx1, tDType, z); \
206
+ i++; \
190
207
  } \
191
208
  } \
192
209
  } else { \
193
- for (i = i1 = 0; i1 < n1 && i < n; i++, i1++) { \
194
- x = ptr[i1]; \
210
+ for (i = i1 = 0; i1 < n1 && i < n; i1++) { \
211
+ if (!na_store_rary_fetch(v1, i1, &x)) break; \
195
212
  if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, rb_cArithSeq)) { \
196
213
  nary_step_sequence(x, &len, &beg, &step); \
197
214
  for (c = 0; c < len && i < n; c++, i++) { \
@@ -202,6 +219,7 @@
202
219
  } else if (TYPE(x) != T_ARRAY) { \
203
220
  z = m_num_to_data(x); \
204
221
  SET_DATA_STRIDE(p1, s1, tDType, z); \
222
+ i++; \
205
223
  } \
206
224
  } \
207
225
  } \
@@ -474,7 +492,7 @@
474
492
  robject_store_uint8(self, obj); \
475
493
  return self; \
476
494
  } \
477
- if (klass == numo_cRObject) { \
495
+ if (RTEST(rb_obj_is_kind_of(obj, numo_cRObject))) { \
478
496
  robject_store_robject(self, obj); \
479
497
  return self; \
480
498
  } \
@@ -9,6 +9,7 @@
9
9
  #include <ruby.h>
10
10
 
11
11
  #include "SFMT.h"
12
+ #include "mh/store.h"
12
13
  #include "numo/narray.h"
13
14
  #include "numo/template.h"
14
15
 
@@ -134,7 +135,9 @@ static void iter_bit_fill(na_loop_t* const lp) {
134
135
  p3 += s3;
135
136
  }
136
137
  } else {
137
- if (p3 > 0 || n < NB) {
138
+ a3 += p3 / NB;
139
+ p3 %= NB;
140
+ if (n > 0 && (p3 > 0 || n < NB)) {
138
141
  len = (int)(NB - p3);
139
142
  if ((int)n < len) {
140
143
  len = (int)n;
@@ -307,8 +310,11 @@ static inline void yield_each_with_index(BIT_DIGIT x, size_t* c, VALUE* a, int n
307
310
 
308
311
  static void iter_bit_each_with_index(na_loop_t* const lp) {
309
312
  size_t* c = (size_t*)(lp->opt_ptr);
310
- int nd = lp->ndim - 1;
311
- int md = lp->ndim + 1;
313
+ int nd = lp->ndim;
314
+ if (nd > 0) {
315
+ nd--;
316
+ }
317
+ int md = nd + 2;
312
318
  VALUE* a = ALLOCA_N(VALUE, md);
313
319
  size_t n;
314
320
  BIT_DIGIT* a1;
@@ -580,7 +586,7 @@ static void iter_bit_store_bit(na_loop_t* const lp) {
580
586
  o1 = (int)(p1 - p3);
581
587
  l1 = NB + o1;
582
588
  r1 = NB - o1;
583
- if (p3 > 0 || n < NB) {
589
+ if (n > 0 && (p3 > 0 || n < NB)) {
584
590
  len = (int)(NB - p3);
585
591
  if ((int)n < len) len = (int)n;
586
592
  if (o1 >= 0)
@@ -1257,7 +1263,7 @@ static VALUE bit_store_robject(VALUE self, VALUE obj) {
1257
1263
  static void iter_bit_store_array(na_loop_t* const lp) {
1258
1264
  size_t i, n;
1259
1265
  size_t i1, n1;
1260
- VALUE v1, *ptr;
1266
+ VALUE v1;
1261
1267
  BIT_DIGIT* a1;
1262
1268
  size_t p1;
1263
1269
  size_t s1, *idx1;
@@ -1274,8 +1280,13 @@ static void iter_bit_store_array(na_loop_t* const lp) {
1274
1280
 
1275
1281
  if (lp->args[1].ptr) {
1276
1282
  if (v1 == Qtrue) {
1277
- iter_bit_store_bit(lp);
1278
1283
  i = lp->args[1].shape[0];
1284
+ if (i > n) {
1285
+ i = n;
1286
+ }
1287
+ NDL_CNT(lp) = i;
1288
+ iter_bit_store_bit(lp);
1289
+ NDL_CNT(lp) = n;
1279
1290
  if (idx1) {
1280
1291
  idx1 += i;
1281
1292
  } else {
@@ -1285,12 +1296,9 @@ static void iter_bit_store_array(na_loop_t* const lp) {
1285
1296
  goto loop_end;
1286
1297
  }
1287
1298
 
1288
- ptr = &v1;
1289
-
1290
1299
  switch (TYPE(v1)) {
1291
1300
  case T_ARRAY:
1292
1301
  n1 = RARRAY_LEN(v1);
1293
- ptr = RARRAY_PTR(v1);
1294
1302
  break;
1295
1303
  case T_NIL:
1296
1304
  n1 = 0;
@@ -1300,8 +1308,8 @@ static void iter_bit_store_array(na_loop_t* const lp) {
1300
1308
  }
1301
1309
 
1302
1310
  if (idx1) {
1303
- for (i = i1 = 0; i1 < n1 && i < n; i++, i1++) {
1304
- x = ptr[i1];
1311
+ for (i = i1 = 0; i1 < n1 && i < n; i1++) {
1312
+ if (!na_store_rary_fetch(v1, i1, &x)) break;
1305
1313
  if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, rb_cArithSeq)) {
1306
1314
  nary_step_sequence(x, &len, &beg, &step);
1307
1315
  for (c = 0; c < len && i < n; c++, i++) {
@@ -1310,17 +1318,17 @@ static void iter_bit_store_array(na_loop_t* const lp) {
1310
1318
  STORE_BIT(a1, p1 + *idx1, z);
1311
1319
  idx1++;
1312
1320
  }
1313
- }
1314
- if (TYPE(x) != T_ARRAY) {
1321
+ } else if (TYPE(x) != T_ARRAY) {
1315
1322
  if (x == Qnil) x = INT2FIX(0);
1316
1323
  z = m_num_to_data(x);
1317
1324
  STORE_BIT(a1, p1 + *idx1, z);
1318
1325
  idx1++;
1326
+ i++;
1319
1327
  }
1320
1328
  }
1321
1329
  } else {
1322
- for (i = i1 = 0; i1 < n1 && i < n; i++, i1++) {
1323
- x = ptr[i1];
1330
+ for (i = i1 = 0; i1 < n1 && i < n; i1++) {
1331
+ if (!na_store_rary_fetch(v1, i1, &x)) break;
1324
1332
  if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, rb_cArithSeq)) {
1325
1333
  nary_step_sequence(x, &len, &beg, &step);
1326
1334
  for (c = 0; c < len && i < n; c++, i++) {
@@ -1329,11 +1337,11 @@ static void iter_bit_store_array(na_loop_t* const lp) {
1329
1337
  STORE_BIT(a1, p1, z);
1330
1338
  p1 += s1;
1331
1339
  }
1332
- }
1333
- if (TYPE(x) != T_ARRAY) {
1340
+ } else if (TYPE(x) != T_ARRAY) {
1334
1341
  z = m_num_to_data(x);
1335
1342
  STORE_BIT(a1, p1, z);
1336
1343
  p1 += s1;
1344
+ i++;
1337
1345
  }
1338
1346
  }
1339
1347
  }
@@ -1693,7 +1701,7 @@ static void iter_bit_copy(na_loop_t* const lp) {
1693
1701
  o1 = (int)(p1 - p3);
1694
1702
  l1 = NB + o1;
1695
1703
  r1 = NB - o1;
1696
- if (p3 > 0 || n < NB) {
1704
+ if (n > 0 && (p3 > 0 || n < NB)) {
1697
1705
  len = (int)(NB - p3);
1698
1706
  if ((int)n < len) len = (int)n;
1699
1707
  if (o1 >= 0)
@@ -1787,7 +1795,7 @@ static void iter_bit_not(na_loop_t* const lp) {
1787
1795
  o1 = (int)(p1 - p3);
1788
1796
  l1 = NB + o1;
1789
1797
  r1 = NB - o1;
1790
- if (p3 > 0 || n < NB) {
1798
+ if (n > 0 && (p3 > 0 || n < NB)) {
1791
1799
  len = (int)(NB - p3);
1792
1800
  if ((int)n < len) len = (int)n;
1793
1801
  if (o1 >= 0)
@@ -1887,7 +1895,7 @@ static void iter_bit_and(na_loop_t* const lp) {
1887
1895
  r1 = NB - o1;
1888
1896
  l2 = NB + o2;
1889
1897
  r2 = NB - o2;
1890
- if (p3 > 0 || n < NB) {
1898
+ if (n > 0 && (p3 > 0 || n < NB)) {
1891
1899
  len = (int)(NB - p3);
1892
1900
  if ((int)n < len) len = (int)n;
1893
1901
  if (o1 >= 0)
@@ -2016,7 +2024,7 @@ static void iter_bit_or(na_loop_t* const lp) {
2016
2024
  r1 = NB - o1;
2017
2025
  l2 = NB + o2;
2018
2026
  r2 = NB - o2;
2019
- if (p3 > 0 || n < NB) {
2027
+ if (n > 0 && (p3 > 0 || n < NB)) {
2020
2028
  len = (int)(NB - p3);
2021
2029
  if ((int)n < len) len = (int)n;
2022
2030
  if (o1 >= 0)
@@ -2145,7 +2153,7 @@ static void iter_bit_xor(na_loop_t* const lp) {
2145
2153
  r1 = NB - o1;
2146
2154
  l2 = NB + o2;
2147
2155
  r2 = NB - o2;
2148
- if (p3 > 0 || n < NB) {
2156
+ if (n > 0 && (p3 > 0 || n < NB)) {
2149
2157
  len = (int)(NB - p3);
2150
2158
  if ((int)n < len) len = (int)n;
2151
2159
  if (o1 >= 0)
@@ -2274,7 +2282,7 @@ static void iter_bit_eq(na_loop_t* const lp) {
2274
2282
  r1 = NB - o1;
2275
2283
  l2 = NB + o2;
2276
2284
  r2 = NB - o2;
2277
- if (p3 > 0 || n < NB) {
2285
+ if (n > 0 && (p3 > 0 || n < NB)) {
2278
2286
  len = (int)(NB - p3);
2279
2287
  if ((int)n < len) len = (int)n;
2280
2288
  if (o1 >= 0)
@@ -288,7 +288,7 @@ static VALUE dcomplex_allocate(VALUE self) {
288
288
  case NARRAY_DATA_T:
289
289
  ptr = NA_DATA_PTR(na);
290
290
  if (na->size > 0 && ptr == NULL) {
291
- ptr = xmalloc(sizeof(dtype) * na->size);
291
+ ptr = xmalloc2(na->size, sizeof(dtype));
292
292
 
293
293
  NA_DATA_PTR(na) = ptr;
294
294
  NA_DATA_OWNED(na) = TRUE;
@@ -358,7 +358,7 @@ static VALUE dfloat_allocate(VALUE self) {
358
358
  case NARRAY_DATA_T:
359
359
  ptr = NA_DATA_PTR(na);
360
360
  if (na->size > 0 && ptr == NULL) {
361
- ptr = xmalloc(sizeof(dtype) * na->size);
361
+ ptr = xmalloc2(na->size, sizeof(dtype));
362
362
 
363
363
  NA_DATA_PTR(na) = ptr;
364
364
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE int16_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -271,7 +271,7 @@ static VALUE int32_allocate(VALUE self) {
271
271
  case NARRAY_DATA_T:
272
272
  ptr = NA_DATA_PTR(na);
273
273
  if (na->size > 0 && ptr == NULL) {
274
- ptr = xmalloc(sizeof(dtype) * na->size);
274
+ ptr = xmalloc2(na->size, sizeof(dtype));
275
275
 
276
276
  NA_DATA_PTR(na) = ptr;
277
277
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE int64_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE int8_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -50,6 +50,7 @@ static ID id_reciprocal;
50
50
  static ID id_round;
51
51
  static ID id_square;
52
52
  static ID id_to_a;
53
+ static ID id_to_s;
53
54
  static ID id_truncate;
54
55
 
55
56
  #include <numo/types/robject.h>
@@ -146,7 +147,7 @@ DEF_NARRAY_ASET_METHOD_FUNC(robject)
146
147
  DEF_NARRAY_COERCE_CAST_METHOD_FUNC(robject)
147
148
  DEF_NARRAY_TO_A_METHOD_FUNC(robject)
148
149
  DEF_NARRAY_FILL_METHOD_FUNC(robject)
149
- DEF_NARRAY_FORMAT_METHOD_FUNC(robject)
150
+ DEF_NARRAY_ROBJ_FORMAT_METHOD_FUNC()
150
151
  DEF_NARRAY_FORMAT_TO_A_METHOD_FUNC(robject)
151
152
  DEF_NARRAY_ROBJ_INSPECT_METHOD_FUNC()
152
153
  DEF_NARRAY_EACH_METHOD_FUNC(robject)
@@ -308,7 +309,7 @@ static VALUE robject_allocate(VALUE self) {
308
309
  case NARRAY_DATA_T:
309
310
  ptr = NA_DATA_PTR(na);
310
311
  if (na->size > 0 && ptr == NULL) {
311
- ptr = xmalloc(sizeof(dtype) * na->size);
312
+ ptr = xmalloc2(na->size, sizeof(dtype));
312
313
 
313
314
  {
314
315
  size_t i;
@@ -370,6 +371,7 @@ void Init_numo_robject(void) {
370
371
  id_round = rb_intern("round");
371
372
  id_square = rb_intern("square");
372
373
  id_to_a = rb_intern("to_a");
374
+ id_to_s = rb_intern("to_s");
373
375
  id_truncate = rb_intern("truncate");
374
376
 
375
377
  /**
@@ -286,7 +286,7 @@ static VALUE scomplex_allocate(VALUE self) {
286
286
  case NARRAY_DATA_T:
287
287
  ptr = NA_DATA_PTR(na);
288
288
  if (na->size > 0 && ptr == NULL) {
289
- ptr = xmalloc(sizeof(dtype) * na->size);
289
+ ptr = xmalloc2(na->size, sizeof(dtype));
290
290
 
291
291
  NA_DATA_PTR(na) = ptr;
292
292
  NA_DATA_OWNED(na) = TRUE;
@@ -356,7 +356,7 @@ static VALUE sfloat_allocate(VALUE self) {
356
356
  case NARRAY_DATA_T:
357
357
  ptr = NA_DATA_PTR(na);
358
358
  if (na->size > 0 && ptr == NULL) {
359
- ptr = xmalloc(sizeof(dtype) * na->size);
359
+ ptr = xmalloc2(na->size, sizeof(dtype));
360
360
 
361
361
  NA_DATA_PTR(na) = ptr;
362
362
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE uint16_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE uint32_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE uint64_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -270,7 +270,7 @@ static VALUE uint8_allocate(VALUE self) {
270
270
  case NARRAY_DATA_T:
271
271
  ptr = NA_DATA_PTR(na);
272
272
  if (na->size > 0 && ptr == NULL) {
273
- ptr = xmalloc(sizeof(dtype) * na->size);
273
+ ptr = xmalloc2(na->size, sizeof(dtype));
274
274
 
275
275
  NA_DATA_PTR(na) = ptr;
276
276
  NA_DATA_OWNED(na) = TRUE;
@@ -137,6 +137,10 @@ module Numo
137
137
  # # [[2, -3, 5],
138
138
  # # [4, 9, 7],
139
139
  # # [2, -1, 6]]
140
+ # @example
141
+ # a = Numo::NArray.parse('true false nil')
142
+ # # => Numo::Bit#shape=[1,3]
143
+ # # [[1, 0, 0]]
140
144
 
141
145
  def self.parse(str, split1d: /\s+/, split2d: /;?$|;/,
142
146
  split3d: /\s*\n(\s*\n)+/m)
@@ -151,7 +155,8 @@ module Numo
151
155
 
152
156
  c = []
153
157
  line.split(split1d).each do |item|
154
- c << eval(item.strip) unless item.empty? # rubocop:disable Security/Eval
158
+ item = item.strip
159
+ c << parse_token(item) unless item.empty?
155
160
  end
156
161
  b << c unless c.empty?
157
162
  end
@@ -164,6 +169,42 @@ module Numo
164
169
  end
165
170
  end
166
171
 
172
+ # Convert one token of {parse} input into a value.
173
+ #
174
+ # Only the literals that describe an element are accepted: integer, float
175
+ # and complex numbers, and +true+, +false+ and +nil+, which {cast} turns
176
+ # into a {Numo::Bit}. Anything else -- an expression, a method call, a bare
177
+ # word -- raises ArgumentError, so text handed to {parse} is never executed
178
+ # as Ruby code.
179
+ #
180
+ # @param item [String] one whitespace-delimited token, already stripped
181
+ # @return [Integer, Float, Complex, true, false, nil] the parsed value
182
+ # @raise [ArgumentError] if the token is not one of those literals
183
+ def self.parse_token(item)
184
+ case item
185
+ when 'true' then return true
186
+ when 'false' then return false
187
+ when 'nil' then return nil
188
+ end
189
+
190
+ v = Integer(item, exception: false)
191
+ return v if v
192
+
193
+ v = Float(item, exception: false)
194
+ return v if v
195
+
196
+ if item.end_with?('i')
197
+ begin
198
+ return Complex(item)
199
+ rescue ArgumentError, TypeError
200
+ nil
201
+ end
202
+ end
203
+
204
+ raise ArgumentError, "invalid literal: #{item.inspect}"
205
+ end
206
+ private_class_method :parse_token
207
+
167
208
  # Iterate over an axis
168
209
  # @example
169
210
  # > a = Numo::DFloat.new(2,2,2).seq
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-narray-alt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.6
4
+ version: 0.10.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
@@ -214,7 +214,7 @@ licenses:
214
214
  metadata:
215
215
  homepage_uri: https://github.com/yoshoku/numo-narray-alt
216
216
  changelog_uri: https://github.com/yoshoku/numo-narray-alt/blob/main/CHANGELOG.md
217
- documentation_uri: https://gemdocs.org/gems/numo-narray-alt/0.10.6/
217
+ documentation_uri: https://gemdocs.org/gems/numo-narray-alt/0.10.8/
218
218
  rubygems_mfa_required: 'true'
219
219
  post_install_message: |
220
220
  ===
@@ -238,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  - !ruby/object:Gem::Version
239
239
  version: '0'
240
240
  requirements: []
241
- rubygems_version: 4.0.16
241
+ rubygems_version: 4.0.20
242
242
  specification_version: 4
243
243
  summary: Numo::NArray Alternative is a project forked from Numo::NArray.
244
244
  test_files: []