numo-narray 0.9.0.6 → 0.9.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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
- }