tioga 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Tioga_README +372 -0
  2. data/lgpl.txt +504 -0
  3. data/split/Dtable/defs.h +33 -0
  4. data/split/Dtable/dtable.c +1928 -0
  5. data/split/Dtable/dtable_intern.h +144 -0
  6. data/split/Dtable/dvector.h +61 -0
  7. data/split/Dtable/extconf.rb +4 -0
  8. data/split/Dtable/include/dtable.h +35 -0
  9. data/split/Dtable/lib/Dtable_extras.rb +90 -0
  10. data/split/Dtable/namespace.h +47 -0
  11. data/split/Dtable/safe_double.h +104 -0
  12. data/split/Dtable/symbols.c +92 -0
  13. data/split/Dtable/symbols.h +52 -0
  14. data/split/Dvector/defs.h +33 -0
  15. data/split/Dvector/dvector.c +5486 -0
  16. data/split/Dvector/dvector_intern.h +142 -0
  17. data/split/Dvector/extconf.rb +4 -0
  18. data/split/Dvector/include/dvector.h +61 -0
  19. data/split/Dvector/lib/Dvector_extras.rb +328 -0
  20. data/split/Dvector/lib/Numeric_extras.rb +134 -0
  21. data/split/Dvector/namespace.h +47 -0
  22. data/split/Dvector/safe_double.h +104 -0
  23. data/split/Dvector/symbols.c +92 -0
  24. data/split/Dvector/symbols.h +52 -0
  25. data/split/Flate/defs.h +33 -0
  26. data/split/Flate/extconf.rb +19 -0
  27. data/split/Flate/flate.c +156 -0
  28. data/split/Flate/flate_intern.h +97 -0
  29. data/split/Flate/include/flate.h +98 -0
  30. data/split/Flate/namespace.h +47 -0
  31. data/split/Flate/safe_double.h +104 -0
  32. data/split/Flate/symbols.c +92 -0
  33. data/split/Flate/symbols.h +52 -0
  34. data/split/Function/defs.h +33 -0
  35. data/split/Function/dvector.h +61 -0
  36. data/split/Function/extconf.rb +4 -0
  37. data/split/Function/function.c +988 -0
  38. data/split/Function/joint_qsort.c +258 -0
  39. data/split/Function/lib/Function_extras.rb +44 -0
  40. data/split/Function/namespace.h +47 -0
  41. data/split/Function/safe_double.h +104 -0
  42. data/split/Function/symbols.c +92 -0
  43. data/split/Function/symbols.h +52 -0
  44. data/split/Tioga/axes.c +774 -0
  45. data/split/Tioga/defs.h +33 -0
  46. data/split/Tioga/dtable.h +35 -0
  47. data/split/Tioga/dvector.h +61 -0
  48. data/split/Tioga/extconf.rb +4 -0
  49. data/split/Tioga/figures.c +672 -0
  50. data/split/Tioga/figures.h +855 -0
  51. data/split/Tioga/flate.h +98 -0
  52. data/split/Tioga/init.c +524 -0
  53. data/split/Tioga/lib/Arcs_and_Circles.rb +64 -0
  54. data/split/Tioga/lib/ColorConstants.rb +274 -0
  55. data/split/Tioga/lib/Colorbars.rb +10 -0
  56. data/split/Tioga/lib/Colormaps.rb +105 -0
  57. data/split/Tioga/lib/Coordinate_Conversions.rb +194 -0
  58. data/split/Tioga/lib/Creating_Paths.rb +94 -0
  59. data/split/Tioga/lib/Doc.rb +91 -0
  60. data/split/Tioga/lib/Executive.rb +515 -0
  61. data/split/Tioga/lib/FigMkr.rb +2224 -0
  62. data/split/Tioga/lib/FigureConstants.rb +125 -0
  63. data/split/Tioga/lib/Figures_and_Plots.rb +268 -0
  64. data/split/Tioga/lib/Images.rb +278 -0
  65. data/split/Tioga/lib/Legends.rb +190 -0
  66. data/split/Tioga/lib/MarkerConstants.rb +122 -0
  67. data/split/Tioga/lib/Markers.rb +129 -0
  68. data/split/Tioga/lib/Page_Frame_Bounds.rb +567 -0
  69. data/split/Tioga/lib/Rectangles.rb +94 -0
  70. data/split/Tioga/lib/Shading.rb +100 -0
  71. data/split/Tioga/lib/Special_Paths.rb +307 -0
  72. data/split/Tioga/lib/Strokes.rb +129 -0
  73. data/split/Tioga/lib/TeX_Text.rb +454 -0
  74. data/split/Tioga/lib/TexPreamble.rb +358 -0
  75. data/split/Tioga/lib/Titles_and_Labels.rb +306 -0
  76. data/split/Tioga/lib/Transparency.rb +89 -0
  77. data/split/Tioga/lib/Using_Paths.rb +164 -0
  78. data/split/Tioga/lib/Utils.rb +74 -0
  79. data/split/Tioga/lib/X_and_Y_Axes.rb +749 -0
  80. data/split/Tioga/lib/irb_tioga.rb +122 -0
  81. data/split/Tioga/lib/tioga.rb +1 -0
  82. data/split/Tioga/lib/tioga_ui.rb +5 -0
  83. data/split/Tioga/lib/tioga_ui_cmds.rb +793 -0
  84. data/split/Tioga/makers.c +989 -0
  85. data/split/Tioga/mk_tioga_sty.rb +53 -0
  86. data/split/Tioga/namespace.h +47 -0
  87. data/split/Tioga/pdf_font_dicts.c +18253 -0
  88. data/split/Tioga/pdfcolor.c +486 -0
  89. data/split/Tioga/pdfcoords.c +505 -0
  90. data/split/Tioga/pdffile.c +342 -0
  91. data/split/Tioga/pdfimage.c +536 -0
  92. data/split/Tioga/pdfpath.c +914 -0
  93. data/split/Tioga/pdfs.h +229 -0
  94. data/split/Tioga/pdftext.c +443 -0
  95. data/split/Tioga/safe_double.h +104 -0
  96. data/split/Tioga/symbols.c +92 -0
  97. data/split/Tioga/symbols.h +52 -0
  98. data/split/Tioga/texout.c +380 -0
  99. data/split/defs.h +33 -0
  100. data/split/extconf.rb +107 -0
  101. data/split/mkmf2.rb +1612 -0
  102. data/split/namespace.h +47 -0
  103. data/split/safe_double.h +104 -0
  104. data/split/scripts/tioga +4 -0
  105. data/split/symbols.c +92 -0
  106. data/split/symbols.h +52 -0
  107. data/tests/dtable_test.data +6 -0
  108. data/tests/dvector_read_test.data +1 -0
  109. data/tests/dvector_test.data +101 -0
  110. data/tests/tc_Dtable.rb +221 -0
  111. data/tests/tc_Dvector.rb +791 -0
  112. data/tests/tc_FMkr.rb +162 -0
  113. data/tests/tc_Flate.rb +45 -0
  114. data/tests/tc_Function.rb +111 -0
  115. data/tests/ts_Tioga.rb +38 -0
  116. metadata +163 -0
@@ -0,0 +1,33 @@
1
+ /**********************************************************************
2
+
3
+ defs.h:
4
+ some definitions that are used everywhere and that depend on some
5
+ HAVE_* macros.
6
+
7
+ Copyright (C) 2006 Vincent Fourmond
8
+
9
+ This program is free software; you can redistribute it and/or modify
10
+ it under the terms of the GNU General Library Public License as published
11
+ by the Free Software Foundation; either version 2 of the License, or
12
+ (at your option) any later version.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU Library General Public License for more details.
18
+
19
+ You should have received a copy of the GNU Library General Public License
20
+ along with this program; if not, write to the Free Software
21
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
+
23
+ **********************************************************************/
24
+
25
+
26
+ #ifdef HAVE_ISNAN
27
+ /* we use isnan and isinf, which are much faster than the workaround */
28
+ #define is_okay_number(x) (! isnan(x) && ! isinf(x))
29
+ #else
30
+ #define is_okay_number(x) ((x) - (x) == 0.0)
31
+ #define isnan(x) ((x) != (x))
32
+ /* yes, as funny as it may look NaN != NaN, and that's the only one */
33
+ #endif
@@ -0,0 +1,1928 @@
1
+ /* dtable.c */
2
+ /*
3
+ Copyright (C) 2004 Bill Paxton
4
+
5
+ This file is part of Dtable.
6
+
7
+ Dtable is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Library Public License as published
9
+ by the Free Software Foundation; either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Dtable is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Library General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Library General Public License
18
+ along with Dtable; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #include <namespace.h>
23
+ #include "dtable_intern.h"
24
+ #include <stdbool.h>
25
+ #include <stdlib.h>
26
+ #include <ctype.h>
27
+ #include <math.h>
28
+ #include "intern.h"
29
+
30
+ #include <defs.h>
31
+
32
+ /* safe storing of doubles */
33
+ #include <safe_double.h>
34
+
35
+
36
+ #define is_a_dtable(d) ( TYPE(d) == T_DATA && RDATA(d)->dfree == (RUBY_DATA_FUNC)dtable_free )
37
+
38
+ #ifndef MAX
39
+ #define MAX(a,b) (((a) > (b)) ? (a) : (b))
40
+ #endif
41
+ #ifndef MIN
42
+ #define MIN(a,b) (((a) < (b)) ? (a) : (b))
43
+ #endif
44
+
45
+ typedef struct {
46
+ long num_cols, num_rows; /* the dimensions */
47
+ double **ptr; /* the data */
48
+ } Dtable;
49
+
50
+ /* prototypes */
51
+ static void dtable_free(Dtable *d);
52
+
53
+
54
+ PRIVATE bool Is_Dtable(VALUE obj) { return is_a_dtable(obj); }
55
+
56
+ // data stored in row order
57
+ // i.e., array arr of num_cols W and num_rows H is actually an array of H pointers
58
+ // each pointing to an array of W doubles.
59
+ // access row i and col j as arr[i][j] in c, as arr[i,j] in Ruby.
60
+
61
+ static void Alloc2dGrid(double ***f, int num_cols, int num_rows) {
62
+ int i;
63
+ if ((*f = (double **) calloc(num_rows, sizeof(double *)))==NULL)
64
+ rb_raise(rb_eArgError, "Memory allocation error in \"Alloc2dGrid\"");
65
+ for (i = 0; i < num_rows; i++) {
66
+ if (((*f)[i] = (double *) calloc(num_cols ,sizeof(double)))==NULL)
67
+ rb_raise(rb_eArgError, "Memory allocation error in \"Alloc2dGrid\"");
68
+ }
69
+ }
70
+
71
+ static double Max2dGrid(double **f, int num_cols, int num_rows) {
72
+ int i, j;
73
+ double M;
74
+ M = f[0][0];
75
+ for (i = 0; i < num_rows; i++) {
76
+ for (j = 0; j < num_cols; j++) {
77
+ if (f[i][j] > M) M = f[i][j];
78
+ }
79
+ }
80
+ return M;
81
+ }
82
+
83
+ static double Min2dGrid(double **f, int num_cols, int num_rows) {
84
+ int i, j;
85
+ double M;
86
+ M = f[0][0];
87
+ for (i = 0; i < num_rows; i++) {
88
+ for (j = 0; j < num_cols; j++) {
89
+ if (f[i][j] < M) M = f[i][j];
90
+ }
91
+ }
92
+ return M;
93
+ }
94
+
95
+ static bool Max_Lt_2dGrid(double **f, double limit, int num_cols, int num_rows, double *fmax) {
96
+ int i, j;
97
+ double M=0, tmp;
98
+ bool found = false;
99
+ for (i = 0; i < num_rows; i++) {
100
+ for (j = 0; j < num_cols; j++) {
101
+ tmp = f[i][j];
102
+ if (tmp >= limit) continue;
103
+ if (!found) { found = true; M = tmp; }
104
+ else if (tmp > M) M = tmp;
105
+ }
106
+ }
107
+ *fmax = M;
108
+ return found;
109
+ }
110
+
111
+ static bool Min_Gt_2dGrid(double **f, double limit, int num_cols, int num_rows, double *fmin) {
112
+ int i, j;
113
+ double M=0, tmp;
114
+ bool found = false;
115
+ for (i = 0; i < num_rows; i++) {
116
+ for (j = 0; j < num_cols; j++) {
117
+ tmp = f[i][j];
118
+ if (tmp <= limit) continue;
119
+ if (!found) { found = true; M = tmp; }
120
+ else if (tmp < M) M = tmp;
121
+ }
122
+ }
123
+ *fmin = M;
124
+ return found;
125
+ }
126
+
127
+ static Dtable *Get_Dtable(VALUE obj) {
128
+ Dtable *d;
129
+ Data_Get_Struct(obj, Dtable, d);
130
+ return d;
131
+ }
132
+
133
+ double **Dtable_Ptr(VALUE dtable, long *num_cols, long *num_rows) {
134
+ Dtable *d;
135
+ Data_Get_Struct(dtable, Dtable, d);
136
+ if(num_cols)
137
+ *num_cols = d->num_cols;
138
+ if(num_rows)
139
+ *num_rows = d->num_rows;
140
+ return d->ptr;
141
+ }
142
+
143
+ static VALUE cDtable; /* the Dtable class object */
144
+
145
+ static void dtable_free(Dtable *d) {
146
+ double **array = d->ptr;
147
+ int i;
148
+ for (i = 0; i < d->num_rows; i++) free(array[i]);
149
+ free(array);
150
+ free(d);
151
+ }
152
+
153
+ static VALUE dtable_alloc(VALUE klass) {
154
+ Dtable *d;
155
+ VALUE ary = Data_Make_Struct(klass, Dtable, NULL, dtable_free, d);
156
+ d->num_cols = d->num_rows = 0;
157
+ d->ptr = NULL;
158
+ return ary;
159
+ }
160
+
161
+ static VALUE dtable_init(VALUE ary, int num_cols, int num_rows) {
162
+ Dtable *d = Get_Dtable(ary);
163
+ if (num_cols <= 0 || num_rows <= 0)
164
+ rb_raise(rb_eArgError, "bad args: Dtable.new(%d, %d)", num_cols, num_rows);
165
+ Alloc2dGrid(&d->ptr, num_cols, num_rows);
166
+ d->num_cols = num_cols;
167
+ d->num_rows = num_rows;
168
+ return ary;
169
+ }
170
+
171
+ PRIVATE
172
+ /*
173
+ * call-seq:
174
+ * dtable.dup -> a_dtable
175
+ *
176
+ * Returns a copy of _dtable_. For performance sensitive situations involving a series of operations,
177
+ * first make a copy using dup and then do "bang" operations to modify the result without further copying.
178
+ */
179
+ VALUE dtable_dup(VALUE ary) {
180
+ Dtable *d = Get_Dtable(ary);
181
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows;
182
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_cols, num_rows);
183
+ Dtable *d2 = Get_Dtable(new);
184
+ double **src, **dest;
185
+ src = d->ptr; dest = d2->ptr;
186
+ for (i = 0; i < num_rows; i++) {
187
+ for (j = 0; j < num_cols; j++) {
188
+ dest[i][j] = src[i][j];
189
+ }
190
+ }
191
+ return new;
192
+ }
193
+
194
+ PRIVATE
195
+ /*
196
+ * call-seq:
197
+ * dtable.reverse_rows -> a_dtable
198
+ *
199
+ * Returns a copy of _dtable_ with the order of rows reversed.
200
+ */ VALUE dtable_reverse_rows(VALUE ary)
201
+ {
202
+ Dtable *d = Get_Dtable(ary);
203
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows, last_row = num_rows - 1;
204
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_cols, num_rows);
205
+ Dtable *d2 = Get_Dtable(new);
206
+ double **src, **dest;
207
+ src = d->ptr; dest = d2->ptr;
208
+ for (i = 0; i < num_rows; i++) {
209
+ for (j = 0; j < num_cols; j++) {
210
+ dest[last_row-i][j] = src[i][j];
211
+ }
212
+ }
213
+ return new;
214
+ }
215
+
216
+ PRIVATE
217
+ /*
218
+ * call-seq:
219
+ * dtable.reverse_cols -> a_dtable
220
+ *
221
+ * Returns a copy of _dtable_ with the order of columns reversed.
222
+ */ VALUE dtable_reverse_cols(VALUE ary)
223
+ {
224
+ Dtable *d = Get_Dtable(ary);
225
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows, last_col = num_cols - 1;
226
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_cols, num_rows);
227
+ Dtable *d2 = Get_Dtable(new);
228
+ double **src, **dest;
229
+ src = d->ptr; dest = d2->ptr;
230
+ for (i = 0; i < num_rows; i++) {
231
+ for (j = 0; j < num_cols; j++) {
232
+ dest[i][last_col-j] = src[i][j];
233
+ }
234
+ }
235
+ return new;
236
+ }
237
+
238
+
239
+ PRIVATE
240
+ /*
241
+ * call-seq:
242
+ * dtable.rotate_cw90 -> a_dtable
243
+ *
244
+ * Returns a copy of _dtable_ rotated 90 degrees clockwise.
245
+ */ VALUE dtable_rotate_cw90(VALUE ary)
246
+ {
247
+ Dtable *d = Get_Dtable(ary);
248
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows, last_row = num_rows - 1;
249
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_rows, num_cols);
250
+ Dtable *d2 = Get_Dtable(new);
251
+ double **src, **dest;
252
+ src = d->ptr; dest = d2->ptr;
253
+ for (i = 0; i < num_rows; i++) {
254
+ for (j = 0; j < num_cols; j++) {
255
+ dest[j][last_row-i] = src[i][j];
256
+ }
257
+ }
258
+ return new;
259
+ }
260
+
261
+
262
+ PRIVATE
263
+ /*
264
+ * call-seq:
265
+ * dtable.rotate_ccw90 -> a_dtable
266
+ *
267
+ * Returns a copy of _dtable_ rotated 90 degrees counter-clockwise.
268
+ */ VALUE dtable_rotate_ccw90(VALUE ary)
269
+ {
270
+ Dtable *d = Get_Dtable(ary);
271
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows, last_col = num_cols - 1;
272
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_rows, num_cols);
273
+ Dtable *d2 = Get_Dtable(new);
274
+ double **src, **dest;
275
+ src = d->ptr; dest = d2->ptr;
276
+ for (i = 0; i < num_rows; i++) {
277
+ for (j = 0; j < num_cols; j++) {
278
+ dest[last_col-j][i] = src[i][j];
279
+ }
280
+ }
281
+ return new;
282
+ }
283
+
284
+ PRIVATE
285
+ /*
286
+ * call-seq:
287
+ * dtable.transpose -> a_dtable
288
+ *
289
+ * Returns a transposed copy of _dtable_ (i.e., exchange rows and columns).
290
+ */ VALUE dtable_transpose(VALUE ary) {
291
+ Dtable *d = Get_Dtable(ary);
292
+ int i, j, num_cols = d->num_cols, num_rows = d->num_rows;
293
+ VALUE new = dtable_init(dtable_alloc(cDtable), num_rows, num_cols);
294
+ Dtable *d2 = Get_Dtable(new);
295
+ double **src, **dest;
296
+ src = d->ptr; dest = d2->ptr;
297
+ for (i = 0; i < num_rows; i++) {
298
+ for (j = 0; j < num_cols; j++) {
299
+ dest[j][i] = src[i][j];
300
+ }
301
+ }
302
+ return new;
303
+ }
304
+
305
+ PRIVATE
306
+ /*
307
+ * call-seq:
308
+ * Dtable.new(num_cols, num_rows) -> a_dtable
309
+ *
310
+ * Returns a new Dtable with the requested dimensions.
311
+ */
312
+ VALUE dtable_initialize(int argc, VALUE *argv, VALUE ary) {
313
+ if (argc != 2) rb_raise(rb_eArgError, "need 2 args for Dtable.new(num_cols, num_rows)");
314
+ int num_cols = NUM2INT(argv[0]), num_rows = NUM2INT(argv[1]);
315
+ return dtable_init(ary, num_cols, num_rows);
316
+ }
317
+
318
+ PRIVATE
319
+ /*
320
+ * call-seq:
321
+ * dtable.num_cols -> integer
322
+ *
323
+ * Returns the number of entries in the x dimension of _dtable_.
324
+ */
325
+ VALUE dtable_num_cols(VALUE ary) {
326
+ Dtable *d = Get_Dtable(ary);
327
+ return LONG2NUM(d->num_cols);
328
+ }
329
+
330
+ PRIVATE
331
+ /*
332
+ * call-seq:
333
+ * dtable.num_rows -> integer
334
+ *
335
+ * Returns the number of entries in the y dimension of _dtable_.
336
+ */ VALUE dtable_num_rows(VALUE ary) {
337
+ Dtable *d = Get_Dtable(ary);
338
+ return LONG2NUM(d->num_rows);
339
+ }
340
+
341
+ PRIVATE
342
+ /*
343
+ * call-seq:
344
+ * dtable.min_gt(val) -> float or nil
345
+ *
346
+ * Returns the minimum entry in _dtable_ which is greater than _val_, or <code>nil</code> if no such entry if found.
347
+ */ VALUE dtable_min_gt(VALUE ary, VALUE val) {
348
+ Dtable *d = Get_Dtable(ary);
349
+ val = rb_Float(val);
350
+ double zmin, z = NUM2DBL(val);
351
+ if (Min_Gt_2dGrid(d->ptr, z, d->num_cols, d->num_rows, &zmin))
352
+ return rb_float_new(zmin);
353
+ return Qnil;
354
+ }
355
+
356
+ PRIVATE
357
+ /*
358
+ * call-seq:
359
+ * dtable.max_lt(val) -> float or nil
360
+ *
361
+ * Returns the maximum entry in _dtable_ which is less than _val_, or <code>nil</code> if no such entry if found.
362
+ */ VALUE dtable_max_lt(VALUE ary, VALUE val) {
363
+ Dtable *d = Get_Dtable(ary);
364
+ val = rb_Float(val);
365
+ double zmax, z = NUM2DBL(val);
366
+ if (Max_Lt_2dGrid(d->ptr, z, d->num_cols, d->num_rows, &zmax))
367
+ return rb_float_new(zmax);
368
+ return Qnil;
369
+ }
370
+
371
+ PRIVATE
372
+ /*
373
+ * call-seq:
374
+ * dtable.min -> float
375
+ *
376
+ * Returns the minimum entry in _dtable_.
377
+ */ VALUE dtable_min(VALUE ary) {
378
+ Dtable *d = Get_Dtable(ary);
379
+ double zmin = Min2dGrid(d->ptr, d->num_cols, d->num_rows);
380
+ return rb_float_new(zmin);
381
+ }
382
+
383
+ PRIVATE
384
+ /*
385
+ * call-seq:
386
+ * dtable.max -> float
387
+ *
388
+ * Returns the maximum entry in _dtable_.
389
+ */ VALUE dtable_max(VALUE ary) {
390
+ Dtable *d = Get_Dtable(ary);
391
+ double zmax = Max2dGrid(d->ptr, d->num_cols, d->num_rows);
392
+ return rb_float_new(zmax);
393
+ }
394
+
395
+ PRIVATE
396
+ /*
397
+ * call-seq:
398
+ * dtable.row(int) -> a_dvec
399
+ *
400
+ * Creates a Dvector holding a copy of the contents of the requested row.
401
+ */ VALUE dtable_row(VALUE ary, VALUE row_num) {
402
+ Dtable *d = Get_Dtable(ary);
403
+ row_num = rb_Integer(row_num);
404
+ int row = NUM2INT(row_num);
405
+ if (row < 0 || row >= d->num_rows)
406
+ rb_raise(rb_eArgError, "Asking for row i = %i from array with only %i rows", row, d->num_rows);
407
+ VALUE dvec = Dvector_Create();
408
+ Dvector_Data_Replace(dvec, d->num_cols, d->ptr[row]);
409
+ return dvec;
410
+ }
411
+
412
+ PRIVATE
413
+ /*
414
+ * call-seq:
415
+ * dtable.set_row(int,a_dvec) -> a_dvec
416
+ *
417
+ * Stores the contents of _a_dec_ in the specified row of the array.
418
+ * The length of the vector must equal the number of columns in the array.
419
+ */ VALUE dtable_set_row(VALUE ary, VALUE row_num, VALUE dvec) {
420
+ Dtable *d = Get_Dtable(ary);
421
+ long len, j;
422
+ double *data = Dvector_Data_for_Read(dvec, &len);
423
+ row_num = rb_Integer(row_num);
424
+ int row = NUM2INT(row_num);
425
+ if (row < 0 || row >= d->num_rows)
426
+ rb_raise(rb_eArgError, "Asking for row i = %i from array with only %i rows", row, d->num_rows);
427
+ if (len != d->num_cols)
428
+ rb_raise(rb_eArgError, "Length of vector (%i) does not match number of columns (%i)", len, d->num_cols);
429
+ for (j=0; j < len; j++)
430
+ d->ptr[row][j] = data[j];
431
+ return dvec;
432
+ }
433
+
434
+ PRIVATE
435
+ /*
436
+ * call-seq:
437
+ * dtable.set_column(int,a_dvec) -> a_dvec
438
+ *
439
+ * Stores the contents of _a_dec_ in the specified column of the array.
440
+ * The length of the vector must equal the number of rows in the array.
441
+ */ VALUE dtable_set_column(VALUE ary, VALUE col_num, VALUE dvec) {
442
+ Dtable *d = Get_Dtable(ary);
443
+ long len, i;
444
+ double *data = Dvector_Data_for_Read(dvec, &len);
445
+ col_num = rb_Integer(col_num);
446
+ int col = NUM2INT(col_num);
447
+ if (col < 0 || col >= d->num_cols)
448
+ rb_raise(rb_eArgError, "Asking for column i = %i from array with only %i columns", col, d->num_cols);
449
+ if (len != d->num_rows)
450
+ rb_raise(rb_eArgError, "Length of vector (%i) does not match number of rows (%i)", len, d->num_rows);
451
+ for (i=0; i < len; i++)
452
+ d->ptr[i][col] = data[i];
453
+ return dvec;
454
+ }
455
+
456
+ PRIVATE
457
+ /*
458
+ * call-seq:
459
+ * dtable.column(int) -> a_dvec
460
+ *
461
+ * Creates a Dvector holding a copy of the contents of the requested column.
462
+ */ VALUE dtable_column(VALUE ary, VALUE column_num) {
463
+ Dtable *d = Get_Dtable(ary);
464
+ column_num = rb_Integer(column_num);
465
+ int i, column = NUM2INT(column_num), len;
466
+ if (column < 0 || column >= d->num_cols)
467
+ rb_raise(rb_eArgError, "Asking for column i = %i from array with only %i columns", column, d->num_cols);
468
+ VALUE dvec = Dvector_Create();
469
+ len = d->num_rows;
470
+ Dvector_Data_Resize(dvec, len);
471
+ for (i=0; i < len; i++)
472
+ Dvector_Store_Double(dvec, i, d->ptr[i][column]);
473
+ return dvec;
474
+ }
475
+
476
+ static void set_dtable_vals(VALUE ary, double v) {
477
+ Dtable *d = Get_Dtable(ary);
478
+ int num_cols = d->num_cols, num_rows = d->num_rows, i, j;
479
+ double **data = d->ptr;
480
+ for (i = 0; i < num_rows; i++) {
481
+ for (j = 0; j < num_cols; j++) {
482
+ data[i][j] = v;
483
+ }
484
+ }
485
+ }
486
+
487
+ PRIVATE
488
+ /*
489
+ * call-seq:
490
+ * dtable.clear -> dtable
491
+ *
492
+ * Sets the entries of _dtable_ array to zero.
493
+ */ VALUE dtable_clear(VALUE ary, VALUE val) {
494
+ set_dtable_vals(ary, 0.0);
495
+ return ary;
496
+ }
497
+
498
+ PRIVATE
499
+ /*
500
+ * call-seq:
501
+ * dtable.set(float) -> dtable
502
+ * dtable.set(a_dtable) -> dtable
503
+ *
504
+ * Modifies the entries of _dtable_ array. If the argument is a float, then all of the
505
+ * entries are set to that value. If the argument is another Dtable array, then it must
506
+ * be the size as _dtable_, and its contents are copied to _dtable_.
507
+ */ VALUE dtable_set(VALUE ary, VALUE val) {
508
+ if (is_a_dtable(val)) {
509
+ Dtable *d = Get_Dtable(ary);
510
+ Dtable *d2 = Get_Dtable(val);
511
+ int num_cols = d->num_cols, num_rows = d->num_rows, i, j;
512
+ double **data = d->ptr;
513
+ double **data2 = d2->ptr;
514
+ if (d2->num_cols != num_cols || d2->num_rows != num_rows)
515
+ rb_raise(rb_eArgError, "Arrays must be same size for Dtable set");
516
+ for (i = 0; i < num_rows; i++) {
517
+ for (j = 0; j < num_cols; j++) {
518
+ data[i][j] = data2[i][j];
519
+ }
520
+ }
521
+ } else {
522
+ double v = NUM2DBL(val);
523
+ set_dtable_vals(ary, v);
524
+ }
525
+ return ary;
526
+ }
527
+
528
+ PRIVATE
529
+ VALUE dtable_apply_math_op_bang(VALUE ary, double (*op)(double)) {
530
+ Dtable *d = Get_Dtable(ary);
531
+ double **p = d->ptr;
532
+ int num_cols = d->num_cols, num_rows = d->num_rows, i, j;
533
+ for (i = 0; i < num_rows; i++) {
534
+ for (j = 0; j < num_cols; j++) {
535
+ p[i][j] = (*op)(p[i][j]);
536
+ }
537
+ }
538
+ return ary;
539
+ }
540
+
541
+ PRIVATE VALUE dtable_apply_math_op(VALUE source, double (*op)(double)) {
542
+ return dtable_apply_math_op_bang(dtable_dup(source), op);
543
+ }
544
+
545
+ static double do_neg(double arg) { return -arg; }
546
+
547
+ PRIVATE
548
+ /*
549
+ * call-seq:
550
+ * dtable.neg -> a_dtable
551
+ *
552
+ * Returns of copy of _dtable_ with each entry x replaced by -x.
553
+ */ VALUE dtable_neg(VALUE ary) {
554
+ return dtable_apply_math_op(ary, do_neg);
555
+ }
556
+
557
+ PRIVATE
558
+ /*
559
+ * call-seq:
560
+ * dtable.abs -> a_dtable
561
+ *
562
+ * Returns of copy of _dtable_ with all entries replaced by their absolute values.
563
+ */ VALUE dtable_abs(VALUE ary) {
564
+ return dtable_apply_math_op(ary, fabs);
565
+ }
566
+
567
+ PRIVATE
568
+ /*
569
+ * call-seq:
570
+ * dtable.sin -> a_dtable
571
+ *
572
+ * Returns of copy of _dtable_ with entry x replaced by sin(x).
573
+ */ VALUE dtable_sin(VALUE ary) {
574
+ return dtable_apply_math_op(ary, sin);
575
+ }
576
+
577
+ PRIVATE
578
+ /*
579
+ * call-seq:
580
+ * dtable.cos -> a_dtable
581
+ *
582
+ * Returns of copy of _dtable_ with entry x replaced by cos(x).
583
+ */ VALUE dtable_cos(VALUE ary) {
584
+ return dtable_apply_math_op(ary, cos);
585
+ }
586
+
587
+ PRIVATE
588
+ /*
589
+ * call-seq:
590
+ * dtable.tan -> a_dtable
591
+ *
592
+ * Returns of copy of _dtable_ with entry x replaced by tan(x).
593
+ */ VALUE dtable_tan(VALUE ary) {
594
+ return dtable_apply_math_op(ary, tan);
595
+ }
596
+
597
+ PRIVATE
598
+ /*
599
+ * call-seq:
600
+ * dtable.asin -> a_dtable
601
+ *
602
+ * Returns of copy of _dtable_ with entry x replaced by asin(x).
603
+ */ VALUE dtable_asin(VALUE ary) {
604
+ return dtable_apply_math_op(ary, asin);
605
+ }
606
+
607
+ PRIVATE
608
+ /*
609
+ * call-seq:
610
+ * dtable.acos -> a_dtable
611
+ *
612
+ * Returns of copy of _dtable_ with entry x replaced by acos(x).
613
+ */ VALUE dtable_acos(VALUE ary) {
614
+ return dtable_apply_math_op(ary, acos);
615
+ }
616
+
617
+ PRIVATE
618
+ /*
619
+ * call-seq:
620
+ * dtable.atan -> a_dtable
621
+ *
622
+ * Returns of copy of _dtable_ with entry x replaced by atan(x).
623
+ */ VALUE dtable_atan(VALUE ary) {
624
+ return dtable_apply_math_op(ary, atan);
625
+ }
626
+
627
+ PRIVATE
628
+ /*
629
+ * call-seq:
630
+ * dtable.sinh -> a_dtable
631
+ *
632
+ * Returns of copy of _dtable_ with entry x replaced by sinh(x).
633
+ */ VALUE dtable_sinh(VALUE ary) {
634
+ return dtable_apply_math_op(ary, sinh);
635
+ }
636
+
637
+ PRIVATE
638
+ /*
639
+ * call-seq:
640
+ * dtable.cosh -> a_dtable
641
+ *
642
+ * Returns of copy of _dtable_ with entry x replaced by cosh(x).
643
+ */ VALUE dtable_cosh(VALUE ary) {
644
+ return dtable_apply_math_op(ary, cosh);
645
+ }
646
+
647
+ PRIVATE
648
+ /*
649
+ * call-seq:
650
+ * dtable.tanh -> a_dtable
651
+ *
652
+ * Returns of copy of _dtable_ with entry x replaced by tanh(x).
653
+ */ VALUE dtable_tanh(VALUE ary) {
654
+ return dtable_apply_math_op(ary, tanh);
655
+ }
656
+
657
+ static double do_asinh(double x) { return log(x + sqrt(x*x+1.0)); }
658
+
659
+ PRIVATE
660
+ /*
661
+ * call-seq:
662
+ * dtable.asinh -> a_dtable
663
+ *
664
+ * Returns of copy of _dtable_ with entry x replaced by asinh(x).
665
+ */ VALUE dtable_asinh(VALUE ary) {
666
+ return dtable_apply_math_op(ary, do_asinh);
667
+ }
668
+
669
+ static double do_acosh(double x) { return log(x + sqrt(x*x-1.0)); }
670
+
671
+ PRIVATE
672
+ /*
673
+ * call-seq:
674
+ * dtable.acosh -> a_dtable
675
+ *
676
+ * Returns of copy of _dtable_ with entry x replaced by acosh(x).
677
+ */ VALUE dtable_acosh(VALUE ary) {
678
+ return dtable_apply_math_op(ary, do_acosh);
679
+ }
680
+
681
+ static double do_atanh(double x) { return 0.5*log((1.0+x)/(1.0-x)); }
682
+
683
+ PRIVATE
684
+ /*
685
+ * call-seq:
686
+ * dtable.atanh -> a_dtable
687
+ *
688
+ * Returns of copy of _dtable_ with entry x replaced by atanh(x).
689
+ */ VALUE dtable_atanh(VALUE ary) {
690
+ return dtable_apply_math_op(ary, do_atanh);
691
+ }
692
+
693
+ PRIVATE
694
+ /*
695
+ * call-seq:
696
+ * dtable.ceil -> a_dtable
697
+ *
698
+ * Returns of copy of _dtable_ with entry x replaced by smallest integer not less than x.
699
+ */ VALUE dtable_ceil(VALUE ary) {
700
+ return dtable_apply_math_op(ary, ceil);
701
+ }
702
+
703
+ PRIVATE
704
+ /*
705
+ * call-seq:
706
+ * dtable.floor -> a_dtable
707
+ *
708
+ * Returns of copy of _dtable_ with each entry x replaced by largest integer not greater than x.
709
+ */ VALUE dtable_floor(VALUE ary) {
710
+ return dtable_apply_math_op(ary, floor);
711
+ }
712
+
713
+ static double do_round(double x) { return (x == 0.0)? 0.0 : (x > 0.0)? floor(x+0.5) : ceil(x-0.5); }
714
+
715
+ PRIVATE
716
+ /*
717
+ * call-seq:
718
+ * dtable.round -> a_dtable
719
+ *
720
+ * Returns of copy of _dtable_ with each entry x replaced by round(x).
721
+ * (Numbers midway between integers round away from zero.)
722
+ */ VALUE dtable_round(VALUE ary) {
723
+ return dtable_apply_math_op(ary, do_round);
724
+ }
725
+
726
+ PRIVATE
727
+ /*
728
+ * call-seq:
729
+ * dtable.exp -> a_dtable
730
+ *
731
+ * Returns of copy of _dtable_ with each entry x replaced by exp(x).
732
+ */ VALUE dtable_exp(VALUE ary) {
733
+ return dtable_apply_math_op(ary, exp);
734
+ }
735
+
736
+ static double do_exp10(double arg) { return pow(10.0, arg); }
737
+
738
+ PRIVATE
739
+ /*
740
+ * call-seq:
741
+ * dtable.exp10 -> a_dtable
742
+ *
743
+ * Returns of copy of _dtable_ with each entry x replaced by 10**x.
744
+ */ VALUE dtable_exp10(VALUE ary) {
745
+ return dtable_apply_math_op(ary, do_exp10);
746
+ }
747
+
748
+ PRIVATE
749
+ /*
750
+ * call-seq:
751
+ * dtable.log -> a_dtable
752
+ *
753
+ * Returns of copy of _dtable_ with each entry x replaced by log(x).
754
+ */ VALUE dtable_log(VALUE ary) {
755
+ return dtable_apply_math_op(ary, log);
756
+ }
757
+
758
+ PRIVATE
759
+ /*
760
+ * call-seq:
761
+ * dtable.log10 -> a_dtable
762
+ *
763
+ * Returns of copy of _dtable_ with each entry x replaced by log10(x).
764
+ */ VALUE dtable_log10(VALUE ary) {
765
+ return dtable_apply_math_op(ary, log10);
766
+ }
767
+
768
+ static double do_inv(double arg) { return 1.0/arg; }
769
+
770
+ PRIVATE
771
+ /*
772
+ * call-seq:
773
+ * dtable.inv -> a_dtable
774
+ *
775
+ * Returns of copy of _dtable_ with each entry x replaced by 1/x.
776
+ */ VALUE dtable_inv(VALUE ary) {
777
+ return dtable_apply_math_op(ary, do_inv);
778
+ }
779
+
780
+ PRIVATE
781
+ /*
782
+ * call-seq:
783
+ * dtable.sqrt -> a_dtable
784
+ *
785
+ * Returns of copy of _dtable_ with each entry x replaced by sqrt(x).
786
+ */ VALUE dtable_sqrt(VALUE ary) {
787
+ return dtable_apply_math_op(ary, sqrt);
788
+ }
789
+
790
+ PRIVATE
791
+ /*
792
+ * call-seq:
793
+ * dtable.neg! -> dtable
794
+ *
795
+ * Replace each entry x of _dtable_ with -x.
796
+ */ VALUE dtable_neg_bang(VALUE ary) {
797
+ return dtable_apply_math_op_bang(ary, do_neg);
798
+ }
799
+
800
+ PRIVATE
801
+ /*
802
+ * call-seq:
803
+ * dtable.abs! -> dtable
804
+ *
805
+ * Replace each entry x of _dtable_ with abs(x).
806
+ */ VALUE dtable_abs_bang(VALUE ary) {
807
+ return dtable_apply_math_op_bang(ary, fabs);
808
+ }
809
+
810
+ PRIVATE
811
+ /*
812
+ * call-seq:
813
+ * dtable.sin! -> dtable
814
+ *
815
+ * Replace each entry x of _dtable_ with sin(x).
816
+ */ VALUE dtable_sin_bang(VALUE ary) {
817
+ return dtable_apply_math_op_bang(ary, sin);
818
+ }
819
+
820
+ PRIVATE
821
+ /*
822
+ * call-seq:
823
+ * dtable.cos! -> dtable
824
+ *
825
+ * Replace each entry x of _dtable_ with cos(x).
826
+ */ VALUE dtable_cos_bang(VALUE ary) {
827
+ return dtable_apply_math_op_bang(ary, cos);
828
+ }
829
+
830
+ PRIVATE
831
+ /*
832
+ * call-seq:
833
+ * dtable.tan! -> dtable
834
+ *
835
+ * Replace each entry x of _dtable_ with tan(x).
836
+ */ VALUE dtable_tan_bang(VALUE ary) {
837
+ return dtable_apply_math_op_bang(ary, tan);
838
+ }
839
+
840
+ PRIVATE
841
+ /*
842
+ * call-seq:
843
+ * dtable.asin! -> dtable
844
+ *
845
+ * Replace each entry x of _dtable_ with asin(x).
846
+ */ VALUE dtable_asin_bang(VALUE ary) {
847
+ return dtable_apply_math_op_bang(ary, asin);
848
+ }
849
+
850
+ PRIVATE
851
+ /*
852
+ * call-seq:
853
+ * dtable.acos! -> dtable
854
+ *
855
+ * Replace each entry x of _dtable_ with acos(x).
856
+ */ VALUE dtable_acos_bang(VALUE ary) {
857
+ return dtable_apply_math_op_bang(ary, acos);
858
+ }
859
+
860
+ PRIVATE
861
+ /*
862
+ * call-seq:
863
+ * dtable.atan! -> dtable
864
+ *
865
+ * Replace each entry x of _dtable_ with atan(x).
866
+ */ VALUE dtable_atan_bang(VALUE ary) {
867
+ return dtable_apply_math_op_bang(ary, atan);
868
+ }
869
+
870
+ PRIVATE
871
+ /*
872
+ * call-seq:
873
+ * dtable.sinh! -> dtable
874
+ *
875
+ * Replace each entry x of _dtable_ with sinh(x).
876
+ */ VALUE dtable_sinh_bang(VALUE ary) {
877
+ return dtable_apply_math_op_bang(ary, sinh);
878
+ }
879
+
880
+ PRIVATE
881
+ /*
882
+ * call-seq:
883
+ * dtable.cosh! -> dtable
884
+ *
885
+ * Replace each entry x of _dtable_ with cosh(x).
886
+ */ VALUE dtable_cosh_bang(VALUE ary) {
887
+ return dtable_apply_math_op_bang(ary, cosh);
888
+ }
889
+
890
+ PRIVATE
891
+ /*
892
+ * call-seq:
893
+ * dtable.tanh! -> dtable
894
+ *
895
+ * Replace each entry x of _dtable_ with tanh(x).
896
+ */ VALUE dtable_tanh_bang(VALUE ary) {
897
+ return dtable_apply_math_op_bang(ary, tanh);
898
+ }
899
+
900
+ PRIVATE
901
+ /*
902
+ * call-seq:
903
+ * dtable.asinh! -> dtable
904
+ *
905
+ * Replace each entry x of _dtable_ with asinh(x).
906
+ */ VALUE dtable_asinh_bang(VALUE ary) {
907
+ return dtable_apply_math_op_bang(ary, do_asinh);
908
+ }
909
+
910
+ PRIVATE
911
+ /*
912
+ * call-seq:
913
+ * dtable.acosh! -> dtable
914
+ *
915
+ * Replace each entry x of _dtable_ with acosh(x).
916
+ */ VALUE dtable_acosh_bang(VALUE ary) {
917
+ return dtable_apply_math_op_bang(ary, do_acosh);
918
+ }
919
+
920
+ PRIVATE
921
+ /*
922
+ * call-seq:
923
+ * dtable.atanh! -> dtable
924
+ *
925
+ * Replace each entry x of _dtable_ with atanh(x).
926
+ */ VALUE dtable_atanh_bang(VALUE ary) {
927
+ return dtable_apply_math_op_bang(ary, do_atanh);
928
+ }
929
+
930
+ PRIVATE
931
+ /*
932
+ * call-seq:
933
+ * dtable.ceil! -> dtable
934
+ *
935
+ * Replace each entry x of _dtable_ with the smallest integer not less than x.
936
+ */ VALUE dtable_ceil_bang(VALUE ary) {
937
+ return dtable_apply_math_op_bang(ary, ceil);
938
+ }
939
+
940
+ PRIVATE
941
+ /*
942
+ * call-seq:
943
+ * dtable.floor! -> dtable
944
+ *
945
+ * Replace each entry x of _dtable_ with the largest integer not greater than x.
946
+ */ VALUE dtable_floor_bang(VALUE ary) {
947
+ return dtable_apply_math_op_bang(ary, floor);
948
+ }
949
+
950
+ PRIVATE
951
+ /*
952
+ * call-seq:
953
+ * dtable.round! -> dtable
954
+ *
955
+ * Replace each entry x of _dtable_ with the integer closest to x.
956
+ * (Numbers midway between integers round away from zero.)
957
+ */ VALUE dtable_round_bang(VALUE ary) {
958
+ return dtable_apply_math_op_bang(ary, do_round);
959
+ }
960
+
961
+ PRIVATE
962
+ /*
963
+ * call-seq:
964
+ * dtable.exp! -> dtable
965
+ *
966
+ * Replace each entry x of _dtable_ with exp(x).
967
+ */ VALUE dtable_exp_bang(VALUE ary) {
968
+ return dtable_apply_math_op_bang(ary, exp);
969
+ }
970
+
971
+ PRIVATE
972
+ /*
973
+ * call-seq:
974
+ * dtable.exp10! -> dtable
975
+ *
976
+ * Replace each entry x of _dtable_ with 10**x.
977
+ */ VALUE dtable_exp10_bang(VALUE ary) {
978
+ return dtable_apply_math_op_bang(ary, do_exp10);
979
+ }
980
+
981
+ PRIVATE
982
+ /*
983
+ * call-seq:
984
+ * dtable.log! -> dtable
985
+ *
986
+ * Replace each entry x of _dtable_ with log(x).
987
+ */ VALUE dtable_log_bang(VALUE ary) {
988
+ return dtable_apply_math_op_bang(ary, log);
989
+ }
990
+
991
+ PRIVATE
992
+ /*
993
+ * call-seq:
994
+ * dtable.log10! -> dtable
995
+ *
996
+ * Replace each entry x of _dtable_ with log10(x).
997
+ */ VALUE dtable_log10_bang(VALUE ary) {
998
+ return dtable_apply_math_op_bang(ary, log10);
999
+ }
1000
+
1001
+ PRIVATE
1002
+ /*
1003
+ * call-seq:
1004
+ * dtable.inv! -> dtable
1005
+ *
1006
+ * Replace each entry x of _dtable_ with 1/x.
1007
+ */ VALUE dtable_inv_bang(VALUE ary) {
1008
+ return dtable_apply_math_op_bang(ary, do_inv);
1009
+ }
1010
+
1011
+ PRIVATE
1012
+ /*
1013
+ * call-seq:
1014
+ * dtable.sqrt! -> dtable
1015
+ *
1016
+ * Replace each entry x of _dtable_ with sqrt(x).
1017
+ */ VALUE dtable_sqrt_bang(VALUE ary) {
1018
+ return dtable_apply_math_op_bang(ary, sqrt);
1019
+ }
1020
+
1021
+ PRIVATE VALUE dtable_apply_math_op1_bang(VALUE ary, VALUE arg, double (*op)(double, double)) {
1022
+ Dtable *d = Get_Dtable(ary);
1023
+ arg = rb_Float(arg);
1024
+ double y = NUM2DBL(arg), **p = d->ptr;
1025
+ int num_cols = d->num_cols, num_rows = d->num_rows, i, j;
1026
+ for (i = 0; i < num_rows; i++) {
1027
+ for (j = 0; j < num_cols; j++) {
1028
+ p[i][j] = (*op)(p[i][j], y);
1029
+ }
1030
+ }
1031
+ return ary;
1032
+ }
1033
+
1034
+ PRIVATE VALUE dtable_apply_math_op1(VALUE source, VALUE arg, double (*op)(double, double)) {
1035
+ return dtable_apply_math_op1_bang(dtable_dup(source), arg, op);
1036
+ }
1037
+
1038
+ static double do_trim(double x, double cutoff) { return (fabs(x) < cutoff)? 0.0 : x; }
1039
+
1040
+ PRIVATE
1041
+ /*
1042
+ * call-seq:
1043
+ * dtable.trim(cutoff=1e-6) -> a_dtable
1044
+ *
1045
+ * Returns a copy of _dtable_ with any entry with absolute value less than _cutoff_ replaced by 0.
1046
+ */ VALUE dtable_trim(int argc, VALUE *argv, VALUE self) {
1047
+ VALUE arg1;
1048
+ if ((argc < 0) || (argc > 1))
1049
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1050
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-6);
1051
+ return dtable_apply_math_op1(self, arg1, do_trim);
1052
+ }
1053
+
1054
+ static double do_safe_log(double x, double y) { return log(MAX(x,y)); }
1055
+
1056
+ PRIVATE
1057
+ /*
1058
+ * call-seq:
1059
+ * dtable.safe_log(cutoff=1e-99) -> a_dtable
1060
+ *
1061
+ * Returns a copy of _dtable_ with each entry x replaced by log(max(x,_cutoff_)).
1062
+ */ VALUE dtable_safe_log(int argc, VALUE *argv, VALUE self) {
1063
+ VALUE arg1;
1064
+ if ((argc < 0) || (argc > 1))
1065
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1066
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1067
+ return dtable_apply_math_op1(self, arg1, do_safe_log);
1068
+ }
1069
+
1070
+ static double do_safe_log10(double x, double y) { return log10(MAX(x,y)); }
1071
+
1072
+ PRIVATE
1073
+ /*
1074
+ * call-seq:
1075
+ * dtable.safe_log10(cutoff=1e-99) -> a_dtable
1076
+ *
1077
+ * Returns a copy of _dtable_ with each entry x replaced by log10(max(x,_cutoff_)).
1078
+ *
1079
+ */ VALUE dtable_safe_log10(int argc, VALUE *argv, VALUE self) {
1080
+ VALUE arg1;
1081
+ if ((argc < 0) || (argc > 1))
1082
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1083
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1084
+ return dtable_apply_math_op1(self, arg1, do_safe_log10);
1085
+ }
1086
+
1087
+ static double do_safe_inv(double x, double y) {
1088
+ return (fabs(x) >= y)? 1.0/x : (x > 0.0)? 1.0/y : -1.0/y; }
1089
+
1090
+ PRIVATE
1091
+ /*
1092
+ * call-seq:
1093
+ * dtable.safe_inv(cutoff=1e-99) -> a_dtable
1094
+ *
1095
+ * Returns a copy of _dtable_ with each entry x replaced by sign(x)/_cutoff_ if abs(x) < _cutoff_, 1/x otherwise.
1096
+ *
1097
+ */ VALUE dtable_safe_inv(int argc, VALUE *argv, VALUE self) {
1098
+ VALUE arg1;
1099
+ if ((argc < 0) || (argc > 1))
1100
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1101
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1102
+ return dtable_apply_math_op1(self, arg1, do_safe_inv);
1103
+ }
1104
+
1105
+ static double do_safe_asin(double x) { return asin(MAX(-1.0,MIN(1.0,x))); }
1106
+
1107
+ PRIVATE
1108
+ /*
1109
+ * call-seq:
1110
+ * dtable.safe_asin -> a_dtable
1111
+ *
1112
+ * Returns a copy of _dtable_ with each entry x replaced by asin(max(-1,min(1,x))).
1113
+ *
1114
+ */ VALUE dtable_safe_asin(VALUE ary) {
1115
+ return dtable_apply_math_op(ary, do_safe_asin);
1116
+ }
1117
+
1118
+ static double do_safe_acos(double x) { return acos(MAX(-1.0,MIN(1.0,x))); }
1119
+
1120
+ PRIVATE
1121
+ /*
1122
+ * call-seq:
1123
+ * dtable.safe_acos -> a_dtable
1124
+ *
1125
+ * Returns a copy of _dtable_ with each entry x replaced by acos(max(-1,min(1,x))).
1126
+ *
1127
+ */ VALUE dtable_safe_acos(VALUE ary) {
1128
+ return dtable_apply_math_op(ary, do_safe_acos);
1129
+ }
1130
+
1131
+ static double do_safe_sqrt(double x) { return sqrt(MAX(x,0.0)); }
1132
+
1133
+ PRIVATE
1134
+ /*
1135
+ * call-seq:
1136
+ * dtable.safe_sqrt -> a_dtable
1137
+ *
1138
+ * Returns a copy of _dtable_ with each entry x replaced by sqrt(max(x,0)).
1139
+ *
1140
+ */ VALUE dtable_safe_sqrt(VALUE ary) {
1141
+ return dtable_apply_math_op(ary, do_safe_sqrt);
1142
+ }
1143
+
1144
+ PRIVATE
1145
+ /*
1146
+ * call-seq:
1147
+ * dtable.atan2!(number) -> dtable
1148
+ * dtable.atan2!(other) -> dtable
1149
+ *
1150
+ * When argument is a number, this operation replaces each entry x of _dtable_ by the angle whose tangent is x/_number_.
1151
+ * When argument is a data array, this operation replaces each entry x of _dtable_ by the angle whose tangent is x divided
1152
+ * by the corresponding entry in the _other_ data array.
1153
+ */ VALUE dtable_atan2_bang(VALUE ary, VALUE arg) {
1154
+ return dtable_apply_math_op2_bang(ary, arg, atan2);
1155
+ }
1156
+
1157
+ static double do_mod(double x, double y) { return x - y * floor(x/y); }
1158
+ PRIVATE
1159
+ /*
1160
+ * call-seq:
1161
+ * dtable.modulo!(number) -> dtable
1162
+ * dtable.mod!(number) -> dtable
1163
+ * dtable.modulo!(other) -> dtable
1164
+ * dtable.mod!(other) -> dtable
1165
+ *
1166
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x % _number_.
1167
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1168
+ * by x % the corresponding entry in the _other_ data array.
1169
+ */ VALUE dtable_modulo_bang(VALUE ary, VALUE arg) {
1170
+ return dtable_apply_math_op2_bang(ary, arg, do_mod);
1171
+ }
1172
+
1173
+ static double do_remainder(double x, double y) { return (x*y > 0.0)? do_mod(x,y) : do_mod(x,y)-y; }
1174
+
1175
+ PRIVATE
1176
+ /*
1177
+ * call-seq:
1178
+ * dtable.remainder!(number) -> dtable
1179
+ * dtable.remainder!(other) -> dtable
1180
+ *
1181
+ * When the argument is a number, this operation replaces with each entry x of _dtable_ by the remainder of x divided by _number_.
1182
+ * When the argument is a data array, this operation replaces with each entry x of _dtable_
1183
+ * by remainder of x divided by the corresponding entry in the _other_ data array.
1184
+ */ VALUE dtable_remainder_bang(VALUE ary, VALUE arg) {
1185
+ return dtable_apply_math_op2_bang(ary, arg, do_remainder);
1186
+ }
1187
+
1188
+ PRIVATE
1189
+ /*
1190
+ * call-seq:
1191
+ * dtable.trim!(cutoff=1e-6) -> dtable
1192
+ *
1193
+ * Each entry x in _dtable_ having absolute value less than _cutoff_ is replaced by 0.
1194
+ */ VALUE dtable_trim_bang(int argc, VALUE *argv, VALUE self) {
1195
+ VALUE arg1;
1196
+ if ((argc < 0) || (argc > 1))
1197
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1198
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-6);
1199
+ return dtable_apply_math_op1_bang(self, arg1, do_trim);
1200
+ }
1201
+
1202
+ PRIVATE
1203
+ /*
1204
+ * call-seq:
1205
+ * dtable.pow!(number) -> dtable
1206
+ * dtable.pow!(other) -> dtable
1207
+ * dtable.raised_to!(number) -> dtable
1208
+ * dtable.raised_to!(other) -> dtable
1209
+ *
1210
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x ** _number_.
1211
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1212
+ * by x ** the corresponding entry in the _other_ data array.
1213
+ */ VALUE dtable_pow_bang(VALUE ary, VALUE arg) {
1214
+ return dtable_apply_math_op1_bang(ary, arg, pow);
1215
+ }
1216
+
1217
+ static double do_as_exponent_of(double x, double y) { return pow(y,x); }
1218
+
1219
+ PRIVATE
1220
+ /*
1221
+ * call-seq:
1222
+ * dtable.as_exponent_of!(number) -> dtable
1223
+ * dtable.as_exponent_of!(other) -> dtable
1224
+ *
1225
+ * When argument is a number, this operation replaces each entry x of _dtable_ by _number_ ** x.
1226
+ * When argument is a data array, this operation replaces each entry x of _dtable_
1227
+ * by the corresponding entry in the _other_ data array raised to the power x.
1228
+ */ VALUE dtable_as_exponent_of_bang(VALUE ary, VALUE arg) {
1229
+ return dtable_apply_math_op2_bang(ary, arg, do_as_exponent_of);
1230
+ }
1231
+
1232
+ PRIVATE
1233
+ /*
1234
+ * call-seq:
1235
+ * dtable.safe_log!(cutoff=1e-99) -> dtable
1236
+ *
1237
+ * Replaces each entry x in _dtable_ by log(max(x,_cutoff_)).
1238
+ *
1239
+ */ VALUE dtable_safe_log_bang(int argc, VALUE *argv, VALUE self) {
1240
+ VALUE arg1;
1241
+ if ((argc < 0) || (argc > 1))
1242
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1243
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1244
+ return dtable_apply_math_op1_bang(self, arg1, do_safe_log);
1245
+ }
1246
+
1247
+ PRIVATE
1248
+ /*
1249
+ * call-seq:
1250
+ * dtable.safe_log10!(cutoff) -> dtable
1251
+ *
1252
+ * Replaces each entry x in _dtable_ by log10(max(x,_cutoff_)).
1253
+ *
1254
+ */ VALUE dtable_safe_log10_bang(int argc, VALUE *argv, VALUE self) {
1255
+ VALUE arg1;
1256
+ if ((argc < 0) || (argc > 1))
1257
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1258
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1259
+ return dtable_apply_math_op1_bang(self, arg1, do_safe_log10);
1260
+ }
1261
+
1262
+ PRIVATE
1263
+ /*
1264
+ * call-seq:
1265
+ * dtable.safe_inv!(cutoff) -> dtable
1266
+ *
1267
+ * Replaces each entry x in _dtable_ by sign(x)/_cutoff_ if abs(x) < _cutoff_, 1/x otherwise.
1268
+ *
1269
+ */ VALUE dtable_safe_inv_bang(int argc, VALUE *argv, VALUE self) {
1270
+ VALUE arg1;
1271
+ if ((argc < 0) || (argc > 1))
1272
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0 or 1)",argc);
1273
+ arg1 = (argc > 0)? argv[0] : rb_float_new(1e-99);
1274
+ return dtable_apply_math_op1_bang(self, arg1, do_safe_inv);
1275
+ }
1276
+
1277
+ PRIVATE
1278
+ /*
1279
+ * call-seq:
1280
+ * dtable.safe_sqrt! -> dtable
1281
+ *
1282
+ * Replaces each entry x in _dtable_ by sqrt(max(x,0)).
1283
+ *
1284
+ */ VALUE dtable_safe_sqrt_bang(VALUE ary) {
1285
+ return dtable_apply_math_op_bang(ary, do_safe_sqrt);
1286
+ }
1287
+
1288
+ PRIVATE
1289
+ /*
1290
+ * call-seq:
1291
+ * dtable.safe_asin! -> dtable
1292
+ *
1293
+ * Replaces each entry x in _dtable_ by asin(max(-1,min(1,x)))..
1294
+ *
1295
+ */ VALUE dtable_safe_asin_bang(VALUE ary) {
1296
+ return dtable_apply_math_op_bang(ary, do_safe_asin);
1297
+ }
1298
+
1299
+ PRIVATE
1300
+ /*
1301
+ * call-seq:
1302
+ * dtable.safe_acos! -> dtable
1303
+ *
1304
+ * Replaces each entry x in _dtable_ by acos(max(-1,min(1,x)))..
1305
+ *
1306
+ */ VALUE dtable_safe_acos_bang(VALUE ary) {
1307
+ return dtable_apply_math_op_bang(ary, do_safe_acos);
1308
+ }
1309
+
1310
+ PRIVATE VALUE dtable_apply_math_op2_bang(VALUE ary1, VALUE ary2, double (*op)(double, double)) {
1311
+ VALUE check = rb_obj_is_kind_of(ary2, rb_cNumeric);
1312
+ if (check != Qfalse) { return dtable_apply_math_op1_bang(ary1, ary2, op); }
1313
+ Dtable *d1 = Get_Dtable(ary1);
1314
+ Dtable *d2 = Get_Dtable(ary2);
1315
+ int num_cols = d1->num_cols, num_rows = d1->num_rows, i, j;
1316
+ if (num_cols != d2->num_cols || num_rows != d2->num_rows)
1317
+ rb_raise(rb_eArgError, "Dtable arrays must be same dimension for math operation");
1318
+ double **p1, **p2;
1319
+ p1 = d1->ptr; p2 = d2->ptr;
1320
+ for (i = 0; i < num_rows; i++) {
1321
+ for (j = 0; j < num_cols; j++) {
1322
+ p1[i][j] = (*op)(p1[i][j], p2[i][j]);
1323
+ }
1324
+ }
1325
+ return ary1;
1326
+ }
1327
+
1328
+ PRIVATE VALUE dtable_apply_math_op2(VALUE ary1, VALUE ary2, double (*op)(double, double)) {
1329
+ return dtable_apply_math_op2_bang(dtable_dup(ary1), ary2, op);
1330
+ }
1331
+
1332
+ static double do_add(double x, double y) { return x + y; }
1333
+ PRIVATE
1334
+ /*
1335
+ * call-seq:
1336
+ * dtable.add(number) -> a_dtable
1337
+ * dtable.add(other) -> a_dtable
1338
+ * dtable + number -> a_dtable
1339
+ * number + dtable -> a_dtable
1340
+ * dtable + other -> a_dtable
1341
+ *
1342
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x + _number_.
1343
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1344
+ * by x + the corresponding entry in the _other_ data array.
1345
+ */ VALUE dtable_add(VALUE ary, VALUE arg) {
1346
+ return dtable_apply_math_op2(ary, arg, do_add);
1347
+ }
1348
+
1349
+ static double do_sub(double x, double y) { return x - y; }
1350
+ PRIVATE
1351
+ /*
1352
+ * call-seq:
1353
+ * dtable.sub(number) -> a_dtable
1354
+ * dtable.sub(other) -> a_dtable
1355
+ * dtable - number -> a_dtable
1356
+ * number - dtable -> a_dtable
1357
+ * dtable - other -> a_dtable
1358
+ *
1359
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x - _number_.
1360
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1361
+ * by x - the corresponding entry in the _other_ data array.
1362
+ */ VALUE dtable_sub(VALUE ary, VALUE arg) {
1363
+ return dtable_apply_math_op2(ary, arg, do_sub);
1364
+ }
1365
+
1366
+ static double do_mul(double x, double y) { return x * y; }
1367
+ PRIVATE
1368
+ /*
1369
+ * call-seq:
1370
+ * dtable.mul(number) -> a_dtable
1371
+ * dtable.mul(other) -> a_dtable
1372
+ * dtable - number -> a_dtable
1373
+ * number - dtable -> a_dtable
1374
+ * dtable - other -> a_dtable
1375
+ *
1376
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x * _number_.
1377
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1378
+ * by x * the corresponding entry in the _other_ data array.
1379
+ */ VALUE dtable_mul(VALUE ary, VALUE arg) {
1380
+ return dtable_apply_math_op2(ary, arg, do_mul);
1381
+ }
1382
+
1383
+ static double do_div(double x, double y) { return x / y; }
1384
+ PRIVATE
1385
+ /*
1386
+ * call-seq:
1387
+ * dtable.div(number) -> a_dtable
1388
+ * dtable.div(other) -> a_dtable
1389
+ * dtable - number -> a_dtable
1390
+ * number - dtable -> a_dtable
1391
+ * dtable - other -> a_dtable
1392
+ *
1393
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x / _number_.
1394
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1395
+ * by x / the corresponding entry in the _other_ data array.
1396
+ */ VALUE dtable_div(VALUE ary, VALUE arg) {
1397
+ return dtable_apply_math_op2(ary, arg, do_div);
1398
+ }
1399
+
1400
+ PRIVATE
1401
+ /*
1402
+ * call-seq:
1403
+ * dtable.modulo(number) -> a_dtable
1404
+ * dtable.mod(number) -> a_dtable
1405
+ * dtable.modulo(other) -> a_dtable
1406
+ * dtable.mod(other) -> a_dtable
1407
+ * dtable % number -> a_dtable
1408
+ * dtable % other -> a_dtable
1409
+ *
1410
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x % _number_.
1411
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1412
+ * by x % the corresponding entry in the _other_ data array.
1413
+ *
1414
+ */ VALUE dtable_mod(VALUE ary, VALUE arg) {
1415
+ return dtable_apply_math_op2(ary, arg, do_mod);
1416
+ }
1417
+
1418
+ PRIVATE
1419
+ /*
1420
+ * call-seq:
1421
+ * dtable.remainder(number) -> a_dtable
1422
+ * dtable.remainder(other) -> a_dtable
1423
+ *
1424
+ * When the argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by the remainder of x divided by _number_.
1425
+ * When the argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1426
+ * by the remainder of x divided by the corresponding entry in the _other_ data array.
1427
+ */ VALUE dtable_remainder(VALUE ary, VALUE arg) {
1428
+ return dtable_apply_math_op2(ary, arg, do_remainder);
1429
+ }
1430
+
1431
+ PRIVATE
1432
+ /*
1433
+ * call-seq:
1434
+ * dtable.pow(number) -> a_dtable
1435
+ * dtable.pow(other) -> a_dtable
1436
+ * dtable.raised_to(number) -> a_dtable
1437
+ * dtable.raised_to(other) -> a_dtable
1438
+ * dtable ** number -> a_dtable
1439
+ * dtable ** other -> a_dtable
1440
+ *
1441
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by x ** _number_.
1442
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1443
+ * by x ** the corresponding entry in the _other_ data array.
1444
+ *
1445
+ */ VALUE dtable_pow(VALUE ary, VALUE arg) {
1446
+ return dtable_apply_math_op2(ary, arg, pow);
1447
+ }
1448
+
1449
+ PRIVATE
1450
+ /*
1451
+ * call-seq:
1452
+ * dtable.as_exponent_of(number) -> a_dtable
1453
+ * dtable.as_exponent_of(other) -> a_dtable
1454
+ *
1455
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by _number_ ** x.
1456
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1457
+ * by the corresponding entry in the _other_ data array raised to the power x.
1458
+ */ VALUE dtable_as_exponent_of(VALUE ary, VALUE arg) {
1459
+ return dtable_apply_math_op2(ary, arg, do_as_exponent_of);
1460
+ }
1461
+
1462
+ PRIVATE
1463
+ /*
1464
+ * call-seq:
1465
+ * dtable.atan2(number) -> a_dtable
1466
+ * dtable.atan2(other) -> a_dtable
1467
+ *
1468
+ * When argument is a number, this operation returns a copy of _dtable_ with each entry x replaced by the angle whose tangent is x/_number_.
1469
+ * When argument is a data array, this operation returns a copy of _dtable_ with each entry x replaced
1470
+ * by the angle whose tangent is x divided by the corresponding entry in the _other_ data array.
1471
+ */ VALUE dtable_atan2(VALUE ary, VALUE arg) {
1472
+ return dtable_apply_math_op2(ary, arg, atan2);
1473
+ }
1474
+
1475
+ PRIVATE
1476
+ /*
1477
+ * call-seq:
1478
+ * dtable.add!(number) -> dtable
1479
+ * dtable.add!(other) -> dtable
1480
+ *
1481
+ * When argument is a number, each entry x in _dtable_ is replaced by x + _number_.
1482
+ * When argument is a data array, each entry x in _dtable_ is replaced by x +
1483
+ * the corresponding entry in the _other_ data array.
1484
+ */ VALUE dtable_add_bang(VALUE ary, VALUE arg) {
1485
+ return dtable_apply_math_op2_bang(ary, arg, do_add);
1486
+ }
1487
+
1488
+ PRIVATE
1489
+ /*
1490
+ * call-seq:
1491
+ * dtable.sub!(number) -> dtable
1492
+ * dtable.sub!(other) -> dtable
1493
+ *
1494
+ * When argument is a number, each entry x in _dtable_ is replaced by x - _number_.
1495
+ * When argument is a data array, each entry x in _dtable_ is replaced by x -
1496
+ * the corresponding entry in the _other_ data array.
1497
+ */ VALUE dtable_sub_bang(VALUE ary, VALUE arg) {
1498
+ return dtable_apply_math_op2_bang(ary, arg, do_sub);
1499
+ }
1500
+
1501
+ PRIVATE
1502
+ /*
1503
+ * call-seq:
1504
+ * dtable.mul!(number) -> dtable
1505
+ * dtable.mul!(other) -> dtable
1506
+ *
1507
+ * When argument is a number, each entry x in _dtable_ is replaced by x * _number_.
1508
+ * When argument is a data array, each entry x in _dtable_ is replaced by x *
1509
+ * the corresponding entry in the _other_ data array.
1510
+ */ VALUE dtable_mul_bang(VALUE ary, VALUE arg) {
1511
+ return dtable_apply_math_op2_bang(ary, arg, do_mul);
1512
+ }
1513
+
1514
+ PRIVATE
1515
+ /*
1516
+ * call-seq:
1517
+ * dtable.div!(number) -> dtable
1518
+ * dtable.div!(other) -> dtable
1519
+ *
1520
+ * When argument is a number, each entry x in _dtable_ is replaced by x / _number_.
1521
+ * When argument is a data array, each entry x in _dtable_ is replaced by x /
1522
+ * the corresponding entry in the _other_ data array.
1523
+ */ VALUE dtable_div_bang(VALUE ary, VALUE arg) {
1524
+ return dtable_apply_math_op2_bang(ary, arg, do_div);
1525
+ }
1526
+
1527
+ PRIVATE
1528
+ /*======================================================================*/ VALUE Read_Dtable(VALUE dest, char *filename, int skip_lines) {
1529
+ FILE *file = NULL;
1530
+ long num_cols, num_rows;
1531
+ int i, j, k;
1532
+ const int buff_len = 10000;
1533
+ char c, buff[buff_len], *p, *pend;
1534
+ double *data, **ptr = Dtable_Ptr(dest, &num_cols, &num_rows);
1535
+ if ((file=fopen(filename,"r")) == NULL)
1536
+ rb_raise(rb_eArgError, "failed to open %s", filename);
1537
+ for (i = 0; i < skip_lines; i++) { /* skip over initial lines */
1538
+ if (fgets(buff, buff_len, file)==NULL) {
1539
+ fclose(file);
1540
+ rb_raise(rb_eArgError, "ERROR: read reached end of file before reaching line %i in %s",
1541
+ skip_lines, filename);
1542
+ }
1543
+ }
1544
+
1545
+ // rewrite to use strtod instead of fscanf to deal with numbers from fortran like 0.501-129 for 0.501E-129
1546
+
1547
+ for (i = 0; i < num_rows; i++) {
1548
+ data = ptr[i];
1549
+ for (j = 0; j < num_cols; j++) {
1550
+ // skip over blanks (includes end-of-line and tab)
1551
+ p = buff; k = 0;
1552
+ while ((c=getc(file)) != EOF) {
1553
+ if (!isspace(c)) break;
1554
+ }
1555
+ // save the non-blanks
1556
+ *p++ = c;
1557
+ while ((c=getc(file)) != EOF) {
1558
+ if (isspace(c) || k > 1000) break;
1559
+ *p++ = c;
1560
+ }
1561
+ *p = ' ';
1562
+ data[j] = strtod(buff,&pend);
1563
+ if (pend != p) { // need to check to see if have a number like 0.501-129
1564
+ if (pend[0] == '+' || pend[0] == '-') { // insert 'E' and try again
1565
+ pend[5] = ' '; pend[4] = pend[3]; pend[3] = pend[2]; pend[2] = pend[1]; pend[1] = pend[0]; pend[0] = 'E';
1566
+ data[j] = strtod(buff,&pend);
1567
+ }
1568
+ }
1569
+ if (!is_okay_number(data[j])) {
1570
+ fclose(file);
1571
+ rb_raise(rb_eArgError,
1572
+ "reached end of file before reading requested amount of data in %s (asked for %i xs and %i ys; found only %i and %i)",
1573
+ filename, num_cols, num_rows, i+1, j);
1574
+ }
1575
+ }
1576
+ }
1577
+ fclose(file);
1578
+ return dest;
1579
+ }
1580
+
1581
+
1582
+ PRIVATE
1583
+ /*
1584
+ * call-seq:
1585
+ * dtable.read(filename, skip_lines=0) -> dtable
1586
+ *
1587
+ * The contents of _dtable_ are replaced by the contents of the file, starting after skipping
1588
+ * the specified number of lines. The values in the file are listed with row number 0 first.
1589
+ *
1590
+ */ VALUE dtable_read(int argc, VALUE *argv, VALUE self) {
1591
+ if ((argc < 1) || (argc > 2))
1592
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1 or 2)",argc);
1593
+ VALUE filename = argv[0];
1594
+ int skip_lines = (argc==2)? NUM2INT(rb_Integer(argv[1])) : 0;
1595
+ return Read_Dtable(self, StringValuePtr(filename), skip_lines);
1596
+ }
1597
+
1598
+ PRIVATE VALUE dtable_entry(VALUE ary, long i, long j) {
1599
+ Dtable *d = Get_Dtable(ary);
1600
+ if (d->num_cols <= 0 || d->num_rows <= 0) return Qnil;
1601
+ if (i < 0) i += d->num_rows;
1602
+ if (j < 0) j += d->num_cols;
1603
+ if (i < 0 || d->num_rows <= i || j < 0 || d->num_cols <= j) return Qnil;
1604
+ return rb_float_new(d->ptr[i][j]);
1605
+ }
1606
+
1607
+ PRIVATE
1608
+ /*
1609
+ * call-seq:
1610
+ * dtable[row,col] -> number or nil
1611
+ * dtable.at(row,col) -> number or nil
1612
+ *
1613
+ * Returns the element at location _row_, _col_. Returns +nil+
1614
+ * if the location is out of range.
1615
+ */ VALUE dtable_at(VALUE ary, VALUE xloc, VALUE yloc) {
1616
+ return dtable_entry(ary, NUM2LONG(xloc), NUM2LONG(yloc));
1617
+ }
1618
+
1619
+ void dtable_store(VALUE ary, long i, long j, double v) {
1620
+ double **ptr;
1621
+ long num_cols, num_rows;
1622
+ ptr = Dtable_Ptr(ary, &num_cols, &num_rows);
1623
+ if (num_cols <= 0 || num_rows <= 0) {
1624
+ rb_raise(rb_eArgError, "bad args for setting entry in data array");
1625
+ }
1626
+ if (i < 0) i += num_rows;
1627
+ if (j < 0) j += num_cols;
1628
+ if (i < 0 || num_rows <= i || j < 0 || num_cols <= j) {
1629
+ rb_raise(rb_eArgError, "bad args for setting entry in data array");
1630
+ }
1631
+ ptr[i][j] = v;
1632
+ }
1633
+
1634
+ PRIVATE
1635
+ /*
1636
+ * call-seq:
1637
+ * dtable[row,col] = number -> number
1638
+ *
1639
+ * Replaces the element at location _row_, _col_ by the given _number_.
1640
+ */
1641
+ VALUE dtable_aset(VALUE ary, VALUE xloc, VALUE yloc, VALUE val) {
1642
+ dtable_store(ary, NUM2LONG(xloc), NUM2LONG(yloc), NUM2DBL(val));
1643
+ return val;
1644
+ }
1645
+
1646
+ #define DTABLE_DUMP_VERSION 1
1647
+
1648
+ PRIVATE
1649
+ /*
1650
+ Called by the marshalling mechanism to store a permanent copy of a
1651
+ Dtable. _limit_ is simply ignored.
1652
+ */
1653
+ VALUE dtable_dump(VALUE ary, VALUE limit)
1654
+ {
1655
+ int i; /* for STORE_UNSIGNED */
1656
+ long rows, cols;
1657
+ long x, y;
1658
+ double ** data = Dtable_Ptr(ary, &cols, &rows);
1659
+ double * col;
1660
+ long target_len = 1 /* first signature byte */
1661
+ + 8 /* 2 * length */
1662
+ + cols * rows * 8 ;
1663
+ unsigned u_len;
1664
+ VALUE str = rb_str_buf_new(target_len);
1665
+ /* \begin{playing with ruby's internals} */
1666
+ unsigned char * ptr = (unsigned char *) RSTRING(str)->ptr;
1667
+ /* signature byte */
1668
+ (*ptr++) = DTABLE_DUMP_VERSION;
1669
+ u_len = (unsigned) rows; /* limits to 4 billions rows */
1670
+ STORE_UNSIGNED(u_len, ptr); /* destroys u_len */
1671
+ u_len = (unsigned) cols; /* limits to 4 billions columns */
1672
+ STORE_UNSIGNED(u_len, ptr); /* destroys u_len */
1673
+ for(x = 0; x < rows; x++)
1674
+ {
1675
+ col = data[x];
1676
+ for(y = 0; y < cols; y++)
1677
+ {
1678
+ store_double(*(col++), ptr);
1679
+ ptr += 8;
1680
+ }
1681
+ }
1682
+ RSTRING(str)->len = target_len;
1683
+ return str;
1684
+ /* \end{playing with ruby's internals} */
1685
+ }
1686
+
1687
+ PRIVATE
1688
+ /*
1689
+ Called by the marshalling mechanism to retrieve a permanent copy of a
1690
+ Dtable.
1691
+ */
1692
+ VALUE dtable_load(VALUE klass, VALUE str)
1693
+ {
1694
+ VALUE ret = Qnil;
1695
+ VALUE s = StringValue(str);
1696
+ unsigned char * buf = (unsigned char *) StringValuePtr(s);
1697
+ unsigned char * dest = buf + RSTRING(s)->len;
1698
+ unsigned i; /* for GET_UNSIGNED */
1699
+ unsigned tmp = 0;
1700
+ long rows, cols;
1701
+ long x,y;
1702
+ double ** data;
1703
+ double * col;
1704
+ /* depending on the first byte, the decoding will be different */
1705
+ switch(*(buf++))
1706
+ {
1707
+ case 1:
1708
+ GET_UNSIGNED(tmp, buf);
1709
+ rows = tmp;
1710
+ GET_UNSIGNED(tmp, buf);
1711
+ cols = tmp;
1712
+ /* create a new Dtable with the right size */
1713
+ ret = dtable_init(dtable_alloc(cDtable), cols, rows);
1714
+ data = Dtable_Ptr(ret, NULL, NULL);
1715
+ for(x = 0; x < rows; x++)
1716
+ {
1717
+ col = data[x];
1718
+ for(y = 0; y< cols; y++)
1719
+ {
1720
+ if(buf + 8 > dest)
1721
+ {
1722
+ rb_raise(rb_eRuntimeError,
1723
+ "corrupted data given to Dtable._load");
1724
+ break;
1725
+ }
1726
+ else
1727
+ {
1728
+ col[y] = get_double(buf);
1729
+ buf += 8;
1730
+ }
1731
+ }
1732
+ }
1733
+ break;
1734
+ default:
1735
+ rb_raise(rb_eRuntimeError, "corrupted data given to Dtable._load");
1736
+ }
1737
+ return ret;
1738
+ }
1739
+
1740
+ /*
1741
+ * Document-class: Dobjects::Dtable
1742
+ *
1743
+ * Dtables are a specialized implementation of two-dimensional arrays of double precision floating point numbers.
1744
+ * They are intended for use in applications needing efficient processing of large 2D tables of numeric data.
1745
+ * Essentially any of the operations you might do with a Ruby Array of numbers can also be done with a Dtable.
1746
+ * Dtables follow the same design philosophy as Dvector and uses Dvectors for several operations.
1747
+ */
1748
+
1749
+
1750
+ PUBLIC void Init_Dtable() {
1751
+ /* modified by Vincent Fourmond, for splitting out the libraries */
1752
+
1753
+ rb_require("Dobjects/Dvector");
1754
+ /* we first make sure Dvector is included */
1755
+ VALUE mDobjects = rb_define_module("Dobjects");
1756
+ cDtable = rb_define_class_under(mDobjects, "Dtable", rb_cObject);
1757
+ /* end of modification */
1758
+
1759
+ rb_define_alloc_func(cDtable, dtable_alloc);
1760
+ rb_define_method(cDtable, "initialize", dtable_initialize, -1);
1761
+
1762
+ rb_define_method(cDtable, "read", dtable_read, -1);
1763
+
1764
+ rb_define_method(cDtable, "num_cols", dtable_num_cols, 0);
1765
+ rb_define_method(cDtable, "num_rows", dtable_num_rows, 0);
1766
+
1767
+ rb_define_method(cDtable, "at", dtable_at, 2);
1768
+ rb_define_alias(cDtable, "[]", "at");
1769
+ rb_define_method(cDtable, "[]=", dtable_aset, 3);
1770
+
1771
+ rb_define_method(cDtable, "row", dtable_row, 1);
1772
+ rb_define_method(cDtable, "column", dtable_column, 1);
1773
+ rb_define_method(cDtable, "set_row", dtable_set_row, 2);
1774
+ rb_define_method(cDtable, "set_column", dtable_set_column, 2);
1775
+
1776
+ rb_define_method(cDtable, "clear", dtable_clear, 0);
1777
+ rb_define_method(cDtable, "set", dtable_set, 1);
1778
+ rb_define_method(cDtable, "max", dtable_max, 0);
1779
+ rb_define_method(cDtable, "min", dtable_min, 0);
1780
+ rb_define_method(cDtable, "min_gt", dtable_min_gt, 1);
1781
+ rb_define_method(cDtable, "max_lt", dtable_max_lt, 1);
1782
+
1783
+ rb_define_method(cDtable, "dup", dtable_dup, 0);
1784
+ rb_define_method(cDtable, "transpose", dtable_transpose, 0);
1785
+ rb_define_method(cDtable, "reverse_rows", dtable_reverse_rows, 0);
1786
+ rb_define_method(cDtable, "reverse_cols", dtable_reverse_cols, 0);
1787
+ rb_define_method(cDtable, "rotate_cw90", dtable_rotate_cw90, 0);
1788
+ rb_define_method(cDtable, "rotate_ccw90", dtable_rotate_ccw90, 0);
1789
+
1790
+ /* math operations */
1791
+ rb_define_method(cDtable, "add", dtable_add, 1);
1792
+ rb_define_alias(cDtable, "+", "add");
1793
+ rb_define_alias(cDtable, "plus", "add");
1794
+ rb_define_method(cDtable, "sub", dtable_sub, 1);
1795
+ rb_define_alias(cDtable, "-", "sub");
1796
+ rb_define_alias(cDtable, "minus", "sub");
1797
+ rb_define_method(cDtable, "mul", dtable_mul, 1);
1798
+ rb_define_alias(cDtable, "*", "mul");
1799
+ rb_define_alias(cDtable, "times", "mul");
1800
+ rb_define_method(cDtable, "div", dtable_div, 1);
1801
+ rb_define_alias(cDtable, "/", "div");
1802
+ rb_define_method(cDtable, "modulo", dtable_mod, 1);
1803
+ rb_define_alias(cDtable, "mod", "modulo");
1804
+ rb_define_alias(cDtable, "%", "modulo");
1805
+ rb_define_method(cDtable, "remainder", dtable_remainder, 1);
1806
+ rb_define_method(cDtable, "pow", dtable_pow, 1);
1807
+ rb_define_alias(cDtable, "raised_to", "pow");
1808
+ rb_define_alias(cDtable, "**", "pow");
1809
+ rb_define_method(cDtable, "as_exponent_of", dtable_as_exponent_of, 1);
1810
+ rb_define_method(cDtable, "atan2", dtable_atan2, 1);
1811
+
1812
+ /* numeric methods */
1813
+ rb_define_method(cDtable, "abs", dtable_abs, 0);
1814
+ rb_define_method(cDtable, "ceil", dtable_ceil, 0);
1815
+ rb_define_method(cDtable, "floor", dtable_floor, 0);
1816
+ rb_define_method(cDtable, "round", dtable_round, 0);
1817
+
1818
+ /* standard math functions */
1819
+ rb_define_method(cDtable, "acos", dtable_acos, 0);
1820
+ rb_define_method(cDtable, "acosh", dtable_acosh, 0);
1821
+ rb_define_method(cDtable, "asin", dtable_asin, 0);
1822
+ rb_define_method(cDtable, "asinh", dtable_asinh, 0);
1823
+ rb_define_method(cDtable, "atan", dtable_atan, 0);
1824
+ rb_define_method(cDtable, "atanh", dtable_atanh, 0);
1825
+ rb_define_method(cDtable, "cos", dtable_cos, 0);
1826
+ rb_define_method(cDtable, "cosh", dtable_cosh, 0);
1827
+ rb_define_method(cDtable, "exp", dtable_exp, 0);
1828
+ rb_define_method(cDtable, "log", dtable_log, 0);
1829
+ rb_define_method(cDtable, "log10", dtable_log10, 0);
1830
+ rb_define_method(cDtable, "sin", dtable_sin, 0);
1831
+ rb_define_method(cDtable, "sinh", dtable_sinh, 0);
1832
+ rb_define_method(cDtable, "sqrt", dtable_sqrt, 0);
1833
+ rb_define_method(cDtable, "tan", dtable_tan, 0);
1834
+ rb_define_method(cDtable, "tanh", dtable_tanh, 0);
1835
+
1836
+ /* nonstandard math functions */
1837
+ rb_define_method(cDtable, "neg", dtable_neg, 0);
1838
+ rb_define_method(cDtable, "exp10", dtable_exp10, 0);
1839
+ rb_define_method(cDtable, "inv", dtable_inv, 0);
1840
+ rb_define_method(cDtable, "trim", dtable_trim, -1);
1841
+ rb_define_method(cDtable, "safe_log", dtable_safe_log, -1);
1842
+ rb_define_method(cDtable, "safe_log10", dtable_safe_log10, -1);
1843
+ rb_define_method(cDtable, "safe_inv", dtable_safe_inv, -1);
1844
+ rb_define_method(cDtable, "safe_sqrt", dtable_safe_sqrt, 0);
1845
+ rb_define_method(cDtable, "safe_asin", dtable_safe_asin, 0);
1846
+ rb_define_method(cDtable, "safe_acos", dtable_safe_acos, 0);
1847
+
1848
+ rb_define_method(cDtable, "add!", dtable_add_bang, 1);
1849
+ rb_define_alias(cDtable, "plus!", "add!");
1850
+ rb_define_method(cDtable, "sub!", dtable_sub_bang, 1);
1851
+ rb_define_alias(cDtable, "minus!", "sub!");
1852
+ rb_define_method(cDtable, "mul!", dtable_mul_bang, 1);
1853
+ rb_define_alias(cDtable, "times!", "mul!");
1854
+ rb_define_method(cDtable, "div!", dtable_div_bang, 1);
1855
+ rb_define_method(cDtable, "modulo!", dtable_modulo_bang, 1);
1856
+ rb_define_alias(cDtable, "mod!", "modulo!");
1857
+ rb_define_method(cDtable, "remainder!", dtable_remainder_bang, 1);
1858
+ rb_define_method(cDtable, "pow!", dtable_pow_bang, 1);
1859
+ rb_define_alias(cDtable, "raised_to!", "pow!");
1860
+ rb_define_method(cDtable, "as_exponent_of!", dtable_as_exponent_of_bang, 1);
1861
+ rb_define_method(cDtable, "atan2!", dtable_atan2_bang, 1);
1862
+
1863
+ rb_define_method(cDtable, "neg!", dtable_neg_bang, 0);
1864
+ rb_define_method(cDtable, "abs!", dtable_abs_bang, 0);
1865
+ rb_define_method(cDtable, "sin!", dtable_sin_bang, 0);
1866
+ rb_define_method(cDtable, "cos!", dtable_cos_bang, 0);
1867
+ rb_define_method(cDtable, "tan!", dtable_tan_bang, 0);
1868
+ rb_define_method(cDtable, "asin!", dtable_asin_bang, 0);
1869
+ rb_define_method(cDtable, "acos!", dtable_acos_bang, 0);
1870
+ rb_define_method(cDtable, "atan!", dtable_atan_bang, 0);
1871
+ rb_define_method(cDtable, "sinh!", dtable_sinh_bang, 0);
1872
+ rb_define_method(cDtable, "cosh!", dtable_cosh_bang, 0);
1873
+ rb_define_method(cDtable, "tanh!", dtable_tanh_bang, 0);
1874
+ rb_define_method(cDtable, "asinh!", dtable_asinh_bang, 0);
1875
+ rb_define_method(cDtable, "acosh!", dtable_acosh_bang, 0);
1876
+ rb_define_method(cDtable, "atanh!", dtable_atanh_bang, 0);
1877
+ rb_define_method(cDtable, "ceil!", dtable_ceil_bang, 0);
1878
+ rb_define_method(cDtable, "floor!", dtable_floor_bang, 0);
1879
+ rb_define_method(cDtable, "round!", dtable_round_bang, 0);
1880
+ rb_define_method(cDtable, "exp!", dtable_exp_bang, 0);
1881
+ rb_define_method(cDtable, "exp10!", dtable_exp10_bang, 0);
1882
+ rb_define_method(cDtable, "log!", dtable_log_bang, 0);
1883
+ rb_define_method(cDtable, "log10!", dtable_log10_bang, 0);
1884
+ rb_define_method(cDtable, "inv!", dtable_inv_bang, 0);
1885
+ rb_define_method(cDtable, "sqrt!", dtable_sqrt_bang, 0);
1886
+
1887
+ rb_define_method(cDtable, "trim!", dtable_trim_bang, -1);
1888
+ rb_define_method(cDtable, "safe_log!", dtable_safe_log_bang, -1);
1889
+ rb_define_method(cDtable, "safe_log10!", dtable_safe_log10_bang, -1);
1890
+ rb_define_method(cDtable, "safe_inv!", dtable_safe_inv_bang, -1);
1891
+ rb_define_method(cDtable, "safe_sqrt!", dtable_safe_sqrt_bang, 0);
1892
+ rb_define_method(cDtable, "safe_asin!", dtable_safe_asin_bang, 0);
1893
+ rb_define_method(cDtable, "safe_acos!", dtable_safe_acos_bang, 0);
1894
+
1895
+ /* Marshal : */
1896
+ rb_define_method(cDtable, "_dump", dtable_dump, 1);
1897
+ rb_define_singleton_method(cDtable, "_load", dtable_load, 1);
1898
+ /* modified by Vincent Fourmond, for splitting out the libraries */
1899
+ rb_require("Dobjects/Dtable_extras.rb");
1900
+ /* end of modification */
1901
+
1902
+ /* first, we export the symbols needed by other libraries
1903
+ see include/dtable.h for their description
1904
+ */
1905
+ RB_EXPORT_SYMBOL(cDtable, Read_Dtable);
1906
+ RB_EXPORT_SYMBOL(cDtable, Dtable_Ptr);
1907
+
1908
+ /* now we import the symbols from Dvector */
1909
+
1910
+ VALUE cDvector = rb_define_class_under(mDobjects, "Dvector", rb_cObject);
1911
+ RB_IMPORT_SYMBOL(cDvector, Dvector_Create);
1912
+ RB_IMPORT_SYMBOL(cDvector, Dvector_Data_Resize);
1913
+ RB_IMPORT_SYMBOL(cDvector, Dvector_Data_Replace);
1914
+ RB_IMPORT_SYMBOL(cDvector, Dvector_Data_for_Read);
1915
+ RB_IMPORT_SYMBOL(cDvector, Dvector_Store_Double);
1916
+
1917
+ }
1918
+
1919
+ /* implementing the symnbols just means that the location
1920
+ of the global variable with the pointer function will be here
1921
+ */
1922
+ IMPLEMENT_SYMBOL(Dvector_Create);
1923
+ IMPLEMENT_SYMBOL(Dvector_Data_Resize);
1924
+ IMPLEMENT_SYMBOL(Dvector_Data_Replace);
1925
+ IMPLEMENT_SYMBOL(Dvector_Data_for_Read);
1926
+ IMPLEMENT_SYMBOL(Dvector_Store_Double);
1927
+
1928
+