tioga 1.11 → 1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/Tioga_README +58 -35
  2. data/{split/scripts → bin}/tioga +1 -1
  3. data/{split → ext/Dobjects}/Dtable/dtable.c +81 -15
  4. data/{split → ext/Dobjects}/Dtable/dtable_intern.h +0 -0
  5. data/ext/Dobjects/Dtable/extconf.rb +7 -0
  6. data/{split → ext/Dobjects}/Dtable/include/dtable.h +0 -0
  7. data/{split → ext/Dobjects}/Dvector/dvector.c +361 -51
  8. data/{split → ext/Dobjects}/Dvector/dvector_intern.h +0 -0
  9. data/ext/Dobjects/Dvector/extconf.rb +22 -0
  10. data/{split/Dtable → ext/Dobjects/Dvector/include}/dvector.h +0 -0
  11. data/ext/Dobjects/Function/extconf.rb +7 -0
  12. data/{split → ext/Dobjects}/Function/function.c +636 -11
  13. data/{split → ext/Dobjects}/Function/joint_qsort.c +0 -0
  14. data/ext/Flate/extconf.rb +26 -0
  15. data/{split → ext}/Flate/flate.c +7 -3
  16. data/{split → ext}/Flate/flate_intern.h +0 -0
  17. data/{split → ext}/Flate/include/flate.h +0 -0
  18. data/ext/Flate/zlib/adler32.c +149 -0
  19. data/ext/Flate/zlib/compress.c +79 -0
  20. data/ext/Flate/zlib/crc32.c +423 -0
  21. data/ext/Flate/zlib/crc32.h +441 -0
  22. data/ext/Flate/zlib/deflate.c +1736 -0
  23. data/ext/Flate/zlib/deflate.h +331 -0
  24. data/ext/Flate/zlib/gzio.c +1026 -0
  25. data/ext/Flate/zlib/infback.c +623 -0
  26. data/ext/Flate/zlib/inffast.c +318 -0
  27. data/ext/Flate/zlib/inffast.h +11 -0
  28. data/ext/Flate/zlib/inffixed.h +94 -0
  29. data/ext/Flate/zlib/inflate.c +1368 -0
  30. data/ext/Flate/zlib/inflate.h +115 -0
  31. data/ext/Flate/zlib/inftrees.c +329 -0
  32. data/ext/Flate/zlib/inftrees.h +55 -0
  33. data/ext/Flate/zlib/trees.c +1219 -0
  34. data/ext/Flate/zlib/trees.h +128 -0
  35. data/ext/Flate/zlib/uncompr.c +61 -0
  36. data/ext/Flate/zlib/zlib.h +1357 -0
  37. data/ext/Flate/zlib/zutil.c +318 -0
  38. data/ext/Flate/zlib/zutil.h +269 -0
  39. data/ext/Tioga/FigureMaker/__shared_axes.c +1373 -0
  40. data/ext/Tioga/FigureMaker/__shared_makers.c +1303 -0
  41. data/{split/Tioga/pdf_font_dicts.c → ext/Tioga/FigureMaker/__shared_pdf_font_dicts.c} +0 -0
  42. data/{split/Tioga/pdfcolor.c → ext/Tioga/FigureMaker/__shared_pdfcolor.c} +0 -0
  43. data/{split/Tioga/pdfcoords.c → ext/Tioga/FigureMaker/__shared_pdfcoords.c} +0 -0
  44. data/{split/Tioga/pdffile.c → ext/Tioga/FigureMaker/__shared_pdffile.c} +0 -0
  45. data/{split/Tioga/pdfimage.c → ext/Tioga/FigureMaker/__shared_pdfimage.c} +0 -0
  46. data/{split/Tioga/pdfpath.c → ext/Tioga/FigureMaker/__shared_pdfpath.c} +0 -0
  47. data/{split/Tioga/pdftext.c → ext/Tioga/FigureMaker/__shared_pdftext.c} +0 -0
  48. data/{split/Tioga/texout.c → ext/Tioga/FigureMaker/__shared_texout.c} +0 -0
  49. data/ext/Tioga/FigureMaker/extconf.rb +7 -0
  50. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.c +14 -2
  51. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.h +0 -0
  52. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.c +1 -2
  53. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.h +0 -1
  54. data/{split/Tioga → ext/Tioga/FigureMaker}/init.c +0 -0
  55. data/{split/Tioga → ext/Tioga/FigureMaker}/pdfs.h +0 -0
  56. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/axes.c +32 -7
  57. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/makers.c +2 -2
  58. data/ext/Tioga/FigureMaker/shared/pdf_font_dicts.c +18253 -0
  59. data/ext/Tioga/FigureMaker/shared/pdfcolor.c +904 -0
  60. data/ext/Tioga/FigureMaker/shared/pdfcoords.c +518 -0
  61. data/ext/Tioga/FigureMaker/shared/pdffile.c +451 -0
  62. data/ext/Tioga/FigureMaker/shared/pdfimage.c +539 -0
  63. data/ext/Tioga/FigureMaker/shared/pdfpath.c +766 -0
  64. data/ext/Tioga/FigureMaker/shared/pdftext.c +710 -0
  65. data/ext/Tioga/FigureMaker/shared/texout.c +533 -0
  66. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.c +5 -5
  67. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.h +0 -0
  68. data/{split/Dtable → ext/includes}/defs.h +0 -0
  69. data/{split/Dtable → ext/includes}/namespace.h +0 -0
  70. data/{split/Dtable → ext/includes}/safe_double.h +0 -0
  71. data/{split → ext/includes}/symbols.c +0 -1
  72. data/{split/Dtable → ext/includes}/symbols.h +0 -0
  73. data/{split/Dtable/lib → lib/Dobjects}/Dtable_extras.rb +0 -0
  74. data/{split/Dvector/lib → lib/Dobjects}/Dvector_extras.rb +1 -0
  75. data/{split/Function/lib → lib/Dobjects}/Function_extras.rb +0 -0
  76. data/{split/Dvector/lib → lib/Dobjects}/Numeric_extras.rb +0 -0
  77. data/{split/Tioga/lib → lib/Tioga}/Arcs_and_Circles.rb +0 -0
  78. data/{split/Tioga/lib → lib/Tioga}/ColorConstants.rb +0 -0
  79. data/{split/Tioga/lib → lib/Tioga}/Colorbars.rb +0 -0
  80. data/{split/Tioga/lib → lib/Tioga}/Colormaps.rb +0 -0
  81. data/{split/Tioga/lib → lib/Tioga}/Coordinate_Conversions.rb +0 -0
  82. data/{split/Tioga/lib → lib/Tioga}/Creating_Paths.rb +0 -0
  83. data/{split/Tioga/lib → lib/Tioga}/Doc.rb +0 -0
  84. data/{split/Tioga/lib → lib/Tioga}/Executive.rb +0 -0
  85. data/{split/Tioga/lib → lib/Tioga}/FigMkr.rb +13 -70
  86. data/{split/Tioga/lib → lib/Tioga}/FigureConstants.rb +0 -0
  87. data/{split/Tioga/lib → lib/Tioga}/Figures_and_Plots.rb +0 -0
  88. data/{split/Tioga/lib → lib/Tioga}/Images.rb +0 -0
  89. data/{split/Tioga/lib → lib/Tioga}/Legends.rb +0 -0
  90. data/{split/Tioga/lib → lib/Tioga}/MarkerConstants.rb +0 -0
  91. data/{split/Tioga/lib → lib/Tioga}/Markers.rb +0 -0
  92. data/{split/Tioga/lib → lib/Tioga}/Page_Frame_Bounds.rb +0 -0
  93. data/{split/Tioga/lib → lib/Tioga}/Rectangles.rb +0 -0
  94. data/{split/Tioga/lib → lib/Tioga}/Shading.rb +0 -0
  95. data/{split/Tioga/lib → lib/Tioga}/Special_Paths.rb +0 -0
  96. data/{split/Tioga/lib → lib/Tioga}/Strokes.rb +0 -0
  97. data/{split/Tioga/lib → lib/Tioga}/TeX_Text.rb +0 -0
  98. data/{split/Tioga/lib → lib/Tioga}/TexPreamble.rb +0 -0
  99. data/{split/Tioga/lib → lib/Tioga}/Titles_and_Labels.rb +0 -0
  100. data/{split/Tioga/lib → lib/Tioga}/Transparency.rb +0 -0
  101. data/{split/Tioga/lib → lib/Tioga}/Using_Paths.rb +0 -0
  102. data/{split/Tioga/lib → lib/Tioga}/Utils.rb +74 -0
  103. data/{split/Tioga/lib → lib/Tioga}/X_and_Y_Axes.rb +0 -0
  104. data/{split/Tioga/lib → lib/Tioga}/irb_tioga.rb +0 -0
  105. data/{split/Tioga/lib → lib/Tioga}/maker.rb +0 -0
  106. data/{split/Tioga/lib → lib/Tioga}/tioga.rb +0 -0
  107. data/{split/Tioga/lib → lib/Tioga}/tioga_ui.rb +0 -0
  108. data/{split/Tioga/lib → lib/Tioga}/tioga_ui_cmds.rb +0 -0
  109. data/tests/Icon_Test.pdf +0 -0
  110. data/tests/benchmark_dvector_reads.rb +20 -42
  111. data/tests/tc_Dvector.rb +45 -4
  112. data/tests/tc_Flate.rb +4 -5
  113. data/tests/tc_Function.rb +79 -0
  114. data/tests/vg.log +1453 -0
  115. metadata +141 -122
  116. data/split/Dtable/extconf.rb +0 -4
  117. data/split/Dvector/defs.h +0 -39
  118. data/split/Dvector/extconf.rb +0 -4
  119. data/split/Dvector/include/dvector.h +0 -77
  120. data/split/Dvector/namespace.h +0 -59
  121. data/split/Dvector/safe_double.h +0 -104
  122. data/split/Dvector/symbols.h +0 -52
  123. data/split/Flate/defs.h +0 -39
  124. data/split/Flate/extconf.rb +0 -19
  125. data/split/Flate/namespace.h +0 -59
  126. data/split/Flate/safe_double.h +0 -104
  127. data/split/Flate/symbols.h +0 -52
  128. data/split/Function/defs.h +0 -39
  129. data/split/Function/dvector.h +0 -77
  130. data/split/Function/extconf.rb +0 -4
  131. data/split/Function/namespace.h +0 -59
  132. data/split/Function/safe_double.h +0 -104
  133. data/split/Function/symbols.h +0 -52
  134. data/split/Tioga/defs.h +0 -39
  135. data/split/Tioga/dtable.h +0 -35
  136. data/split/Tioga/dvector.h +0 -77
  137. data/split/Tioga/extconf.rb +0 -4
  138. data/split/Tioga/flate.h +0 -98
  139. data/split/Tioga/mk_tioga_sty.rb +0 -53
  140. data/split/Tioga/namespace.h +0 -59
  141. data/split/Tioga/safe_double.h +0 -104
  142. data/split/Tioga/symbols.h +0 -52
  143. data/split/defs.h +0 -39
  144. data/split/extconf.rb +0 -125
  145. data/split/mkmf2.rb +0 -1623
  146. data/split/namespace.h +0 -59
  147. data/split/safe_double.h +0 -104
  148. data/split/symbols.h +0 -52
data/Tioga_README CHANGED
@@ -1,7 +1,8 @@
1
1
  This is the README for the Tioga kernel, version 1.10, March 7, 2009.
2
2
 
3
3
  Copyright (C) 2005, 2006, 2007, 2008, 2009 Bill Paxton
4
- Copyright (C) 2007, 2008, 2009 Vincent Fourmond, Taro Sato
4
+ Copyright (C) 2007, 2008, 2009, 2010 Vincent Fourmond, Taro Sato,
5
+ Benjamin ter Kuile
5
6
 
6
7
  This file is part of Tioga.
7
8
 
@@ -21,16 +22,13 @@ This is the README for the Tioga kernel, version 1.10, March 7, 2009.
21
22
 
22
23
  << What's new >>
23
24
 
24
- Version 1.11 brings in a few new features. First, it is now
25
- possible to set the color of axis tick labels - if you love pink axes,
26
- you can them fully in Pink, now ;-) ! Check out the
27
- x/yaxis_labels_color= accessors. The show_axis/axis_info functions
28
- have been updated accordingly, and are now complete.
29
-
30
- Second, a new interpolation function for monotonic interpolations
31
- has been added to Dvector (check out the Sampled_pm_cubics sample in
32
- samples/plots/plots.rb).
25
+ Tioga 1.13 brings in a fix for a well-hidden memory leak that was
26
+ unlikely to hit you unless you were allocating a huge number of
27
+ vectors.
33
28
 
29
+ More interestingly, a few instance functions that did not depend on
30
+ FigureMaker's internal state (color conversion functions and
31
+ contouring algorithms) were made available as module functions too.
34
32
 
35
33
  << Quick Installation of Tioga >>
36
34
 
@@ -56,41 +54,27 @@ be working, go directly to the << Documentation >> section below.
56
54
  << Step-by-Step Installation >>
57
55
 
58
56
  To get Tioga running, you need to have a working Ruby, a C
59
- compiler, make, and pdflaxtex. Assuming you've got all that (more
57
+ compiler, make, and pdflatex. Assuming you've got all that (more
60
58
  later if you don't), connect to the Tioga directory that you just
61
59
  unpacked and do the following:
62
60
 
63
61
  [ this has been changed, be careful ! ]
64
62
 
65
- cd split
66
- ruby extconf.rb
67
- make
68
- make install
63
+ ruby setup.rb config
64
+ ruby setup.rb seutp
65
+ ruby setup.rb install
69
66
 
70
- This creates the Makefile, runs it, and finally does the actual
71
- installation. The "make install" needs to copy some files to the ruby
72
- directory. On the Mac, this probably means you need to do the whole
73
- thing inside a 'sudo'. For Linux, you may have to become root.
67
+ (that's exactly what the ./QUICK_INSTALL script is doing)
74
68
 
75
- Note that on Linux, the make will compile all the source files. On
76
- the Mac, the tar file includes precompiled versions of everything, so
77
- the make won't have anything to do. That's okay. Do the whole
78
- sequence anyway just to be safe.
79
-
80
- You now have another option to install: if you replace the line
81
-
82
- ruby extconf.rb
83
-
84
- with
85
-
86
- ruby extconf.rb --home
87
-
88
- it will install the files to your home directory, namely
89
- ~/lib/ruby. You don't need root privileges to do that, but make sure
90
- that you set RUBYLIB=~/lib/ruby somewhere, so that ruby can find it.
69
+ Tioga now uses the standard setup.rb installation tool, so you get
70
+ a lot of customization possibilities for free. For more information on
71
+ how to use setup.rb to suit your needs, try
91
72
 
73
+ ruby setup.rb --help
92
74
 
75
+ or, even better, take a look at its documentation:
93
76
 
77
+ http://i.loveruby.net/en/projects/setup/doc/usage.html
94
78
 
95
79
  << Checking The Installation >>
96
80
 
@@ -188,6 +172,45 @@ Bill Paxton
188
172
 
189
173
  Here are the old release messages:
190
174
 
175
+ Tioga 1.12 has seen quite a lot of action. The first and major
176
+ change is the switch from a custom rewrite of mkmf.rb for
177
+ building/installing to the standard setup.rb tool, which finally has
178
+ the gem version build exactly the same way as the pristine one.
179
+
180
+ Another side effect of this is that, for a big part thanks to
181
+ Carlo E. Prelz <fluido@fluido.as>, we now have tioga that works just
182
+ fine with Ruby 1.9.1 (though there is a weird bug while testing the
183
+ Flate library, we welcome any input on that).
184
+
185
+ Apart from that, Tioga has seen many improvements on the numerical
186
+ side. First, we welcome the participation of Benjamin ter Kuile, who
187
+ has started improving some aspects of Dtable.
188
+
189
+ Second, now Dvector is gifted with FFT capacities if the
190
+ development files of fftw3 are available at compile time (have a look
191
+ at the documentation).
192
+
193
+ Third, Function has been endowed with a whole bunch of new
194
+ functions for data processing, such as linear regression, spline
195
+ approximation (that almost looks like a good filter !), 4th order
196
+ accurate first and second derivatives.
197
+
198
+ Finally, a couple of annoying bugs were fixed.
199
+
200
+
201
+ --------------------------
202
+
203
+ Version 1.11 brings in a few new features. First, it is now
204
+ possible to set the color of axis tick labels - if you love pink axes,
205
+ you can them fully in Pink, now ;-) ! Check out the
206
+ x/yaxis_labels_color= accessors. The show_axis/axis_info functions
207
+ have been updated accordingly, and are now complete.
208
+
209
+ Second, a new interpolation function for monotonic interpolations
210
+ has been added to Dvector (check out the Sampled_pm_cubics sample in
211
+ samples/plots/plots.rb).
212
+
213
+
191
214
  --------------------------
192
215
 
193
216
  Version 1.10 is a minor bug-fix release, the most important one
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #! /usr/bin/ruby1.8
2
2
  require 'Tioga/tioga_ui.rb'
3
3
 
4
4
 
@@ -25,15 +25,16 @@
25
25
  #include <stdlib.h>
26
26
  #include <ctype.h>
27
27
  #include <math.h>
28
- #include "intern.h"
29
28
 
30
- #include "../symbols.h"
31
- #include "../symbols.c"
29
+ /* Internal include files, from the ext/includes directory */
30
+ #include <symbols.h>
31
+ #include <symbols.c>
32
32
 
33
33
  #include <defs.h>
34
34
 
35
35
  /* safe storing of doubles */
36
36
  #include <safe_double.h>
37
+ /* End of internal files */
37
38
 
38
39
 
39
40
  #define is_a_dtable(d) ( TYPE(d) == T_DATA && RDATA(d)->dfree == (RUBY_DATA_FUNC)dtable_free )
@@ -406,7 +407,7 @@ PRIVATE
406
407
  row_num = rb_Integer(row_num);
407
408
  int row = NUM2INT(row_num);
408
409
  if (row < 0 || row >= d->num_rows)
409
- rb_raise(rb_eArgError, "Asking for row i = %i from array with only %i rows", row, d->num_rows);
410
+ rb_raise(rb_eArgError, "Asking for row i = %i from array with only %li rows", row, d->num_rows);
410
411
  VALUE dvec = Dvector_Create();
411
412
  Dvector_Data_Replace(dvec, d->num_cols, d->ptr[row]);
412
413
  return dvec;
@@ -426,14 +427,31 @@ PRIVATE
426
427
  row_num = rb_Integer(row_num);
427
428
  int row = NUM2INT(row_num);
428
429
  if (row < 0 || row >= d->num_rows)
429
- rb_raise(rb_eArgError, "Asking for row i = %i from array with only %i rows", row, d->num_rows);
430
+ rb_raise(rb_eArgError, "Asking for row i = %i from array with only %li rows", row, d->num_rows);
430
431
  if (len != d->num_cols)
431
- rb_raise(rb_eArgError, "Length of vector (%i) does not match number of columns (%i)", len, d->num_cols);
432
+ rb_raise(rb_eArgError, "Length of vector (%li) does not match number of columns (%li)", len, d->num_cols);
432
433
  for (j=0; j < len; j++)
433
434
  d->ptr[row][j] = data[j];
434
435
  return dvec;
435
436
  }
436
437
 
438
+ PRIVATE
439
+ /*
440
+ * call-seq:
441
+ * dtable.each_row{|row| }
442
+ *
443
+ * Iterates over all rows and executes the given block
444
+ */ VALUE dtable_each_row(VALUE ary){
445
+ Dtable *d = Get_Dtable(ary);
446
+ VALUE dvec = Dvector_Create();
447
+ int i;
448
+ for(i=0; i < d->num_rows; i++){
449
+ Dvector_Data_Replace(dvec, d->num_cols, d->ptr[i]);
450
+ rb_yield(dvec);
451
+ }
452
+ return ary;
453
+ }
454
+
437
455
  PRIVATE
438
456
  /*
439
457
  * call-seq:
@@ -448,9 +466,9 @@ PRIVATE
448
466
  col_num = rb_Integer(col_num);
449
467
  int col = NUM2INT(col_num);
450
468
  if (col < 0 || col >= d->num_cols)
451
- rb_raise(rb_eArgError, "Asking for column i = %i from array with only %i columns", col, d->num_cols);
469
+ rb_raise(rb_eArgError, "Asking for column i = %i from array with only %li columns", col, d->num_cols);
452
470
  if (len != d->num_rows)
453
- rb_raise(rb_eArgError, "Length of vector (%i) does not match number of rows (%i)", len, d->num_rows);
471
+ rb_raise(rb_eArgError, "Length of vector (%li) does not match number of rows (%li)", len, d->num_rows);
454
472
  for (i=0; i < len; i++)
455
473
  d->ptr[i][col] = data[i];
456
474
  return dvec;
@@ -467,7 +485,7 @@ PRIVATE
467
485
  column_num = rb_Integer(column_num);
468
486
  int i, column = NUM2INT(column_num), len;
469
487
  if (column < 0 || column >= d->num_cols)
470
- rb_raise(rb_eArgError, "Asking for column i = %i from array with only %i columns", column, d->num_cols);
488
+ rb_raise(rb_eArgError, "Asking for column i = %i from array with only %li columns", column, d->num_cols);
471
489
  VALUE dvec = Dvector_Create();
472
490
  len = d->num_rows;
473
491
  Dvector_Data_Resize(dvec, len);
@@ -476,6 +494,25 @@ PRIVATE
476
494
  return dvec;
477
495
  }
478
496
 
497
+ PRIVATE
498
+ /*
499
+ * call-seq:
500
+ * dtable.each_column{|col| }
501
+ *
502
+ * Iterates over all columns and executes the given block
503
+ */ VALUE dtable_each_column(VALUE ary){
504
+ Dtable *d = Get_Dtable(ary);
505
+ VALUE dvec = Dvector_Create();
506
+ int i,j;
507
+ for(j=0; j < d->num_cols; j++){
508
+ for(i=0; i < d->num_rows; i++){
509
+ Dvector_Store_Double(dvec, i, d->ptr[i][j]);
510
+ }
511
+ rb_yield(dvec);
512
+ }
513
+ return ary;
514
+ }
515
+
479
516
  static void set_dtable_vals(VALUE ary, double v) {
480
517
  Dtable *d = Get_Dtable(ary);
481
518
  int num_cols = d->num_cols, num_rows = d->num_rows, i, j;
@@ -1576,7 +1613,7 @@ PRIVATE
1576
1613
  printf("len %i\n", len);
1577
1614
  strncpy(err_str,buff,len);
1578
1615
  rb_raise(rb_eArgError,
1579
- "failed to read requested amount of data in %s (asked for %i xs and %i ys; found only %i and %i). last attempt to read got %g from string starting with: %s",
1616
+ "failed to read requested amount of data in %s (asked for %li xs and %li ys; found only %i and %i). last attempt to read got %g from string starting with: %s",
1580
1617
  filename, num_cols, num_rows, i+1, j, data[j], err_str);
1581
1618
  }
1582
1619
  }
@@ -1759,13 +1796,13 @@ PRIVATE
1759
1796
  Dtable *d = Get_Dtable(ary);
1760
1797
  int nx = NUM2DBL(rb_Integer(nx_val));
1761
1798
  int ny = NUM2DBL(rb_Integer(ny_val));
1762
- int i, j, num_cols = d->num_cols, num_rows = d->num_rows, last_row = num_rows - 1;
1799
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows/*, last_row = num_rows - 1*/;
1763
1800
 
1764
1801
  long xsrc_len, ysrc_len;
1765
1802
  double *xsrc = Dvector_Data_for_Read(x_vec, &xsrc_len);
1766
1803
  double *ysrc = Dvector_Data_for_Read(y_vec, &ysrc_len);
1767
- if(xsrc_len != num_cols) rb_raise(rb_eArgError, "Number of x values (%d) do not match the number of columns (%d)", xsrc_len, num_cols);
1768
- if(ysrc_len != num_rows) rb_raise(rb_eArgError, "Number of y values (%d) do not match the number of rows (%d)", ysrc_len, num_rows);
1804
+ if(xsrc_len != num_cols) rb_raise(rb_eArgError, "Number of x values (%ld) do not match the number of columns (%d)", xsrc_len, num_cols);
1805
+ if(ysrc_len != num_rows) rb_raise(rb_eArgError, "Number of y values (%ld) do not match the number of rows (%d)", ysrc_len, num_rows);
1769
1806
  VALUE new = dtable_init(dtable_alloc(cDtable), nx, ny);
1770
1807
  Dtable *d2 = Get_Dtable(new);
1771
1808
  double **src, **dest;
@@ -1811,6 +1848,34 @@ PRIVATE
1811
1848
  return new;
1812
1849
  }
1813
1850
 
1851
+ PRIVATE
1852
+ /*
1853
+ * call-seq:
1854
+ * dtable.sum -> number
1855
+ *
1856
+ * Returns the sum of the entries in _dtable_. Returns 0.0 if
1857
+ * _dtable_ is empty.
1858
+ *
1859
+ * a = Dtable.new(2,4)
1860
+ * a.set_column(0, Dvector[1,2,3,4])
1861
+ * a.set_column(1, Dvector[0, 1, 0, 1])
1862
+ * a.sum -> 12.0
1863
+ * Dtable.new(2,2).sum -> 0.0
1864
+ */
1865
+ VALUE dtable_sum(VALUE tabl){
1866
+ int i,j;
1867
+ double sum=0.0;
1868
+ double **src;
1869
+ Dtable *d = Get_Dtable(tabl);
1870
+ src = d->ptr;
1871
+ for(i=0; i < d->num_cols; i++){
1872
+ for(j=0; j < d->num_rows; j++){
1873
+ sum = sum + src[j][i];
1874
+ }
1875
+ }
1876
+ return rb_float_new(sum);
1877
+ }
1878
+
1814
1879
  /*
1815
1880
  * Document-class: Dobjects::Dtable
1816
1881
  *
@@ -1819,8 +1884,6 @@ PRIVATE
1819
1884
  * Essentially any of the operations you might do with a Ruby Array of numbers can also be done with a Dtable.
1820
1885
  * Dtables follow the same design philosophy as Dvector and uses Dvectors for several operations.
1821
1886
  */
1822
-
1823
-
1824
1887
  PUBLIC void Init_Dtable() {
1825
1888
  /* modified by Vincent Fourmond, for splitting out the libraries */
1826
1889
 
@@ -1968,6 +2031,9 @@ PUBLIC void Init_Dtable() {
1968
2031
  rb_define_method(cDtable, "safe_acos!", dtable_safe_acos_bang, 0);
1969
2032
 
1970
2033
  rb_define_method(cDtable, "interpolate", dtable_interpolate, 8);
2034
+ rb_define_method(cDtable, "sum", dtable_sum, 0);
2035
+ rb_define_method(cDtable, "each_row", dtable_each_row, 0);
2036
+ rb_define_method(cDtable, "each_column", dtable_each_column, 0);
1971
2037
 
1972
2038
  /* Marshal : */
1973
2039
  rb_define_method(cDtable, "_dump", dtable_dump, 1);
File without changes
@@ -0,0 +1,7 @@
1
+ # Dtable installation file
2
+ require 'mkmf'
3
+
4
+ # We add include directories
5
+ $INCFLAGS += " -I../../includes -I../Dvector/include"
6
+
7
+ create_makefile 'Dobjects/Dtable'
File without changes
@@ -27,11 +27,12 @@
27
27
  #include <ctype.h>
28
28
  #include <math.h>
29
29
  #include "ruby.h"
30
- #include "intern.h"
31
30
  #include "dvector_intern.h"
32
31
 
33
- #include "../symbols.h"
34
- #include "../symbols.c"
32
+
33
+ /* Internal files that are defined in the ext/includes directory */
34
+ #include <symbols.h>
35
+ #include <symbols.c>
35
36
 
36
37
  /* compiler-dependent definitions, such as is_okay_number */
37
38
  #include <defs.h>
@@ -39,8 +40,8 @@
39
40
  /* safe storing of doubles */
40
41
  #include <safe_double.h>
41
42
 
42
- /* temp */
43
- /* #include <stdio.h> */
43
+ /* End of internal files */
44
+
44
45
  #define is_a_dvector(d) ( TYPE(d) == T_DATA && RDATA(d)->dfree == (RUBY_DATA_FUNC)dvector_free )
45
46
 
46
47
  #ifndef MAX
@@ -119,8 +120,8 @@ static VALUE dvector_alloc(VALUE klass) {
119
120
  Dvector *d;
120
121
  VALUE ary = Data_Make_Struct(klass, Dvector, dvector_mark, dvector_free, d);
121
122
  d->len = 0;
122
- d->ptr = ALLOC_N(double, 1);
123
- d->capa = 1;
123
+ d->ptr = NULL;
124
+ d->capa = 0;
124
125
  d->shared = Qnil;
125
126
  return ary;
126
127
  }
@@ -187,7 +188,7 @@ static void dvector_store(VALUE ary, long idx, VALUE val) {
187
188
  static VALUE dvector_to_dvector(VALUE obj) {
188
189
  if ( is_a_dvector(obj) ) return obj;
189
190
  obj = rb_Array(obj);
190
- return dvector_s_create(RARRAY(obj)->len, RARRAY(obj)->ptr, cDvector);
191
+ return dvector_s_create(RARRAY_LEN(obj), RARRAY_PTR(obj), cDvector);
191
192
  }
192
193
 
193
194
  static Dvector *Get_Dvector(VALUE obj) {
@@ -910,7 +911,7 @@ static void dvector_splice(VALUE ary, long beg, long len, VALUE rpl) {
910
911
  rlen = 0;
911
912
  } else if (rb_obj_is_kind_of(rpl,rb_cArray)) {
912
913
  rpl = rb_Array(rpl);
913
- rlen = RARRAY(rpl)->len;
914
+ rlen = RARRAY_LEN(rpl);
914
915
  } else {
915
916
  rpl = dvector_to_dvector(rpl);
916
917
  r = Get_Dvector(rpl);
@@ -925,7 +926,7 @@ static void dvector_splice(VALUE ary, long beg, long len, VALUE rpl) {
925
926
  dvector_mem_clear(d->ptr + d->len, beg - d->len);
926
927
  if (rlen > 0) {
927
928
  if (r != NULL) MEMCPY(d->ptr + beg, r->ptr, double, rlen);
928
- else ary_to_dvector(RARRAY(rpl)->ptr, rlen, d->ptr);
929
+ else ary_to_dvector(RARRAY_PTR(rpl), rlen, d->ptr);
929
930
  }
930
931
  d->len = len;
931
932
  } else {
@@ -944,7 +945,7 @@ static void dvector_splice(VALUE ary, long beg, long len, VALUE rpl) {
944
945
  }
945
946
  if (rlen > 0) {
946
947
  if (r != NULL) MEMMOVE(d->ptr + beg, r->ptr, double, rlen);
947
- else ary_to_dvector(RARRAY(rpl)->ptr, rlen, d->ptr + beg);
948
+ else ary_to_dvector(RARRAY_PTR(rpl), rlen, d->ptr + beg);
948
949
  }
949
950
  }
950
951
  }
@@ -1190,7 +1191,7 @@ PRIVATE
1190
1191
  Dvector *d2 = Get_Dvector(ary2);
1191
1192
  long i;
1192
1193
  if (d->len != d2->len) {
1193
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for each2", d->len, d2->len);
1194
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for each2", d->len, d2->len);
1194
1195
  }
1195
1196
  for (i=0; i < d->len; i++) {
1196
1197
  rb_yield_values(2, rb_float_new(d->ptr[i]), rb_float_new(d2->ptr[i]));
@@ -1258,7 +1259,7 @@ PRIVATE
1258
1259
  Dvector *d2 = Get_Dvector(ary2);
1259
1260
  long i;
1260
1261
  if (d->len != d2->len) {
1261
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for each2_with_index", d->len, d2->len);
1262
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for each2_with_index", d->len, d2->len);
1262
1263
  }
1263
1264
  for (i=0; i < d->len; i++) {
1264
1265
  rb_yield_values(3, rb_float_new(d->ptr[i]), rb_float_new(d2->ptr[i]), LONG2NUM(i));
@@ -1312,7 +1313,7 @@ PRIVATE
1312
1313
  Dvector *d2 = Get_Dvector(ary2);
1313
1314
  long len = d->len;
1314
1315
  if (len != d2->len) {
1315
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for reverse_each2", len, d2->len);
1316
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for reverse_each2", len, d2->len);
1316
1317
  }
1317
1318
  while (len--) {
1318
1319
  rb_yield_values(2, rb_float_new(d->ptr[len]), rb_float_new(d2->ptr[len]));
@@ -1395,7 +1396,7 @@ PRIVATE
1395
1396
  Dvector *d2 = Get_Dvector(ary2);
1396
1397
  long len = d->len;
1397
1398
  if (len != d2->len) {
1398
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for reverse_each2_with_index",
1399
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for reverse_each2_with_index",
1399
1400
  len, d2->len);
1400
1401
  }
1401
1402
  while (len--) {
@@ -1522,7 +1523,7 @@ PRIVATE
1522
1523
  gam[j] = c[j-1] / bet;
1523
1524
  bet = b[j] - a[j]*gam[j];
1524
1525
  if (bet == 0.0) {
1525
- rb_raise(rb_eArgError, "zero divisor in tridag (j=%i)", j);
1526
+ rb_raise(rb_eArgError, "zero divisor in tridag (j=%ld)", j);
1526
1527
  }
1527
1528
  u[j] = (r[j] - a[j]*u[j-1]) / bet;
1528
1529
  }
@@ -1632,7 +1633,7 @@ static VALUE dvector_sort_internal(VALUE ary) {
1632
1633
  else {
1633
1634
  ary2 = dvector_to_a(ary);
1634
1635
  ary2 = rb_ary_sort_bang(ary2);
1635
- ary_to_dvector(RARRAY(ary2)->ptr, d->len, d->ptr);
1636
+ ary_to_dvector(RARRAY_PTR(ary2), d->len, d->ptr);
1636
1637
  }
1637
1638
  return ary;
1638
1639
  }
@@ -1727,7 +1728,7 @@ PRIVATE
1727
1728
  return dvector_new4_dbl(d->len, d->ptr);
1728
1729
  }
1729
1730
  ary = rb_Array(ary);
1730
- return dvector_new4(d->len, RARRAY(ary)->ptr);
1731
+ return dvector_new4(d->len, RARRAY_PTR(ary));
1731
1732
  }
1732
1733
  collect = dvector_new2(0,d->len);
1733
1734
  for (i = 0; i < d->len; i++) {
@@ -1755,7 +1756,7 @@ PRIVATE
1755
1756
  Dvector *d = Get_Dvector(ary);
1756
1757
  Dvector *d2 = Get_Dvector(ary2);
1757
1758
  if (d->len != d2->len) {
1758
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for collect2", d->len, d2->len);
1759
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for collect2", d->len, d2->len);
1759
1760
  }
1760
1761
  if (!rb_block_given_p()) {
1761
1762
  return dvector_collect(ary);
@@ -1813,7 +1814,7 @@ VALUE dvector_collect2_bang(VALUE ary, VALUE ary2) {
1813
1814
  Dvector *d = dvector_modify(ary);
1814
1815
  Dvector *d2 = Get_Dvector(ary2);
1815
1816
  if (d->len != d2->len) {
1816
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for collect2!", d->len, d2->len);
1817
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for collect2!", d->len, d2->len);
1817
1818
  }
1818
1819
  for (i = 0; i < d->len; i++) {
1819
1820
  dvector_store(ary, i, rb_yield_values(2, rb_float_new(d->ptr[i]), rb_float_new(d2->ptr[i])));
@@ -2014,8 +2015,8 @@ VALUE dvector_prune_bang(VALUE ary, VALUE lst) {
2014
2015
  int i, lst_len, ary_len, pos, j;
2015
2016
  VALUE *lst_ptr;
2016
2017
  lst = rb_Array(lst);
2017
- lst_ptr = RARRAY(lst)->ptr;
2018
- lst_len = RARRAY(lst)->len;
2018
+ lst_ptr = RARRAY_PTR(lst);
2019
+ lst_len = RARRAY_LEN(lst);
2019
2020
  for (i = lst_len-1; i >= 0; i--) {
2020
2021
  ary_len = d->len;
2021
2022
  pos = NUM2INT(lst_ptr[i]); // remove this one from ary
@@ -3011,7 +3012,7 @@ VALUE dvector_dot(VALUE ary1, VALUE ary2) {
3011
3012
  double *p1 = d1->ptr, *p2 = d2->ptr, sum = 0.0;
3012
3013
  long len = d1->len, i;
3013
3014
  if (len != d2->len) {
3014
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) for dot", d1->len, d2->len);
3015
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) for dot", d1->len, d2->len);
3015
3016
  }
3016
3017
  for (i=0; i<len; i++) sum += p1[i] * p2[i];
3017
3018
  return rb_float_new(sum);
@@ -4079,7 +4080,7 @@ VALUE dvector_apply_math_op2_bang(VALUE ary1, VALUE ary2, double (*op)(double, d
4079
4080
  double *p1 = d1->ptr, *p2 = d2->ptr;
4080
4081
  long len = d1->len, i;
4081
4082
  if (len != d2->len) {
4082
- rb_raise(rb_eArgError, "vectors with different lengths (%d vs %d) math operation", d1->len, d2->len);
4083
+ rb_raise(rb_eArgError, "vectors with different lengths (%ld vs %ld) math operation", d1->len, d2->len);
4083
4084
  }
4084
4085
  for (i=0; i<len; i++) p1[i] = (*op)(p1[i], p2[i]);
4085
4086
  return ary1;
@@ -4446,8 +4447,8 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
4446
4447
  if ((last_row_of_file != -1 && last_row_of_file < first_row_of_file) || filename == NULL) return false;
4447
4448
  if (destinations != Qnil) {
4448
4449
  cols_obj = rb_Array(destinations);
4449
- num_cols = RARRAY(cols_obj)->len;
4450
- cols_ptr = RARRAY(cols_obj)->ptr;
4450
+ num_cols = RARRAY_LEN(cols_obj);
4451
+ cols_ptr = RARRAY_PTR(cols_obj);
4451
4452
  for (i = 0; i < num_cols; i++) { /* first pass to check validity */
4452
4453
  col_obj = cols_ptr[i];
4453
4454
  if (col_obj == Qnil) continue;
@@ -4494,8 +4495,8 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
4494
4495
  }
4495
4496
  if (row == 0) {
4496
4497
  cols_obj = rb_Array(destinations);
4497
- num_cols = RARRAY(cols_obj)->len;
4498
- cols_ptr = RARRAY(cols_obj)->ptr;
4498
+ num_cols = RARRAY_LEN(cols_obj);
4499
+ cols_ptr = RARRAY_PTR(cols_obj);
4499
4500
  }
4500
4501
  buff_loc = 0;
4501
4502
  for (col = 0; col < num_cols; col++) {
@@ -4592,8 +4593,8 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
4592
4593
  char *buff, *num_str, *pend, c, *cptr;
4593
4594
  int num_rows = 0, i, row, col, buff_loc, skip = first_row_of_file - 1;
4594
4595
  rows_obj = rb_Array(destinations);
4595
- num_rows = RARRAY(rows_obj)->len;
4596
- rows_ptr = RARRAY(rows_obj)->ptr;
4596
+ num_rows = RARRAY_LEN(rows_obj);
4597
+ rows_ptr = RARRAY_PTR(rows_obj);
4597
4598
  for (i = 0; i < num_rows; i++) { /* first pass to check validity */
4598
4599
  row_obj = rows_ptr[i];
4599
4600
  if (row_obj == Qnil) continue;
@@ -4854,7 +4855,7 @@ double *Dvector_Data_Replace(VALUE dvector, long len, double *data) { /* copies
4854
4855
  return dvector_replace_dbls(dvector, len, data); }
4855
4856
  PRIVATE
4856
4857
  VALUE Dvector_Create(void) { return dvector_new(); }
4857
-
4858
+ /*
4858
4859
  PRIVATE int Find_First_Both_Greater(VALUE Xs, VALUE Ys, double x, double y) {
4859
4860
  int i;
4860
4861
  long xlen, ylen;
@@ -4882,7 +4883,7 @@ PRIVATE int Find_First_Both_Smaller(VALUE Xs, VALUE Ys, double x, double y) {
4882
4883
  }
4883
4884
  return -1;
4884
4885
  }
4885
-
4886
+ */
4886
4887
  PRIVATE
4887
4888
  VALUE c_make_bezier_control_points_for_cubic_in_x(VALUE dest, double x0, double y0, double delta_x, double a, double b, double c)
4888
4889
  {
@@ -5011,7 +5012,6 @@ VALUE dvector_create_pm_cubic_interpolant(int argc, VALUE *argv, VALUE klass) {
5011
5012
  klass = Qnil;
5012
5013
  VALUE Xs = argv[0], Ys = argv[1];
5013
5014
  long xdlen, ydlen;
5014
- double start = 0.0, end = 0.0;
5015
5015
  double *X_data = Dvector_Data_for_Read(Xs, &xdlen);
5016
5016
  double *Y_data = Dvector_Data_for_Read(Ys, &ydlen);
5017
5017
  if (X_data == NULL || Y_data == NULL || xdlen != ydlen)
@@ -5060,7 +5060,7 @@ VALUE dvector_pm_cubic_interpolate(int argc, VALUE *argv, VALUE klass) {
5060
5060
  VALUE interpolant = argv[1];
5061
5061
  x = rb_Float(x);
5062
5062
  interpolant = rb_Array(interpolant);
5063
- if (RARRAY(interpolant)->len != 5)
5063
+ if (RARRAY_LEN(interpolant) != 5)
5064
5064
  rb_raise(rb_eArgError, "interpolant must be array of length 5 from create_pm_cubic_interpolant");
5065
5065
  Dvector *Xs = Get_Dvector(rb_ary_entry(interpolant,0));
5066
5066
  Dvector *Ys = Get_Dvector(rb_ary_entry(interpolant,1));
@@ -5189,7 +5189,7 @@ VALUE dvector_spline_interpolate(int argc, VALUE *argv, VALUE klass) {
5189
5189
  VALUE interpolant = argv[1];
5190
5190
  x = rb_Float(x);
5191
5191
  interpolant = rb_Array(interpolant);
5192
- if (RARRAY(interpolant)->len != 5)
5192
+ if (RARRAY_LEN(interpolant) != 5)
5193
5193
  rb_raise(rb_eArgError, "Spline interpolant must be array of length 5 from create_spline_interpolant");
5194
5194
  Dvector *Xs = Get_Dvector(rb_ary_entry(interpolant,0));
5195
5195
  Dvector *Ys = Get_Dvector(rb_ary_entry(interpolant,1));
@@ -5232,7 +5232,7 @@ VALUE dvector_linear_interpolate(int argc, VALUE *argv, VALUE klass) {
5232
5232
  Dvector *X_data = Get_Dvector(Xs);
5233
5233
  Dvector *Y_data = Get_Dvector(Ys);
5234
5234
  if (X_data->len <= 0 || X_data->len != Y_data->len)
5235
- rb_raise(rb_eArgError, "Xs and Ys for linear_interpolate must be equal length Dvectors: xlen %i ylen %i.",
5235
+ rb_raise(rb_eArgError, "Xs and Ys for linear_interpolate must be equal length Dvectors: xlen %ld ylen %ld.",
5236
5236
  X_data->len, Y_data->len);
5237
5237
  x = rb_Float(x);
5238
5238
  double y = c_dvector_linear_interpolate(X_data->len, X_data->ptr, Y_data->ptr, NUM2DBL(x));
@@ -5255,8 +5255,8 @@ VALUE dvector_min_of_many(VALUE klass, VALUE ary) {
5255
5255
  double m=0.0, tmp;
5256
5256
  bool found_one = false;
5257
5257
  ary = rb_Array(ary);
5258
- ary_ptr = RARRAY(ary)->ptr;
5259
- ary_len = RARRAY(ary)->len;
5258
+ ary_ptr = RARRAY_PTR(ary);
5259
+ ary_len = RARRAY_LEN(ary);
5260
5260
  if (ary_len == 0) return Qnil;
5261
5261
  for (i = 0; i < ary_len; i++) {
5262
5262
  if (ary_ptr[i] == Qnil) continue;
@@ -5289,8 +5289,8 @@ VALUE dvector_max_of_many(VALUE klass, VALUE ary) {
5289
5289
  double m=0.0, tmp;
5290
5290
  bool found_one = false;
5291
5291
  ary = rb_Array(ary);
5292
- ary_ptr = RARRAY(ary)->ptr;
5293
- ary_len = RARRAY(ary)->len;
5292
+ ary_ptr = RARRAY_PTR(ary);
5293
+ ary_len = RARRAY_LEN(ary);
5294
5294
  if (ary_len == 0) return Qnil;
5295
5295
  for (i = 0; i < ary_len; i++) {
5296
5296
  if (ary_ptr[i] == Qnil) continue;
@@ -5496,14 +5496,17 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
5496
5496
  number of the line read
5497
5497
  * 'remove_space': whether to remove spaces at the beginning of a line. *This
5498
5498
  option is currently not implemented !*
5499
+ * 'comment_out': this should be an array into which the comments
5500
+ will be dumped one by one.
5499
5501
  * 'default': what to put when nothing was found but a number must be used
5500
5502
 
5501
- As a side note, the read time is highly non-linear, which suggests that
5502
- the read is memory-allocation/copying-limited, at least for big files.
5503
+ In addition to these options that control the output, here are a few
5504
+ others to tune memory allocation; these can strongly improve the
5505
+ performance (or make it worse if you wish):
5503
5506
 
5504
- An internal memory allocation with aggressive policy should solve that,
5505
- that is, not using directly Dvectors (and it would be way faster to store
5506
- anyway).
5507
+ * 'initial_size': the initial size of the memory buffers: if there
5508
+ are not more lines than that, no additional memory allocation/copy
5509
+ occurs.
5507
5510
  */
5508
5511
  static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5509
5512
  {
@@ -5512,12 +5515,13 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5512
5515
  rb_str_new2("default")));
5513
5516
  int remove_space = RTEST(rb_hash_aref(options,
5514
5517
  rb_str_new2("remove_space")));
5515
- int index_col = RTEST(rb_hash_aref(options,
5516
- rb_str_new2("index_col")));
5518
+ // int index_col = RTEST(rb_hash_aref(options,
5519
+ // rb_str_new2("index_col")));
5517
5520
  long skip_first = FIX2LONG(rb_hash_aref(options,
5518
5521
  rb_str_new2("skip_first")));
5519
5522
  VALUE sep = rb_hash_aref(options, rb_str_new2("sep"));
5520
5523
  VALUE comments = rb_hash_aref(options, rb_str_new2("comments"));
5524
+ VALUE comment_out = rb_hash_aref(options, rb_str_new2("comment_out"));
5521
5525
 
5522
5526
  /* Then, some various variables: */
5523
5527
  VALUE line;
@@ -5527,13 +5531,19 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5527
5531
  long line_number = 0;
5528
5532
 
5529
5533
  /*
5530
- Now come the fun part - rudimentary vectors management
5534
+ Now come the fun part - rudimentary vectors management
5535
+
5536
+ TODO: if the stream provides functionality to get its total size,
5537
+ it could be interesting to estimate the total number of lines
5538
+ based on some small heuristics
5531
5539
  */
5532
5540
  int nb_vectors = 0; /* The number of vectors currently created */
5533
5541
  int current_size = 10; /* The number of slots available */
5534
5542
  double ** vectors = ALLOC_N(double *, current_size);
5535
5543
  long index = 0; /* The current index in the vectors */
5536
- int allocated_size = 5004; /* The size available in the vectors */
5544
+ /* The size available in the vectors */
5545
+ int allocated_size =
5546
+ FIX2LONG(rb_hash_aref(options, rb_str_new2("initial_size")));
5537
5547
 
5538
5548
 
5539
5549
  int i;
@@ -5541,7 +5551,7 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5541
5551
  /* The return value */
5542
5552
  VALUE ary;
5543
5553
 
5544
- /* We use a real gets so we can also rely on StringIO, for instance */
5554
+ /* We use a real gets so we can also use StringIO, for instance */
5545
5555
  while(RTEST(line = rb_funcall(stream, gets_id, 0))) {
5546
5556
  VALUE pre, post, match;
5547
5557
  const char * line_ptr;
@@ -5564,8 +5574,11 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5564
5574
  line = rb_str_new2(line_ptr);
5565
5575
 
5566
5576
  /* ... or a comment line */
5567
- if(RTEST(comments) && RTEST(rb_reg_match(comments, line)))
5577
+ if(RTEST(comments) && RTEST(rb_reg_match(comments, line))) {
5578
+ if(RTEST(comment_out))
5579
+ rb_ary_push(comment_out, line);
5568
5580
  continue;
5581
+ }
5569
5582
 
5570
5583
  /* Then, we remove the newline: */
5571
5584
  post = line;
@@ -5630,6 +5643,288 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5630
5643
  return ary;
5631
5644
  }
5632
5645
 
5646
+ /*
5647
+ Returns a list of local extrema of the vector, organized thus:
5648
+
5649
+ [ [:min, idmin1], [:max, idmax1], ...]
5650
+
5651
+ The values are pushed in the order in which they are found. It works
5652
+ thus: it scans the vector and looks around the current point in a
5653
+ given window. If the current point is the maximum or the minimum, it
5654
+ is considered as a local maximum/minimum. Control over which extrema
5655
+ are included is given to the used through threshold mechanisms.
5656
+
5657
+ The _options_ hash controls how the peaks are detected:
5658
+ * _window_: the number of elements on which we look on
5659
+ both sides (default 5, ie the local maximum is over 11 points)
5660
+ * _threshold_: the minimum amplitude the extrema must have to
5661
+ be considered (default 0)
5662
+ * _dthreshold_: how much over/under the average an extremum must be
5663
+ (default 0)
5664
+ * _or_: whether the _threshold_ and _dthreshold_ tests are both
5665
+ necessary or if only one is (default false: both tests are
5666
+ necessary)
5667
+
5668
+ *Note:* beware of NANs ! They *will* screw up peak detection, as
5669
+ they are neither bigger nor smaller than anything...
5670
+ */
5671
+ static VALUE dvector_extrema(int argc, VALUE *argv, VALUE self)
5672
+ {
5673
+ long window = 5;
5674
+ double threshold = 0;
5675
+ double dthreshold = 0;
5676
+ int inclusive = 1;
5677
+
5678
+ if(argc == 1) {
5679
+ VALUE t;
5680
+ t = rb_hash_aref(argv[0], rb_str_new2("window"));
5681
+ if(RTEST(t)) {
5682
+ window = FIX2LONG(t);
5683
+ }
5684
+ t = rb_hash_aref(argv[0], rb_str_new2("threshold"));
5685
+ if(RTEST(t)) {
5686
+ threshold = rb_num2dbl(t);
5687
+ }
5688
+ t = rb_hash_aref(argv[0], rb_str_new2("dthreshold"));
5689
+ if(RTEST(t)) {
5690
+ dthreshold = rb_num2dbl(t);
5691
+ }
5692
+
5693
+ t = rb_hash_aref(argv[0], rb_str_new2("or"));
5694
+ inclusive = ! RTEST(t);
5695
+ } else if(argc > 1)
5696
+ rb_raise(rb_eArgError, "Dvector.extrema only takes 0 or 1 argument");
5697
+
5698
+ /* Handling of the vector */
5699
+ long len, i,j;
5700
+ double * data = Dvector_Data_for_Read(self, &len);
5701
+ VALUE s_min = ID2SYM(rb_intern("min"));
5702
+ VALUE s_max = ID2SYM(rb_intern("max"));
5703
+
5704
+
5705
+
5706
+ VALUE ret = rb_ary_new();
5707
+
5708
+ for(i = 0; i < len; i++) {
5709
+
5710
+ /* This is stupid and will need decent optimization when I have
5711
+ time */
5712
+ long first = i > window ? i - window : 0;
5713
+ double cur_min = data[first];
5714
+ long cur_min_idx = first;
5715
+ double cur_max = data[first];
5716
+ long cur_max_idx = first;
5717
+ double average = 0;
5718
+ long nb = 0;
5719
+
5720
+ for(j = first; (j < i+window) && (j < len); j++,nb++) {
5721
+ average += data[j];
5722
+ if(data[j] <= cur_min) {
5723
+ cur_min = data[j];
5724
+ cur_min_idx = j;
5725
+ }
5726
+ if(data[j] >= cur_max) {
5727
+ cur_max = data[j];
5728
+ cur_max_idx = j;
5729
+ }
5730
+ }
5731
+ average /= nb;
5732
+
5733
+ if(cur_min_idx == i) {
5734
+ /* This is a potential minimum */
5735
+ if((inclusive &&
5736
+ (fabs(cur_min) >= threshold) &&
5737
+ (fabs(cur_min - average) >= dthreshold))
5738
+ || (!inclusive &&
5739
+ ((fabs(cur_min) >= threshold) ||
5740
+ (fabs(cur_min - average) >= dthreshold))
5741
+ )) {
5742
+ VALUE min = rb_ary_new();
5743
+ rb_ary_push(min, s_min);
5744
+ rb_ary_push(min, LONG2FIX(i));
5745
+ rb_ary_push(ret, min);
5746
+ }
5747
+ }
5748
+ else if(cur_max_idx == i) {
5749
+ /* A potential maximum */
5750
+ if((inclusive &&
5751
+ (fabs(cur_max) >= threshold) &&
5752
+ (fabs(cur_max - average) >= dthreshold))
5753
+ || (!inclusive &&
5754
+ ((fabs(cur_max) >= threshold) ||
5755
+ (fabs(cur_max - average) >= dthreshold))
5756
+ )) {
5757
+ VALUE max = rb_ary_new();
5758
+ rb_ary_push(max, s_max);
5759
+ rb_ary_push(max, LONG2FIX(i));
5760
+ rb_ary_push(ret, max);
5761
+ }
5762
+ }
5763
+ }
5764
+ return ret;
5765
+ }
5766
+
5767
+ /* This is the FFTW-based part of the game */
5768
+ #ifdef HAVE_FFTW3_H
5769
+ #include <fftw3.h>
5770
+
5771
+ /*
5772
+ Performs an in-place Fourier transform of the vector. The results
5773
+ is stored in the so-called "half-complex" format (see
5774
+ http://www.fftw.org/fftw3_doc/The-Halfcomplex_002dformat-DFT.html
5775
+ for more information).
5776
+
5777
+ */
5778
+ static VALUE dvector_fft(VALUE self)
5779
+ {
5780
+ long len;
5781
+ double * values = Dvector_Data_for_Write(self, &len);
5782
+ fftw_plan plan = fftw_plan_r2r_1d(len, values, values,
5783
+ FFTW_R2HC, FFTW_ESTIMATE);
5784
+ fftw_execute(plan);
5785
+ fftw_destroy_plan(plan);
5786
+ return self;
5787
+ }
5788
+
5789
+ /*
5790
+ Performs a reverse in-place Fourier transform of the vector. The
5791
+ original data must have been stored in the so called "half-complex"
5792
+ format (see #fft!).
5793
+ */
5794
+
5795
+ static VALUE dvector_rfft(VALUE self)
5796
+ {
5797
+ long len;
5798
+ double * values = Dvector_Data_for_Write(self, &len);
5799
+ fftw_plan plan = fftw_plan_r2r_1d(len, values, values,
5800
+ FFTW_HC2R, FFTW_ESTIMATE);
5801
+ fftw_execute(plan);
5802
+ fftw_destroy_plan(plan);
5803
+ return self;
5804
+ }
5805
+
5806
+ /*
5807
+ Now, small functions to manipulate the FFTed data:
5808
+ * multiply them
5809
+ * divide them
5810
+ * get (the square of) their module
5811
+ */
5812
+
5813
+
5814
+ /*
5815
+ Returns the power spectra of the ffted data (ie the square of the
5816
+ norm of the complex fourier coefficients.
5817
+
5818
+ The returned value is a new Dvector of size about two times smaller
5819
+ than the original (precisely size/2 + 1)
5820
+
5821
+ For some reasons, convolutions don't work for now.
5822
+ */
5823
+ static VALUE dvector_fft_spectrum(VALUE self)
5824
+ {
5825
+ long len;
5826
+ const double * values = Dvector_Data_for_Read(self, &len);
5827
+ /* First compute the size of the target: */
5828
+ long target_size = len/2+1;
5829
+ long i;
5830
+ VALUE retval = dvector_new2(target_size,target_size);
5831
+ double * ret = Dvector_Data_for_Write(retval,NULL);
5832
+
5833
+ /* Pointer to real and imaginary parts */
5834
+ const double * real;
5835
+ const double * img;
5836
+ ret[0] = values[0] * values[0];
5837
+
5838
+
5839
+ /* The Nyquist frequency */
5840
+ if(len % 2 == 0)
5841
+ ret[target_size - 1] = values[target_size-1] * values[target_size-1];
5842
+ for(i = 1, real = values + 1, img = values + len-1; i < len/2;
5843
+ i++, real++, img--)
5844
+ ret[i] = *real * *real + *img * *img;
5845
+ return retval;
5846
+ }
5847
+
5848
+ /*
5849
+ Converts the FFTed data in the complex conjugate
5850
+ */
5851
+ static VALUE dvector_fft_conj(VALUE self)
5852
+ {
5853
+ long len;
5854
+ double * v1 = Dvector_Data_for_Write(self, &len);
5855
+ double * img;
5856
+ long i;
5857
+ for(i = 1, img = v1 + len-1; i < (len+1)/2;
5858
+ i++, img--)
5859
+ *img = -*img;
5860
+ return self;
5861
+ }
5862
+
5863
+
5864
+ /*
5865
+ Multiplies the FFTed data held in the vector by another vector. The
5866
+ behaviour depends on the size of the target vector:
5867
+
5868
+ * if it is the same size, it is assumed to be FFTed data
5869
+ * if it is the same size of a power spectrum, then it is assumed that it
5870
+ is multiplication by real values
5871
+ * anything else won't make this function happy.
5872
+
5873
+ As a side note, if you only want multiplication by a scalar, the
5874
+ standard #mul! should be what you look for.
5875
+ */
5876
+ static VALUE dvector_fft_mul(VALUE self, VALUE m)
5877
+ {
5878
+ long len;
5879
+ double * v1 = Dvector_Data_for_Write(self, &len);
5880
+ long len2;
5881
+ const double * v2 = Dvector_Data_for_Write(m, &len2);
5882
+ if(len2 == len) { /* Full complex multiplication */
5883
+ const double * m_img;
5884
+ const double * m_real;
5885
+ double * v_img;
5886
+ double * v_real;
5887
+ long i;
5888
+ /* First, special cases */
5889
+ v1[0] *= v2[0];
5890
+ if(len % 2 == 0)
5891
+ v1[len/2] *= v2[len/2];
5892
+
5893
+ for(i = 1, m_real = v2 + 1, m_img = v2 + len-1,
5894
+ v_real = v1 + 1, v_img = v1 + len-1; i < (len+1)/2;
5895
+ i++, m_real++, v_real++, m_img--, v_img--) {
5896
+ double r = *m_real * *v_real - *m_img * *v_img;
5897
+ *v_img = *m_real * *v_img + *v_real * *m_img;
5898
+ *v_real = r;
5899
+ }
5900
+ return self;
5901
+ }
5902
+ else if(len2 == len/2+1) { /* Complex * real*/
5903
+ const double * val;
5904
+ double * v_img;
5905
+ double * v_real;
5906
+ long i;
5907
+ /* First, special cases */
5908
+ v1[0] *= v2[0];
5909
+ if(len % 2 == 0)
5910
+ v1[len/2] *= v2[len/2];
5911
+
5912
+ for(i = 1, val = v2 + 1,
5913
+ v_real = v1 + 1, v_img = v1 + len-1; i < (len+1)/2;
5914
+ i++, val++, v_real++, v_img--) {
5915
+ *v_real *= *val;
5916
+ *v_img *= *val;
5917
+ }
5918
+ return self;
5919
+ }
5920
+ else {
5921
+ rb_raise(rb_eArgError, "incorrect Dvector size for fft_mul!");
5922
+ }
5923
+ }
5924
+
5925
+
5926
+ #endif
5927
+
5633
5928
 
5634
5929
  /*
5635
5930
  * Document-class: Dobjects::Dvector
@@ -5958,6 +6253,21 @@ void Init_Dvector() {
5958
6253
  dvector_fast_fancy_read, 2);
5959
6254
 
5960
6255
 
6256
+ /* Local extrema */
6257
+ rb_define_method(cDvector, "extrema", dvector_extrema, -1);
6258
+
6259
+ /* FFT functions */
6260
+ #ifdef HAVE_FFTW3_H
6261
+
6262
+ rb_define_method(cDvector, "fft!", dvector_fft, 0);
6263
+ rb_define_method(cDvector, "rfft!", dvector_rfft, 0);
6264
+ rb_define_method(cDvector, "fft_spectrum", dvector_fft_spectrum, 0);
6265
+ rb_define_method(cDvector, "fft_mul!", dvector_fft_mul, 1);
6266
+ rb_define_method(cDvector, "fft_conj!", dvector_fft_conj, 0);
6267
+
6268
+ #endif
6269
+
6270
+
5961
6271
  dvector_output_fs = Qnil;
5962
6272
  rb_global_variable(&dvector_output_fs);
5963
6273
  dvector_output_fs = rb_str_new2(" ");