tioga 1.4

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 (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
+