numo-narray 0.9.0.6 → 0.9.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc2454fb169ad87ab4cb44c775c52906cb7636e8
4
- data.tar.gz: f81cd5ccc97b7fec259329021fce9ed896871670
3
+ metadata.gz: 2d0790c23a92e44538dfd0978899cdf87ccb5a36
4
+ data.tar.gz: c08e683349d0a8fad66c124f4fc687d79381a7bf
5
5
  SHA512:
6
- metadata.gz: c0e17e85b64041604643c9dfec270466dcf298cb794059f62f203eb82eb0b001d7a60a1b992c4bba7e0c286b03f508aaab0181187c9dff983f78b1c1f860c2f5
7
- data.tar.gz: 3a37fe344a33dd64effe30eb531300ef0144d250ad9223198bb4cbc016cbff7a312f3f39fdc4ad2bc83314dfc2de708d842c64740494690f79c62acfd58ef277
6
+ metadata.gz: 9f961ea396916fb91fc4e25cd93987786952397fbe75b9d7f11681e4abb3a764a8e12f9040ea2ed6a4164c4390535e01599ceba30351397617b4db39605b7bbe
7
+ data.tar.gz: f269691e7a51587070e4b548272ce56aeb84c6f036e2f70482801d7b4d8a19dadc96bf13783b19302ff1f937f3436240f23ca680676d7d54ffa77ae1fe1d1b8a
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ task :doc do
7
7
  map{|s| File.join(dir,s)} +
8
8
  [File.join(dir,"types/*.c"), "lib/numo/narray/extra.rb"]
9
9
  sh "cd ext/numo/narray; ruby extconf.rb; make src"
10
- sh "rm -rf yard .yardoc; yard doc -o yard -r README.md #{src.join(' ')}"
10
+ sh "rm -rf yard .yardoc; yard doc -o yard -m markdown -r README.md #{src.join(' ')}"
11
11
  end
12
12
 
13
13
  require "rake/extensiontask"
@@ -335,18 +335,15 @@ na_transpose(int argc, VALUE *argv, VALUE self)
335
335
 
336
336
  //----------------------------------------------------------------------
337
337
 
338
- /* private function for reshape */
339
- static VALUE
340
- na_reshape(int argc, VALUE *argv, VALUE self)
338
+ static void
339
+ na_check_reshape(int argc, VALUE *argv, VALUE self, size_t *shape)
341
340
  {
342
341
  int i, unfixed=-1;
343
342
  size_t total=1;
344
- size_t *shape; //, *shape_save;
345
343
  narray_t *na;
346
- VALUE copy;
347
344
 
348
345
  if (argc == 0) {
349
- rb_raise(rb_eRuntimeError, "No argrument");
346
+ rb_raise(rb_eArgError, "No argrument");
350
347
  }
351
348
  GetNArray(self,na);
352
349
  if (NA_SIZE(na) == 0) {
@@ -354,7 +351,6 @@ na_reshape(int argc, VALUE *argv, VALUE self)
354
351
  }
355
352
 
356
353
  /* get shape from argument */
357
- shape = ALLOCA_N(size_t,argc);
358
354
  for (i=0; i<argc; ++i) {
359
355
  switch(TYPE(argv[i])) {
360
356
  case T_FIXNUM:
@@ -362,6 +358,9 @@ na_reshape(int argc, VALUE *argv, VALUE self)
362
358
  break;
363
359
  case T_NIL:
364
360
  case T_TRUE:
361
+ if (unfixed >= 0) {
362
+ rb_raise(rb_eArgError,"multiple unfixed dimension");
363
+ }
365
364
  unfixed = i;
366
365
  break;
367
366
  default:
@@ -370,24 +369,66 @@ na_reshape(int argc, VALUE *argv, VALUE self)
370
369
  }
371
370
 
372
371
  if (unfixed>=0) {
373
- if (NA_SIZE(na) % total != 0)
372
+ if (NA_SIZE(na) % total != 0) {
374
373
  rb_raise(rb_eArgError, "Total size size must be divisor");
374
+ }
375
375
  shape[unfixed] = NA_SIZE(na) / total;
376
376
  }
377
377
  else if (total != NA_SIZE(na)) {
378
378
  rb_raise(rb_eArgError, "Total size must be same");
379
379
  }
380
+ }
380
381
 
381
- copy = rb_funcall(self,rb_intern("dup"),0);
382
- GetNArray(copy,na);
383
- //shape_save = NA_SHAPE(na);
384
- na_setup_shape(na,argc,shape);
385
- //if (NA_SHAPE(na) != shape_save) {
386
- // xfree(shape_save);
387
- //}
388
- return copy;
382
+ /*
383
+ Change the shape of self NArray without coping.
384
+ Raise exception if self is non-contiguous.
385
+
386
+ @overload reshape!(size0,size1,...)
387
+ @param sizeN [Integer] new shape
388
+ @return [Numo::NArray] return self.
389
+ @example
390
+ */
391
+ static VALUE
392
+ na_reshape_bang(int argc, VALUE *argv, VALUE self)
393
+ {
394
+ size_t *shape;
395
+ narray_t *na;
396
+
397
+ if (na_check_contiguous(self)==Qfalse) {
398
+ rb_raise(rb_eStandardError, "cannot change shape of non-contiguous NArray");
399
+ }
400
+ shape = ALLOCA_N(size_t, argc);
401
+ na_check_reshape(argc, argv, self, shape);
402
+
403
+ GetNArray(self, na);
404
+ na_setup_shape(na, argc, shape);
405
+ return self;
389
406
  }
390
407
 
408
+ /*
409
+ Copy and change the shape of NArray.
410
+ Returns a copied NArray.
411
+
412
+ @overload reshape(size0,size1,...)
413
+ @param sizeN [Integer] new shape
414
+ @return [Numo::NArray] return self.
415
+ @example
416
+ */
417
+ static VALUE
418
+ na_reshape(int argc, VALUE *argv, VALUE self)
419
+ {
420
+ size_t *shape;
421
+ narray_t *na;
422
+ VALUE copy;
423
+
424
+ shape = ALLOCA_N(size_t, argc);
425
+ na_check_reshape(argc, argv, self, shape);
426
+
427
+ copy = rb_funcall(self, rb_intern("dup"), 0);
428
+ GetNArray(copy, na);
429
+ na_setup_shape(na, argc, shape);
430
+ return copy;
431
+ }
391
432
 
392
433
  //----------------------------------------------------------------------
393
434
 
@@ -739,6 +780,7 @@ na_diagonal(int argc, VALUE *argv, VALUE self)
739
780
  //----------------------------------------------------------------------
740
781
 
741
782
 
783
+ #if 0
742
784
  #ifdef SWAP
743
785
  #undef SWAP
744
786
  #endif
@@ -880,7 +922,7 @@ numo_na_dot(VALUE self, VALUE other)
880
922
  }
881
923
  return rb_funcall(a1,id_mulsum,2,a2,INT2FIX(-1));
882
924
  }
883
-
925
+ #endif
884
926
 
885
927
  void
886
928
  Init_nary_data()
@@ -892,8 +934,8 @@ Init_nary_data()
892
934
  rb_define_method(cNArray, "transpose", na_transpose, -1);
893
935
 
894
936
  rb_define_method(cNArray, "reshape", na_reshape,-1);
895
- /*
896
937
  rb_define_method(cNArray, "reshape!", na_reshape_bang,-1);
938
+ /*
897
939
  rb_define_alias(cNArray, "shape=","reshape!");
898
940
  */
899
941
  rb_define_method(cNArray, "diagonal", na_diagonal,-1);
@@ -914,7 +956,7 @@ Init_nary_data()
914
956
  rb_define_method(cNArray, "to_host", nary_to_host, 0);
915
957
  rb_define_method(cNArray, "to_swapped", nary_to_swapped, 0);
916
958
 
917
- rb_define_method(cNArray, "dot", numo_na_dot, 1);
959
+ //rb_define_method(cNArray, "dot", numo_na_dot, 1);
918
960
 
919
961
  id_mulsum = rb_intern("mulsum");
920
962
  sym_mulsum = ID2SYM(id_mulsum);
@@ -109,6 +109,7 @@ end
109
109
  class DefLib < ErbPP
110
110
  def initialize(parent=nil, **opts, &block)
111
111
  opts[:erb_base] ||= 'lib'
112
+ opts[:include_files] ||= []
112
113
  super(parent, **opts, &block)
113
114
  end
114
115
  def id_assign
@@ -222,7 +223,7 @@ class DefMethod < ErbPP
222
223
  end
223
224
 
224
225
  def c_name
225
- @opts[:name].gsub(/\?/,"_p").gsub(/\!/,"_bang")
226
+ @opts[:name].gsub(/\?/,"_p").gsub(/\!/,"_bang").gsub(/=/,"_set")
226
227
  end
227
228
 
228
229
  def op_map
@@ -64,6 +64,16 @@ else
64
64
  def_const "CONTIGUOUS_STRIDE", "INT2FIX(sizeof(dtype))"
65
65
  end
66
66
 
67
+ if !is_object
68
+ if is_float
69
+ def_const "EPSILON", "M_EPSILON"
70
+ end
71
+ if is_float || is_int
72
+ def_const "MAX", "M_MAX"
73
+ def_const "MIN", "M_MIN"
74
+ end
75
+ end
76
+
67
77
  # Un-define
68
78
 
69
79
  if is_object
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  qsort.c
3
3
  Numerical Array Extension for Ruby
4
- (C) Copyright 2007-2017 by Masahiro TANAKA
4
+ modified by Masahiro TANAKA
5
5
  */
6
6
 
7
7
  /*
@@ -13,14 +13,14 @@ static void
13
13
  if (idx1) {
14
14
  if (idx2) {
15
15
  for (; i--;) {
16
- GET_DATA_INDEX(p1,idx1,dtype,x);
16
+ GET_DATA(p1+*idx1,dtype,x);
17
17
  GET_DATA_INDEX(p2,idx2,<%=dtype%>,y);
18
18
  x = m_<%=name%>(x,y);
19
19
  SET_DATA_INDEX(p1,idx1,dtype,x);
20
20
  }
21
21
  } else {
22
22
  for (; i--;) {
23
- GET_DATA_INDEX(p1,idx1,dtype,x);
23
+ GET_DATA(p1+*idx1,dtype,x);
24
24
  GET_DATA_STRIDE(p2,s2,<%=dtype%>,y);
25
25
  x = m_<%=name%>(x,y);
26
26
  SET_DATA_INDEX(p1,idx1,dtype,x);
@@ -1448,52 +1448,15 @@ na_test_reduce(VALUE reduce, int dim)
1448
1448
  }
1449
1449
 
1450
1450
 
1451
- VALUE
1452
- na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
1453
- ndfunc_t *ndf, na_iter_func_t iter_nan)
1451
+ static VALUE
1452
+ na_get_reduce_flag_from_narray(int naryc, VALUE *naryv, int *max_arg)
1454
1453
  {
1455
1454
  int ndim, ndim0;
1456
- int row_major;
1457
- int i, r;
1458
- long narg;
1455
+ int rowmaj;
1456
+ int i;
1459
1457
  size_t j;
1460
- size_t len;
1461
- ssize_t beg, step;
1462
- VALUE v;
1463
1458
  narray_t *na;
1464
- size_t m;
1465
1459
  VALUE reduce;
1466
- VALUE kw_hash = Qnil;
1467
- ID kw_table[3] = {id_axis,id_nan,id_keepdims};
1468
- VALUE opts[3] = {Qundef,Qundef,Qundef};
1469
- VALUE axes;
1470
-
1471
- narg = rb_scan_args(argc, argv, "*:", &axes, &kw_hash);
1472
- rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
1473
-
1474
- // option: axis
1475
- if (opts[0] != Qundef && RTEST(opts[0])) {
1476
- if (narg > 0) {
1477
- rb_raise(rb_eArgError,"both axis-arguments and axis-keyword are given");
1478
- }
1479
- if (TYPE(opts[0]) == T_ARRAY) {
1480
- axes = opts[0];
1481
- } else {
1482
- axes = rb_ary_new3(1,opts[0]);
1483
- }
1484
- }
1485
- if (ndf) {
1486
- // option: nan
1487
- if (iter_nan && opts[1] != Qundef) {
1488
- if (RTEST(opts[1]))
1489
- ndf->func = iter_nan; // replace to nan-aware iterator function
1490
- }
1491
- // option: keepdims
1492
- if (opts[2] != Qundef) {
1493
- if (RTEST(opts[2]))
1494
- ndf->flag |= NDF_KEEP_DIM;
1495
- }
1496
- }
1497
1460
 
1498
1461
  if (naryc<1) {
1499
1462
  rb_raise(rb_eRuntimeError,"must be positive: naryc=%d", naryc);
@@ -1503,32 +1466,47 @@ na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
1503
1466
  rb_raise(nary_eShapeError,"cannot reduce empty NArray");
1504
1467
  }
1505
1468
  reduce = na->reduce;
1506
- if (argc==0) {
1507
- //printf("pass argc=0 reduce=%d\n",NUM2INT(reduce));
1508
- return reduce;
1509
- }
1510
1469
  ndim = ndim0 = na->ndim;
1511
- row_major = TEST_COLUMN_MAJOR(naryv[0]);
1512
- for (i=1; i<naryc; i++) {
1470
+ if (max_arg) *max_arg = 0;
1471
+ rowmaj = TEST_COLUMN_MAJOR(naryv[0]);
1472
+ for (i=0; i<naryc; i++) {
1513
1473
  GetNArray(naryv[i],na);
1514
1474
  if (na->size==0) {
1515
1475
  rb_raise(nary_eShapeError,"cannot reduce empty NArray");
1516
1476
  }
1517
- if (TEST_COLUMN_MAJOR(naryv[i]) != row_major) {
1477
+ if (TEST_COLUMN_MAJOR(naryv[i]) != rowmaj) {
1518
1478
  rb_raise(nary_eDimensionError,"dimension order is different");
1519
1479
  }
1520
- if (na->ndim > ndim) {
1480
+ if (na->ndim > ndim) { // maximum dimension
1521
1481
  ndim = na->ndim;
1482
+ if (max_arg) *max_arg = i;
1522
1483
  }
1523
1484
  }
1524
1485
  if (ndim != ndim0) {
1525
- j = FIX2ULONG(reduce) << (ndim-ndim0);
1526
- reduce = ULONG2NUM(j);
1527
- if (!FIXNUM_P(reduce)) {
1528
- rb_raise(nary_eDimensionError,"reduce has too many bits");
1529
- }
1486
+ j = NUM2SIZET(reduce) << (ndim-ndim0);
1487
+ reduce = SIZET2NUM(j);
1530
1488
  }
1531
- //printf("argc=%d\n",argc);
1489
+ return reduce;
1490
+ }
1491
+
1492
+
1493
+ static VALUE
1494
+ na_get_reduce_flag_from_axes(VALUE na_obj, VALUE axes)
1495
+ {
1496
+ int i, r;
1497
+ int ndim, rowmaj;
1498
+ long narg;
1499
+ size_t j;
1500
+ size_t len;
1501
+ ssize_t beg, step;
1502
+ VALUE v;
1503
+ size_t m;
1504
+ VALUE reduce;
1505
+ narray_t *na;
1506
+
1507
+ GetNArray(na_obj,na);
1508
+ ndim = na->ndim;
1509
+ rowmaj = TEST_COLUMN_MAJOR(na_obj);
1532
1510
 
1533
1511
  m = 0;
1534
1512
  reduce = Qnil;
@@ -1554,8 +1532,9 @@ na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
1554
1532
  }
1555
1533
  for (j=0; j<len; j++) {
1556
1534
  r = beg + step*j;
1557
- if (row_major)
1535
+ if (rowmaj) {
1558
1536
  r = ndim-1-r;
1537
+ }
1559
1538
  if (reduce==Qnil) {
1560
1539
  if ( r < (ssize_t)sizeof(size_t) ) {
1561
1540
  m |= ((size_t)1) << r;
@@ -1568,12 +1547,70 @@ na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
1568
1547
  reduce = rb_funcall( reduce, '|', 1, v );
1569
1548
  }
1570
1549
  }
1571
- RB_GC_GUARD(axes);
1572
- if (reduce==Qnil) reduce = SIZET2NUM(m);
1550
+ if (NIL_P(reduce)) reduce = SIZET2NUM(m);
1573
1551
  return reduce;
1574
1552
  }
1575
1553
 
1576
1554
 
1555
+ VALUE
1556
+ nary_reduce_options(VALUE axes, VALUE *opts, int naryc, VALUE *naryv,
1557
+ ndfunc_t *ndf)
1558
+ {
1559
+ int max_arg;
1560
+ VALUE reduce;
1561
+
1562
+ // option: axis
1563
+ if (opts[0] != Qundef && RTEST(opts[0])) {
1564
+ if (!NIL_P(axes)) {
1565
+ rb_raise(rb_eArgError,
1566
+ "cannot specify axis-arguments and axis-keyword simultaneously");
1567
+ }
1568
+ if (TYPE(opts[0]) == T_ARRAY) {
1569
+ axes = opts[0];
1570
+ } else {
1571
+ axes = rb_ary_new3(1,opts[0]);
1572
+ }
1573
+ }
1574
+ if (ndf) {
1575
+ // option: keepdims
1576
+ if (opts[1] != Qundef) {
1577
+ if (RTEST(opts[1]))
1578
+ ndf->flag |= NDF_KEEP_DIM;
1579
+ }
1580
+ }
1581
+
1582
+ reduce = na_get_reduce_flag_from_narray(naryc, naryv, &max_arg);
1583
+
1584
+ if (NIL_P(axes)) return reduce;
1585
+
1586
+ return na_get_reduce_flag_from_axes(naryv[max_arg], axes);
1587
+ }
1588
+
1589
+
1590
+ VALUE
1591
+ nary_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
1592
+ ndfunc_t *ndf, na_iter_func_t iter_nan)
1593
+ {
1594
+ long narg;
1595
+ VALUE axes;
1596
+ VALUE kw_hash = Qnil;
1597
+ ID kw_table[3] = {id_axis,id_keepdims,id_nan};
1598
+ VALUE opts[3] = {Qundef,Qundef,Qundef};
1599
+
1600
+ narg = rb_scan_args(argc, argv, "*:", &axes, &kw_hash);
1601
+ rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
1602
+
1603
+ if (ndf) {
1604
+ // option: nan
1605
+ if (iter_nan && opts[2] != Qundef) {
1606
+ if (RTEST(opts[2]))
1607
+ ndf->func = iter_nan; // replace to nan-aware iterator function
1608
+ }
1609
+ }
1610
+
1611
+ return na_reduce_options((narg)?axes:Qnil, opts, naryc, naryv, ndf);
1612
+ }
1613
+
1577
1614
  /*
1578
1615
  Return true if column major.
1579
1616
  */
@@ -1205,15 +1205,10 @@ ndfunc_write_back(ndfunc_t *nf, na_md_loop_t *lp, VALUE orig_args, VALUE results
1205
1205
  static VALUE
1206
1206
  ndloop_extract(VALUE results, ndfunc_t *nf)
1207
1207
  {
1208
- static ID id_extract = 0;
1209
1208
  long n, i;
1210
1209
  VALUE x, y;
1211
1210
  narray_t *na;
1212
1211
 
1213
- if (id_extract==0) {
1214
- id_extract = id_extract;
1215
- }
1216
-
1217
1212
  // extract result objects
1218
1213
  switch(nf->nout) {
1219
1214
  case 0:
@@ -75,6 +75,10 @@ void na_release_lock(VALUE); // currently do nothing
75
75
  VALUE nary_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv,
76
76
  ndfunc_t *ndf, na_iter_func_t nan_iter);
77
77
 
78
+ #define na_reduce_options nary_reduce_options
79
+ VALUE nary_reduce_options(VALUE axes, VALUE *opts, int naryc, VALUE *naryv,
80
+ ndfunc_t *ndf);
81
+
78
82
  // ndloop
79
83
  VALUE na_ndloop(ndfunc_t *nf, int argc, ...);
80
84
  VALUE na_ndloop2(ndfunc_t *nf, VALUE args);
@@ -13,8 +13,8 @@ extern "C" {
13
13
  #endif
14
14
  #endif
15
15
 
16
- #define NARRAY_VERSION "0.9.0.6"
17
- #define NARRAY_VERSION_CODE 906
16
+ #define NARRAY_VERSION "0.9.0.7"
17
+ #define NARRAY_VERSION_CODE 907
18
18
 
19
19
  #include <math.h>
20
20
  #include "numo/compat.h"
@@ -10,10 +10,11 @@
10
10
  { c = (lp)->n[0]; }
11
11
 
12
12
  #define NDL_CNT(lp) ((lp)->n[0])
13
- #define NDL_PTR(lp,i) (((lp)->args[i]).ptr + ((lp)->args[i].iter[0]).pos)
14
- #define NDL_STP(lp,i) (((lp)->args[i].iter[0]).step)
15
- #define NDL_IDX(lp,i) (((lp)->args[i].iter[0]).idx)
16
- #define NDL_ESZ(lp,i) (((lp)->args[i]).elmsz)
13
+ #define NDL_PTR(lp,i) ((lp)->args[i].ptr + (lp)->args[i].iter[0].pos)
14
+ #define NDL_STEP(lp,i) ((lp)->args[i].iter[0].step)
15
+ #define NDL_IDX(lp,i) ((lp)->args[i].iter[0].idx)
16
+ #define NDL_ESZ(lp,i) ((lp)->args[i].elmsz)
17
+ #define NDL_SHAPE(lp,i) ((lp)->args[i].shape)
17
18
 
18
19
  #define INIT_PTR( lp, i, pt, st ) \
19
20
  { \
@@ -10,6 +10,7 @@ static inline bool c_nearly_eq(dtype x, dtype y) {
10
10
  return c_abs(c_sub(x,y)) <= (c_abs(x)+c_abs(y))*DBL_EPSILON*2;
11
11
  }
12
12
 
13
+ #ifdef SFMT_H
13
14
  /* generates a random number on [0,1)-real-interval */
14
15
  inline static dtype m_rand(dtype max)
15
16
  {
@@ -36,3 +37,8 @@ inline static void m_rand_norm(dtype mu, rtype sigma, dtype *a0)
36
37
  REAL(*a0) = x1*w * sigma + REAL(mu);
37
38
  IMAG(*a0) = x2*w * sigma + IMAG(mu);
38
39
  }
40
+ #endif
41
+
42
+ #define M_EPSILON rb_float_new(2.2204460492503131e-16)
43
+ #define M_MIN rb_float_new(2.2250738585072014e-308)
44
+ #define M_MAX rb_float_new(1.7976931348623157e+308)
@@ -6,6 +6,7 @@ typedef double rtype;
6
6
 
7
7
  #include "float_macro.h"
8
8
 
9
+ #ifdef SFMT_H
9
10
  /* generates a random number on [0,1)-real-interval */
10
11
  inline static dtype m_rand(dtype max)
11
12
  {
@@ -29,8 +30,13 @@ inline static void m_rand_norm(dtype mu, dtype sigma, dtype *a0, dtype *a1)
29
30
  if (a0) {*a0 = x1*w * sigma + mu;}
30
31
  if (a1) {*a1 = x2*w * sigma + mu;}
31
32
  }
33
+ #endif
32
34
 
33
35
  #define m_min_init numo_dfloat_new_dim0(0.0/0.0)
34
36
  #define m_max_init numo_dfloat_new_dim0(0.0/0.0)
35
37
  #define m_extract(x) rb_float_new(*(double*)x)
36
38
  #define m_nearly_eq(x,y) (fabs(x-y)<=(fabs(x)+fabs(y))*DBL_EPSILON*2)
39
+
40
+ #define M_EPSILON rb_float_new(2.2204460492503131e-16)
41
+ #define M_MIN rb_float_new(2.2250738585072014e-308)
42
+ #define M_MAX rb_float_new(1.7976931348623157e+308)
@@ -9,3 +9,13 @@ typedef int16_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%d",(int)(x))
10
10
 
11
11
  #include "int_macro.h"
12
+
13
+ #ifndef INT16_MIN
14
+ #define INT16_MIN (-32767-1)
15
+ #endif
16
+ #ifndef INT16_MAX
17
+ #define INT16_MAX (32767)
18
+ #endif
19
+
20
+ #define M_MIN m_data_to_num(INT16_MIN)
21
+ #define M_MAX m_data_to_num(INT16_MAX)
@@ -9,3 +9,13 @@ typedef int32_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%"PRId32,(int32_t)(x))
10
10
 
11
11
  #include "int_macro.h"
12
+
13
+ #ifndef INT32_MIN
14
+ #define INT32_MIN (-2147483647-1)
15
+ #endif
16
+ #ifndef INT32_MAX
17
+ #define INT32_MAX (2147483647)
18
+ #endif
19
+
20
+ #define M_MIN m_data_to_num(INT32_MIN)
21
+ #define M_MAX m_data_to_num(INT32_MAX)
@@ -9,3 +9,13 @@ typedef int64_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%"PRId64,(int64_t)(x))
10
10
 
11
11
  #include "int_macro.h"
12
+
13
+ #ifndef INT64_MIN
14
+ #define INT64_MIN (-9223372036854775807l-1)
15
+ #endif
16
+ #ifndef INT64_MAX
17
+ #define INT64_MAX (9223372036854775807l)
18
+ #endif
19
+
20
+ #define M_MIN m_data_to_num(INT64_MIN)
21
+ #define M_MAX m_data_to_num(INT64_MAX)
@@ -9,3 +9,13 @@ typedef int8_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%d",(int)(x))
10
10
 
11
11
  #include "int_macro.h"
12
+
13
+ #ifndef INT8_MIN
14
+ #define INT8_MIN (-127-1)
15
+ #endif
16
+ #ifndef INT8_MAX
17
+ #define INT8_MAX (127)
18
+ #endif
19
+
20
+ #define M_MIN INT2FIX(INT8_MIN)
21
+ #define M_MAX INT2FIX(INT8_MAX)
@@ -10,6 +10,7 @@ static inline bool c_nearly_eq(dtype x, dtype y) {
10
10
  return c_abs(c_sub(x,y)) <= (c_abs(x)+c_abs(y))*FLT_EPSILON*2;
11
11
  }
12
12
 
13
+ #ifdef SFMT_H
13
14
  /* generates a random number on [0,1)-real-interval */
14
15
  inline static dtype m_rand(dtype max)
15
16
  {
@@ -36,3 +37,8 @@ inline static void m_rand_norm(dtype mu, rtype sigma, dtype *a0)
36
37
  REAL(*a0) = x1*w * sigma + REAL(mu);
37
38
  IMAG(*a0) = x2*w * sigma + IMAG(mu);
38
39
  }
40
+ #endif
41
+
42
+ #define M_EPSILON rb_float_new(1.1920928955078125e-07)
43
+ #define M_MIN rb_float_new(1.1754943508222875e-38)
44
+ #define M_MAX rb_float_new(3.4028234663852886e+38)
@@ -1,11 +1,12 @@
1
1
  typedef float dtype;
2
2
  typedef float rtype;
3
3
  #define cT numo_cSFloat
4
- #define cRT cT
4
+ #define cRT numo_cSFloat
5
5
  #define mTM numo_mSFloatMath
6
6
 
7
7
  #include "float_macro.h"
8
8
 
9
+ #ifdef SFMT_H
9
10
  /* generates a random number on [0,1)-real-interval */
10
11
  inline static dtype m_rand(dtype max)
11
12
  {
@@ -29,9 +30,14 @@ inline static void m_rand_norm(dtype mu, dtype sigma, dtype *a0, dtype *a1)
29
30
  if (a0) {*a0 = x1*w * sigma + mu;}
30
31
  if (a1) {*a1 = x2*w * sigma + mu;}
31
32
  }
33
+ #endif
32
34
 
33
35
  #define m_min_init numo_sfloat_new_dim0(0.0/0.0)
34
36
  #define m_max_init numo_sfloat_new_dim0(0.0/0.0)
35
37
 
36
38
  #define m_extract(x) rb_float_new(*(float*)x)
37
39
  #define m_nearly_eq(x,y) (fabs(x-y)<=(fabs(x)+fabs(y))*FLT_EPSILON*2)
40
+
41
+ #define M_EPSILON rb_float_new(1.1920928955078125e-07)
42
+ #define M_MIN rb_float_new(1.1754943508222875e-38)
43
+ #define M_MAX rb_float_new(3.4028234663852886e+38)
@@ -9,3 +9,10 @@ typedef u_int16_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%u",(unsigned int)(x))
10
10
 
11
11
  #include "uint_macro.h"
12
+
13
+ #ifndef UINT16_MAX
14
+ #define UINT16_MAX (65535)
15
+ #endif
16
+
17
+ #define M_MIN INT2FIX(0)
18
+ #define M_MAX m_data_to_num(UINT16_MAX)
@@ -9,3 +9,10 @@ typedef u_int32_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%"PRIu32,(u_int32_t)(x))
10
10
 
11
11
  #include "uint_macro.h"
12
+
13
+ #ifndef UINT32_MAX
14
+ #define UINT32_MAX (4294967295u)
15
+ #endif
16
+
17
+ #define M_MIN INT2FIX(0)
18
+ #define M_MAX m_data_to_num(UINT32_MAX)
@@ -9,3 +9,10 @@ typedef u_int64_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%"PRIu64,(u_int64_t)(x))
10
10
 
11
11
  #include "uint_macro.h"
12
+
13
+ #ifndef UINT64_MAX
14
+ #define UINT64_MAX (18446744073709551615ul)
15
+ #endif
16
+
17
+ #define M_MIN INT2FIX(0)
18
+ #define M_MAX m_data_to_num(UINT64_MAX)
@@ -9,3 +9,10 @@ typedef u_int8_t rtype;
9
9
  #define m_sprintf(s,x) sprintf(s,"%u",(unsigned int)(x))
10
10
 
11
11
  #include "uint_macro.h"
12
+
13
+ #ifndef UINT8_MAX
14
+ #define UINT8_MAX (255)
15
+ #endif
16
+
17
+ #define M_MIN INT2FIX(0)
18
+ #define M_MAX m_data_to_num(UINT8_MAX)
@@ -32,20 +32,20 @@ module Numo
32
32
  end
33
33
 
34
34
  # Flip each row in the left/right direction.
35
- # Same as a[true, (-1..0).step(-1), ...].
35
+ # Same as `a[true, (-1..0).step(-1), ...]`.
36
36
  def fliplr
37
37
  reverse(1)
38
38
  end
39
39
 
40
40
  # Flip each column in the up/down direction.
41
- # Same as a[(-1..0).step(-1), ...].
41
+ # Same as `a[(-1..0).step(-1), ...]`.
42
42
  def flipud
43
43
  reverse(0)
44
44
  end
45
45
 
46
46
  # Multi-dimensional array indexing.
47
47
  # Same as [] for one-dimensional NArray.
48
- # Similar to numpy's tuple indexing, i.e., a[[1,2,..],[3,4,..]]
48
+ # Similar to numpy's tuple indexing, i.e., `a[[1,2,..],[3,4,..]]`
49
49
  # (This method will be rewritten in C)
50
50
  # @return [Numo::NArray] one-dimensional view of self.
51
51
  # @example
@@ -162,7 +162,7 @@ module Numo
162
162
  def self.asarray(a)
163
163
  case a
164
164
  when NArray
165
- a
165
+ (a.ndim == 0) ? a[:new] : a
166
166
  when Numeric,Range
167
167
  self[a]
168
168
  else
@@ -170,6 +170,44 @@ module Numo
170
170
  end
171
171
  end
172
172
 
173
+ # parse matrix like matlab, octave
174
+ # @example
175
+ # a = Numo::DFloat.parse %[
176
+ # 2 -3 5
177
+ # 4 9 7
178
+ # 2 -1 6
179
+ # ]
180
+ # => Numo::DFloat#shape=[3,3]
181
+ # [[2, -3, 5],
182
+ # [4, 9, 7],
183
+ # [2, -1, 6]]
184
+
185
+ def self.parse(str, split1d:/\s+/, split2d:/;?$|;/,
186
+ split3d:/\s*\n(\s*\n)+/m)
187
+ a = []
188
+ str.split(split3d).each do |block|
189
+ b = []
190
+ #print "b"; p block
191
+ block.split(split2d).each do |line|
192
+ #p line
193
+ line.strip!
194
+ if !line.empty?
195
+ c = []
196
+ line.split(split1d).each do |item|
197
+ c << eval(item.strip) if !item.empty?
198
+ end
199
+ b << c if !c.empty?
200
+ end
201
+ end
202
+ a << b if !b.empty?
203
+ end
204
+ if a.size==1
205
+ self.cast(a[0])
206
+ else
207
+ self.cast(a)
208
+ end
209
+ end
210
+
173
211
  # Append values to the end of an narray.
174
212
  # @example
175
213
  # a = Numo::DFloat[1, 2, 3]
@@ -919,15 +957,305 @@ module Numo
919
957
  return result
920
958
  end
921
959
 
960
+
961
+ # Upper triangular matrix.
962
+ # Return a copy with the elements below the k-th diagonal filled with zero.
963
+ def triu(k=0)
964
+ dup.triu!(k)
965
+ end
966
+
967
+ # Upper triangular matrix.
968
+ # Fill the self elements below the k-th diagonal with zero.
969
+ def triu!(k=0)
970
+ if ndim < 2
971
+ raise NArray::ShapeError, "must be >= 2-dimensional array"
972
+ end
973
+ if contiguous?
974
+ *shp,m,n = shape
975
+ idx = tril_indices(k-1)
976
+ reshape!(*shp,m*n)
977
+ self[false,idx] = 0
978
+ reshape!(*shp,m,n)
979
+ else
980
+ store(triu(k))
981
+ end
982
+ end
983
+
984
+ # Return the indices for the uppler-triangle on and above the k-th diagonal.
985
+ def triu_indices(k=0)
986
+ if ndim < 2
987
+ raise NArray::ShapeError, "must be >= 2-dimensional array"
988
+ end
989
+ m,n = shape[-2..-1]
990
+ NArray.triu_indices(m,n,k=0)
991
+ end
992
+
993
+ # Return the indices for the uppler-triangle on and above the k-th diagonal.
994
+ def self.triu_indices(m,n,k=0)
995
+ x = Numo::Int64.new(m,1).seq + k
996
+ y = Numo::Int64.new(1,n).seq
997
+ (x<=y).where
998
+ end
999
+
1000
+ # Lower triangular matrix.
1001
+ # Return a copy with the elements above the k-th diagonal filled with zero.
1002
+ def tril(k=0)
1003
+ dup.tril!(k)
1004
+ end
1005
+
1006
+ # Lower triangular matrix.
1007
+ # Fill the self elements above the k-th diagonal with zero.
1008
+ def tril!(k=0)
1009
+ if ndim < 2
1010
+ raise NArray::ShapeError, "must be >= 2-dimensional array"
1011
+ end
1012
+ if contiguous?
1013
+ idx = triu_indices(k+1)
1014
+ *shp,m,n = shape
1015
+ reshape!(*shp,m*n)
1016
+ self[false,idx] = 0
1017
+ reshape!(*shp,m,n)
1018
+ else
1019
+ store(tril(k))
1020
+ end
1021
+ end
1022
+
1023
+ # Return the indices for the lower-triangle on and below the k-th diagonal.
1024
+ def tril_indices(k=0)
1025
+ if ndim < 2
1026
+ raise NArray::ShapeError, "must be >= 2-dimensional array"
1027
+ end
1028
+ m,n = shape[-2..-1]
1029
+ NArray.tril_indices(m,n,k)
1030
+ end
1031
+
1032
+ # Return the indices for the lower-triangle on and below the k-th diagonal.
1033
+ def self.tril_indices(m,n,k=0)
1034
+ x = Numo::Int64.new(m,1).seq + k
1035
+ y = Numo::Int64.new(1,n).seq
1036
+ (x>=y).where
1037
+ end
1038
+
1039
+ # Return the k-th diagonal indices.
1040
+ def diag_indices(k=0)
1041
+ if ndim < 2
1042
+ raise NArray::ShapeError, "must be >= 2-dimensional array"
1043
+ end
1044
+ m,n = shape[-2..-1]
1045
+ NArray.diag_indices(m,n,k)
1046
+ end
1047
+
1048
+ # Return the k-th diagonal indices.
1049
+ def self.diag_indices(m,n,k=0)
1050
+ x = Numo::Int64.new(m,1).seq + k
1051
+ y = Numo::Int64.new(1,n).seq
1052
+ (x.eq y).where
1053
+ end
1054
+
1055
+ # Return a matrix whose diagonal is constructed by self along the last axis.
1056
+ def diag(k=0)
1057
+ *shp,n = shape
1058
+ n += k.abs
1059
+ a = self.class.zeros(*shp,n,n)
1060
+ a.diagonal(k).store(self)
1061
+ a
1062
+ end
1063
+
1064
+ # Return the sum along diagonals of the array.
1065
+ #
1066
+ # If 2-D array, computes the summation along its diagonal with the
1067
+ # given offset, i.e., sum of `a[i,i+offset]`.
1068
+ # If more than 2-D array, the diagonal is determined from the axes
1069
+ # specified by axis argument. The default is axis=[-2,-1].
1070
+ # @param offset [Integer] (optional, default=0) diagonal offset
1071
+ # @param axis [Array] (optional, default=[-2,-1]) diagonal axis
1072
+ # @param nan [Bool] (optional, default=false) nan-aware algorithm, i.e., if true then it ignores nan.
1073
+
1074
+ def trace(offset=nil,axis=nil,nan:false)
1075
+ diagonal(offset,axis).sum(nan:nan,axis:-1)
1076
+ end
1077
+
1078
+
1079
+ @@warn_slow_dot = false
1080
+
1081
+ # Dot product of two arrays.
1082
+ # @param b [Numo::NArray]
1083
+ # @return [Numo::NArray] return dot product
1084
+
1085
+ def dot(b)
1086
+ t = self.class::UPCAST[b.class]
1087
+ if defined?(Linalg) && [SFloat,DFloat,SComplex,DComplex].include?(t)
1088
+ Linalg.dot(self,b)
1089
+ else
1090
+ b = self.class.asarray(b)
1091
+ case b.ndim
1092
+ when 1
1093
+ mulsum(b, axis:-1)
1094
+ else
1095
+ case ndim
1096
+ when 0
1097
+ b.mulsum(self, axis:-2)
1098
+ when 1
1099
+ self[true,:new].mulsum(b, axis:-2)
1100
+ else
1101
+ unless @@warn_slow_dot
1102
+ nx = 200
1103
+ ns = 200000
1104
+ am,an = shape[-2..-1]
1105
+ bm,bn = b.shape[-2..-1]
1106
+ if am > nx && an > nx && bm > nx && bn > nx &&
1107
+ size > ns && b.size > ns
1108
+ @@warn_slow_dot = true
1109
+ warn "\nwarning: Built-in matrix dot is slow. Consider installing Numo::Linalg.\n\n"
1110
+ end
1111
+ end
1112
+ self[false,:new].mulsum(b[false,:new,true,true], axis:-2)
1113
+ end
1114
+ end
1115
+ end
1116
+ end
1117
+
1118
+ # Inner product of two arrays.
1119
+ # Same as `(a*b).sum(axis:-1)`.
1120
+ # @param b [Numo::NArray]
1121
+ # @param axis [Integer] applied axis
1122
+ # @return [Numo::NArray] return (a*b).sum(axis:axis)
1123
+
1124
+ def inner(b, axis:-1)
1125
+ mulsum(b, axis:axis)
1126
+ end
1127
+
1128
+ # Outer product of two arrays.
1129
+ # Same as `self[false,:new] * b[false,:new,true]`.
1130
+ #
1131
+ # @param b [Numo::NArray]
1132
+ # @param axis [Integer] applied axis (default=-1)
1133
+ # @return [Numo::NArray] return outer product
1134
+ # @example
1135
+ # a = Numo::DFloat.ones(5)
1136
+ # => Numo::DFloat#shape=[5]
1137
+ # [1, 1, 1, 1, 1]
1138
+ # b = Numo::DFloat.linspace(-2,2,5)
1139
+ # => Numo::DFloat#shape=[5]
1140
+ # [-2, -1, 0, 1, 2]
1141
+ # a.outer(b)
1142
+ # => Numo::DFloat#shape=[5,5]
1143
+ # [[-2, -1, 0, 1, 2],
1144
+ # [-2, -1, 0, 1, 2],
1145
+ # [-2, -1, 0, 1, 2],
1146
+ # [-2, -1, 0, 1, 2],
1147
+ # [-2, -1, 0, 1, 2]]
1148
+
1149
+ def outer(b, axis:nil)
1150
+ b = NArray.cast(b)
1151
+ if axis.nil?
1152
+ self[false,:new] * ((b.ndim==0) ? b : b[false,:new,true])
1153
+ else
1154
+ md,nd = [ndim,b.ndim].minmax
1155
+ axis = check_axis(axis) - nd
1156
+ if axis < -md
1157
+ raise ArgumentError,"axis=#{axis} is out of range"
1158
+ end
1159
+ adim = [true]*ndim
1160
+ adim[axis+ndim+1,0] = :new
1161
+ bdim = [true]*b.ndim
1162
+ bdim[axis+b.ndim,0] = :new
1163
+ self[*adim] * b[*bdim]
1164
+ end
1165
+ end
1166
+
1167
+ # Kronecker product of two arrays.
1168
+ #
1169
+ # kron(a,b)[k_0, k_1, ...] = a[i_0, i_1, ...] * b[j_0, j_1, ...]
1170
+ # where: k_n = i_n * b.shape[n] + j_n
1171
+ #
1172
+ # @param b [Numo::NArray]
1173
+ # @return [Numo::NArray] return Kronecker product
1174
+ # @example
1175
+ # Numo::DFloat[1,10,100].kron([5,6,7])
1176
+ # => Numo::DFloat#shape=[9]
1177
+ # [5, 6, 7, 50, 60, 70, 500, 600, 700]
1178
+ # Numo::DFloat[5,6,7].kron([1,10,100])
1179
+ # => Numo::DFloat#shape=[9]
1180
+ # [5, 50, 500, 6, 60, 600, 7, 70, 700]
1181
+ # Numo::DFloat.eye(2).kron(Numo::DFloat.ones(2,2))
1182
+ # => Numo::DFloat#shape=[4,4]
1183
+ # [[1, 1, 0, 0],
1184
+ # [1, 1, 0, 0],
1185
+ # [0, 0, 1, 1],
1186
+ # [0, 0, 1, 1]]
1187
+
1188
+ def kron(b)
1189
+ b = NArray.cast(b)
1190
+ nda = ndim
1191
+ ndb = b.ndim
1192
+ shpa = shape
1193
+ shpb = b.shape
1194
+ adim = [:new]*(2*[ndb-nda,0].max) + [true,:new]*nda
1195
+ bdim = [:new]*(2*[nda-ndb,0].max) + [:new,true]*ndb
1196
+ shpr = (-[nda,ndb].max..-1).map{|i| (shpa[i]||1) * (shpb[i]||1)}
1197
+ (self[*adim] * b[*bdim]).reshape(*shpr)
1198
+ end
1199
+
1200
+
1201
+ # under construction
1202
+ def cov(y=nil, ddof:1, fweights:nil, aweights:nil)
1203
+ if y
1204
+ m = NArray.vstack([self,y])
1205
+ else
1206
+ m = self
1207
+ end
1208
+ w = nil
1209
+ if fweights
1210
+ f = fweights
1211
+ w = f
1212
+ end
1213
+ if aweights
1214
+ a = aweights
1215
+ w = w ? w*a : a
1216
+ end
1217
+ if w
1218
+ w_sum = w.sum(axis:-1, keepdims:true)
1219
+ if ddof == 0
1220
+ fact = w_sum
1221
+ elsif aweights.nil?
1222
+ fact = w_sum - ddof
1223
+ else
1224
+ wa_sum = (w*a).sum(axis:-1, keepdims:true)
1225
+ fact = w_sum - ddof * wa_sum / w_sum
1226
+ end
1227
+ if (fact <= 0).any?
1228
+ raise StandardError,"Degrees of freedom <= 0 for slice"
1229
+ end
1230
+ else
1231
+ fact = m.shape[-1] - ddof
1232
+ end
1233
+ if w
1234
+ m -= (m*w).sum(axis:-1, keepdims:true) / w_sum
1235
+ mw = m*w
1236
+ else
1237
+ m -= m.mean(axis:-1, keepdims:true)
1238
+ mw = m
1239
+ end
1240
+ mt = (m.ndim < 2) ? m : m.swapaxes(-2,-1)
1241
+ mw.dot(mt.conj) / fact
1242
+ end
1243
+
922
1244
  private
1245
+
1246
+ # @!visibility private
923
1247
  def check_axis(axis)
924
- if axis < 0
925
- axis += ndim
1248
+ unless Integer===axis
1249
+ raise ArgumentError,"axis=#{axis} must be Integer"
926
1250
  end
927
- if axis < 0 || axis >= ndim
928
- raise ArgumentError,"invalid axis"
1251
+ a = axis
1252
+ if a < 0
1253
+ a += ndim
1254
+ end
1255
+ if a < 0 || a >= ndim
1256
+ raise ArgumentError,"axis=#{axis} is invalid"
929
1257
  end
930
- axis
1258
+ a
931
1259
  end
932
1260
 
933
1261
  end
data/numo-narray.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.description = %q{Numo::NArray - New NArray class library in Ruby/Numo.}
20
20
  spec.summary = %q{alpha release of Numo::NArray - New NArray class library in Ruby/Numo (NUmerical MOdule)}
21
21
  spec.homepage = "https://github.com/ruby-numo/narray"
22
- spec.license = "MIT"
22
+ spec.license = "BSD-3-Clause"
23
23
  spec.required_ruby_version = '~> 2.1'
24
24
 
25
25
  spec.files = `git ls-files Gemfile README.md Rakefile lib ext numo-narray.gemspec spec`.split($/)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-narray
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.6
4
+ version: 0.9.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro TANAKA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-27 00:00:00.000000000 Z
11
+ date: 2017-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -204,7 +204,6 @@ files:
204
204
  - ext/numo/narray/gen/tmpl_bit/where.c
205
205
  - ext/numo/narray/gen/tmpl_bit/where2.c
206
206
  - ext/numo/narray/index.c
207
- - ext/numo/narray/kwarg.c
208
207
  - ext/numo/narray/math.c
209
208
  - ext/numo/narray/narray.c
210
209
  - ext/numo/narray/ndloop.c
@@ -249,7 +248,7 @@ files:
249
248
  - spec/narray_spec.rb
250
249
  homepage: https://github.com/ruby-numo/narray
251
250
  licenses:
252
- - MIT
251
+ - BSD-3-Clause
253
252
  metadata: {}
254
253
  post_install_message:
255
254
  rdoc_options: []
@@ -1,74 +0,0 @@
1
- /*
2
- kwarg.c : Process keyword arguments for Ruby
3
-
4
- Copyright (c) 2001 Masahiro TANAKA
5
- */
6
- #include <ruby.h>
7
- #include "numo/compat.h"
8
-
9
- /* void rb_scan_kw_args __((VALUE, ...)); */
10
-
11
- static VALUE
12
- kw_hash_i(i, tmp)
13
- VALUE i, tmp;
14
- {
15
- VALUE key;
16
-
17
- key = RARRAY_AREF(i,0);
18
- if (TYPE(key)==T_SYMBOL) {
19
- key = rb_funcall(key, rb_intern("id2name"), 0);
20
- } else
21
- if (TYPE(key)!=T_STRING) {
22
- rb_raise(rb_eArgError, "keywords must be String or Symbol");
23
- }
24
-
25
- rb_hash_aset(tmp, key, RARRAY_AREF(i,1));
26
- return Qnil;
27
- }
28
-
29
- #ifdef HAVE_STDARG_PROTOTYPES
30
- #include <stdarg.h>
31
- #define va_init_list(a,b) va_start(a,b)
32
- #else
33
- #include <varargs.h>
34
- #define va_init_list(a,b) va_start(a)
35
- #endif
36
-
37
- void
38
- #ifdef HAVE_STDARG_PROTOTYPES
39
- rb_scan_kw_args(VALUE hash, ...)
40
- #else
41
- rb_scan_kw_args(hash, va_alist)
42
- VALUE hash;
43
- va_dcl
44
- #endif
45
- {
46
- va_list vargs;
47
- va_init_list(vargs, hash);
48
-
49
- char *key;
50
- VALUE *var, val, str, tmp;
51
-
52
- tmp = rb_hash_new();
53
- if (TYPE(hash) == T_HASH)
54
- rb_iterate(rb_each, hash, kw_hash_i, tmp);
55
- else if (hash != Qnil)
56
- rb_fatal("rb_san_kw_args: non-hash arg passed");
57
-
58
- for (;;) {
59
- key = va_arg(vargs, char*);
60
- if (!key) break;
61
- var = va_arg(vargs, VALUE*);
62
- //printf("i=%d key=%x, val=%x\n",i,key,val);
63
- str = rb_str_new2(key);
64
- val = rb_funcall(tmp, rb_intern("delete"), 1, str);
65
- if (var) *var = val;
66
- }
67
- va_end(vargs);
68
-
69
- if (rb_funcall(tmp, rb_intern("empty?"), 0)==Qfalse) {
70
- val = rb_funcall(tmp, rb_intern("keys"), 0);
71
- val = rb_funcall(val, rb_intern("join"), 1, rb_str_new2(","));
72
- rb_raise(rb_eArgError, "unknown keywords: %s",StringValueCStr(val));
73
- }
74
- }