tioga 1.11 → 1.13

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.
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(" ");