linalg 1.0.2

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +24 -0
  3. data/ext/g2c_typedefs.h +5 -0
  4. data/ext/lapack/extconf.rb +309 -0
  5. data/ext/lapack/include/BLAS.h +154 -0
  6. data/ext/lapack/include/LAPACK.h +1314 -0
  7. data/ext/lapack/main.c +49 -0
  8. data/ext/lapack/rb_lapack.h +36 -0
  9. data/ext/lapack/rb_lapack_c.c +11614 -0
  10. data/ext/lapack/rb_lapack_d.c +12663 -0
  11. data/ext/lapack/rb_lapack_s.c +12649 -0
  12. data/ext/lapack/rb_lapack_x.c +208 -0
  13. data/ext/lapack/rb_lapack_z.c +11614 -0
  14. data/ext/linalg/dcomplex.c +359 -0
  15. data/ext/linalg/dcomplex.h +40 -0
  16. data/ext/linalg/ddata.c +194 -0
  17. data/ext/linalg/extconf.rb +324 -0
  18. data/ext/linalg/linalg.c +55 -0
  19. data/ext/linalg/linalg.h +21 -0
  20. data/ext/linalg/xdata.c +21 -0
  21. data/ext/linalg/xdata.h +33 -0
  22. data/ext/linalg/xmatrix.c.tmpl +1630 -0
  23. data/ext/linalg/xmatrix.h.tmpl +77 -0
  24. data/ext/linalg/xmatrixc.c.tmpl +138 -0
  25. data/ext/linalg/xmatrixr.c.tmpl +130 -0
  26. data/lib/lapack.rb +87 -0
  27. data/lib/linalg.rb +9 -0
  28. data/lib/linalg/dcomplex.rb +17 -0
  29. data/lib/linalg/dmatrix.rb +29 -0
  30. data/lib/linalg/dmatrix/alias.rb +32 -0
  31. data/lib/linalg/dmatrix/cholesky.rb +52 -0
  32. data/lib/linalg/dmatrix/cond.rb +80 -0
  33. data/lib/linalg/dmatrix/det.rb +36 -0
  34. data/lib/linalg/dmatrix/eigen.rb +153 -0
  35. data/lib/linalg/dmatrix/fit.rb +281 -0
  36. data/lib/linalg/dmatrix/inverse.rb +78 -0
  37. data/lib/linalg/dmatrix/lu.rb +120 -0
  38. data/lib/linalg/dmatrix/main.rb +244 -0
  39. data/lib/linalg/dmatrix/norms.rb +88 -0
  40. data/lib/linalg/dmatrix/nullspace.rb +114 -0
  41. data/lib/linalg/dmatrix/qr.rb +129 -0
  42. data/lib/linalg/dmatrix/schur.rb +88 -0
  43. data/lib/linalg/dmatrix/solve.rb +78 -0
  44. data/lib/linalg/dmatrix/svd.rb +125 -0
  45. data/lib/linalg/exception.rb +32 -0
  46. data/lib/linalg/iterators.rb +221 -0
  47. data/lib/linalg/math.rb +23 -0
  48. data/lib/linalg/scomplex.rb +15 -0
  49. data/lib/linalg/version.rb +3 -0
  50. data/lib/linalg/xdata.rb +123 -0
  51. metadata +94 -0
@@ -0,0 +1,1630 @@
1
+ /*
2
+ * Copyright (c) 2004-2008 by James M. Lawrence
3
+ *
4
+ * See LICENSE
5
+ *
6
+ * Inspired by Rubikitch's +DMatrix+ class in +mathx+.
7
+ *
8
+ */
9
+
10
+ #include "CLASSLOWER.h"
11
+
12
+ /**************************************************
13
+ *
14
+ * globals
15
+ *
16
+ **************************************************/
17
+
18
+ VALUE rb_cCLASSUPPER ;
19
+
20
+ /**************************************************
21
+ *
22
+ * statics
23
+ *
24
+ **************************************************/
25
+
26
+ static integer integer_1 = 1 ;
27
+
28
+ /**************************************************
29
+ **************************************************
30
+ *
31
+ * CLASSUPPER core
32
+ *
33
+ **************************************************
34
+ **************************************************/
35
+
36
+ /**************************************************
37
+ *
38
+ * init
39
+ *
40
+ **************************************************/
41
+
42
+ void CLASSUPPER_init(CLASSUPPER* a, integer vsize, integer hsize)
43
+ {
44
+ a->vsize = vsize ;
45
+ a->hsize = hsize ;
46
+ a->data = (FORTRANTYPE*)ALLOC_N(FORTRANTYPE, vsize*hsize) ;
47
+ }
48
+
49
+ /**************************************************
50
+ *
51
+ * constructors
52
+ *
53
+ **************************************************/
54
+
55
+ CLASSUPPER* CLASSUPPER_new(integer vsize, integer hsize)
56
+ {
57
+ CLASSUPPER* a = (CLASSUPPER*)ALLOC(CLASSUPPER) ;
58
+ a->data = (FORTRANTYPE*)ALLOC_N(FORTRANTYPE, vsize*hsize) ;
59
+ a->vsize = vsize ;
60
+ a->hsize = hsize ;
61
+ return a ;
62
+ }
63
+
64
+ CLASSUPPER* CLASSUPPER_clone(CLASSUPPER* a)
65
+ {
66
+ CLASSUPPER* dup = CLASSUPPER_new(a->vsize, a->hsize) ;
67
+ integer size = a->vsize*a->hsize ;
68
+ xcopy_(&size , a->data, &integer_1, dup->data, &integer_1) ;
69
+ return dup ;
70
+ }
71
+
72
+ /**************************************************
73
+ *
74
+ * destructor
75
+ *
76
+ **************************************************/
77
+
78
+ void CLASSUPPER_free(CLASSUPPER* a)
79
+ {
80
+ free(a->data) ;
81
+ free(a) ;
82
+ }
83
+
84
+ /**************************************************
85
+ *
86
+ * assignment
87
+ *
88
+ **************************************************/
89
+
90
+ CLASSUPPER* CLASSUPPER_assign(CLASSUPPER* c, CLASSUPPER* a)
91
+ {
92
+ integer size = a->vsize*a->hsize ;
93
+
94
+ xcopy_(&size,
95
+ a->data,
96
+ &integer_1,
97
+ c->data,
98
+ &integer_1) ;
99
+
100
+ return c ;
101
+ }
102
+
103
+ CLASSUPPER* CLASSUPPER_swap(CLASSUPPER* c, CLASSUPPER* a)
104
+ {
105
+ CLASSUPPER tmp = *c ;
106
+ *c = *a ;
107
+ *a = tmp ;
108
+ return c ;
109
+ }
110
+
111
+ /**************************************************
112
+ *
113
+ * fillers
114
+ *
115
+ **************************************************/
116
+
117
+ CLASSUPPER* CLASSUPPER_fill(CLASSUPPER* a, FORTRANTYPE value)
118
+ {
119
+ FORTRANTYPE* p = a->data ;
120
+ FORTRANTYPE* end = p + a->vsize*a->hsize ;
121
+
122
+ for( ; p != end ; ++p )
123
+ {
124
+ *p = value ;
125
+ }
126
+
127
+ return a ;
128
+ }
129
+
130
+ CLASSUPPER* CLASSUPPER_scalar_diagonal(CLASSUPPER* c, FORTRANTYPE s)
131
+ {
132
+ integer i ;
133
+
134
+ CLASSUPPER_fill(c, CLASSLOWER_FORTRANTYPE_0) ;
135
+
136
+ for( i = 0 ; i != c->vsize ; ++i )
137
+ {
138
+ c->data[i + i*c->vsize] = s ;
139
+ }
140
+
141
+ return c ;
142
+ }
143
+
144
+ CLASSUPPER* CLASSUPPER_identity(CLASSUPPER* a)
145
+ {
146
+ return CLASSUPPER_scalar_diagonal(a, CLASSLOWER_FORTRANTYPE_1) ;
147
+ }
148
+
149
+ /**************************************************
150
+ *
151
+ * operations
152
+ *
153
+ **************************************************/
154
+
155
+ CLASSUPPER* CLASSUPPER_mul(CLASSUPPER* c, CLASSUPPER* a, CLASSUPPER* b)
156
+ {
157
+ xgemm_("N",
158
+ "N",
159
+ &a->vsize,
160
+ &b->hsize,
161
+ &a->hsize,
162
+ &CLASSLOWER_FORTRANTYPE_1,
163
+ a->data,
164
+ &a->vsize,
165
+ b->data,
166
+ &b->vsize,
167
+ &CLASSLOWER_FORTRANTYPE_0,
168
+ c->data,
169
+ &c->vsize) ;
170
+
171
+ return c ;
172
+ }
173
+
174
+ CLASSUPPER* CLASSUPPER_mul_scalar(CLASSUPPER* a, FORTRANTYPE s)
175
+ {
176
+ integer n = a->vsize*a->hsize ;
177
+
178
+ xscal_(&n,
179
+ &s,
180
+ a->data,
181
+ &integer_1) ;
182
+
183
+ return a ;
184
+ }
185
+
186
+ CLASSUPPER* CLASSUPPER_plus(CLASSUPPER* a, CLASSUPPER* b)
187
+ {
188
+ integer n = a->vsize*a->hsize ;
189
+
190
+ xaxpy_(&n,
191
+ &CLASSLOWER_FORTRANTYPE_1,
192
+ b->data,
193
+ &integer_1,
194
+ a->data,
195
+ &integer_1) ;
196
+
197
+ return a ;
198
+ }
199
+
200
+ CLASSUPPER* CLASSUPPER_minus(CLASSUPPER* a, CLASSUPPER* b)
201
+ {
202
+ integer n = a->vsize*a->hsize ;
203
+
204
+ xaxpy_(&n,
205
+ &CLASSLOWER_FORTRANTYPE_neg_1,
206
+ b->data,
207
+ &integer_1,
208
+ a->data,
209
+ &integer_1) ;
210
+
211
+ return a ;
212
+ }
213
+
214
+ CLASSUPPER* CLASSUPPER_transpose( CLASSUPPER* c, CLASSUPPER* a )
215
+ {
216
+ if( a->vsize > a->hsize )
217
+ {
218
+ int j ;
219
+
220
+ for( j = 0 ; j != a->hsize ; ++j )
221
+ {
222
+ xcopy_(&a->vsize,
223
+ &a->data[j*a->vsize],
224
+ &integer_1,
225
+ &c->data[j],
226
+ &c->vsize) ;
227
+ }
228
+ }
229
+ else
230
+ {
231
+ int i ;
232
+
233
+ for( i = 0 ; i != a->vsize ; ++i )
234
+ {
235
+ xcopy_(&a->hsize,
236
+ &a->data[i],
237
+ &a->vsize,
238
+ &c->data[i*c->vsize],
239
+ &integer_1) ;
240
+ }
241
+ }
242
+
243
+ return c ;
244
+ }
245
+
246
+ CLASSUPPER* CLASSUPPER_transpose_inplace( CLASSUPPER* a )
247
+ {
248
+ if( a->vsize == 1 || a->hsize == 1 )
249
+ {
250
+ integer tmp = a->vsize ;
251
+ a->vsize = a->hsize ;
252
+ a->hsize = tmp ;
253
+ }
254
+ else
255
+ {
256
+ CLASSUPPER* dup = CLASSUPPER_clone(a) ;
257
+
258
+ integer tmp = a->vsize ;
259
+ a->vsize = a->hsize ;
260
+ a->hsize = tmp ;
261
+
262
+ CLASSUPPER_transpose(a, dup) ;
263
+
264
+ CLASSUPPER_free(dup) ;
265
+ }
266
+
267
+ return a ;
268
+ }
269
+
270
+ CLASSUPPER* CLASSUPPER_minor( CLASSUPPER* c,
271
+ CLASSUPPER* a,
272
+ integer minor_i,
273
+ integer minor_j,
274
+ integer minor_vsize,
275
+ integer minor_hsize )
276
+ {
277
+ int j ;
278
+
279
+ for( j = 0 ; j != minor_hsize ; ++j )
280
+ {
281
+ xcopy_(&minor_vsize,
282
+ &a->data[minor_i + (minor_j + j)*a->vsize],
283
+ &integer_1,
284
+ &c->data[j*minor_vsize],
285
+ &integer_1) ;
286
+ }
287
+
288
+ return c ;
289
+ }
290
+
291
+ CLASSUPPER* CLASSUPPER_replace_minor( CLASSUPPER* c,
292
+ integer minor_i,
293
+ integer minor_j,
294
+ CLASSUPPER* a )
295
+ {
296
+ int j ;
297
+
298
+ for( j = 0 ; j != a->hsize ; ++j )
299
+ {
300
+ xcopy_(&a->vsize,
301
+ &a->data[j*a->vsize],
302
+ &integer_1,
303
+ &c->data[minor_i + (minor_j + j)*c->vsize],
304
+ &integer_1) ;
305
+ }
306
+
307
+ return c ;
308
+ }
309
+
310
+ /**************************************************
311
+ **************************************************
312
+ *
313
+ * ruby interface
314
+ *
315
+ **************************************************
316
+ **************************************************/
317
+
318
+ /**************************************************
319
+ *
320
+ * util
321
+ *
322
+ **************************************************/
323
+
324
+ static integer num2size(VALUE val)
325
+ {
326
+ integer n = NUM2INT(val) ;
327
+ if( n < 1 )
328
+ {
329
+ raise_dim_error() ;
330
+ }
331
+ return n ;
332
+ }
333
+
334
+ /**************************************************
335
+ *
336
+ * allocate
337
+ *
338
+ **************************************************/
339
+
340
+ VALUE rb_CLASSLOWER_allocate( VALUE klass )
341
+ {
342
+ CLASSUPPER* a ;
343
+ VALUE obj = Data_Make_Struct(klass,
344
+ CLASSUPPER,
345
+ 0,
346
+ CLASSUPPER_free,
347
+ a) ;
348
+ return obj ;
349
+ }
350
+
351
+ /**************************************************
352
+ *
353
+ * constructors
354
+ *
355
+ **************************************************/
356
+
357
+ /*
358
+ * call-seq: rows(array)
359
+ *
360
+ * Create a matrix using the elements of +array+ as rows.
361
+ *
362
+ * CLASSUPPER.rows(array)
363
+ *
364
+ * is equivalent to
365
+ *
366
+ * CLASSUPPER.new(array.size, array[0].size) { |i,j| array[i][j] }
367
+ *
368
+ * +DimensionError+ is raised if +array+ is not rectangular.
369
+ *
370
+ */
371
+ VALUE rb_CLASSLOWER_s_rows( VALUE klass, VALUE array )
372
+ {
373
+ int i ;
374
+ int j ;
375
+ int vsize ;
376
+ int hsize ;
377
+
378
+ VALUE* ptr ;
379
+ VALUE crow ;
380
+
381
+ CLASSUPPER* a = 0 ;
382
+ VALUE ra ;
383
+
384
+ if( TYPE(array) != T_ARRAY )
385
+ {
386
+ raise_bad_array() ;
387
+ }
388
+
389
+ ptr = RARRAY_PTR(array) ;
390
+ vsize = RARRAY_LEN(array) ;
391
+
392
+ if( vsize < 1 || TYPE(ptr[0]) != T_ARRAY )
393
+ {
394
+ raise_bad_array() ;
395
+ }
396
+ if( (hsize = RARRAY_LEN(ptr[0])) == 0 )
397
+ {
398
+ raise_bad_array() ;
399
+ }
400
+
401
+ a = CLASSUPPER_new(vsize, hsize) ;
402
+ ra = wrap_CLASSLOWER(a) ;
403
+
404
+ for( i = 0 ; i != vsize ; ++i )
405
+ {
406
+ crow = ptr[i] ;
407
+
408
+ if( TYPE(crow) != T_ARRAY )
409
+ {
410
+ raise_bad_array() ;
411
+ }
412
+
413
+ if( RARRAY_LEN(crow) != hsize )
414
+ {
415
+ raise_bad_array() ;
416
+ }
417
+
418
+ for( j = 0 ; j != hsize ; j++ )
419
+ {
420
+ a->data[i + j*a->vsize] = RUBY2FORTRAN(RARRAY_PTR(crow)[j]) ;
421
+ }
422
+ }
423
+
424
+ return ra ;
425
+ }
426
+
427
+ /*
428
+ * call-seq: rand(vsize, hsize)
429
+ *
430
+ * Create a matrix filled with random numbers between -1.0 and 1.0.
431
+ *
432
+ * Similar to
433
+ *
434
+ * CLASSUPPER.new(vsize, hsize) { 2*rand - 1 }
435
+ *
436
+ * except uses <tt>rand()</tt> from <tt>stdlib.h</tt>
437
+ *
438
+ */
439
+ VALUE rb_CLASSLOWER_s_rand(VALUE klass, VALUE rvsize, VALUE rhsize)
440
+ {
441
+ CLASSUPPER* a = CLASSUPPER_new(num2size(rvsize),
442
+ num2size(rhsize)) ;
443
+
444
+ static int first = 1 ;
445
+ if( first )
446
+ {
447
+ srand(time(NULL)) ;
448
+ first = 0 ;
449
+ }
450
+
451
+ CLASSUPPER_rand(a) ;
452
+ return wrap_CLASSLOWER(a) ;
453
+ }
454
+
455
+ /*
456
+ * call-seq: identity(n)
457
+ *
458
+ * Create an +n+ x +n+ identity matrix.
459
+ *
460
+ */
461
+ VALUE rb_CLASSLOWER_s_identity(VALUE klass, VALUE rsize)
462
+ {
463
+ int size = num2size(rsize) ;
464
+ CLASSUPPER* a = CLASSUPPER_new(size, size) ;
465
+ CLASSUPPER_identity(a) ;
466
+ return wrap_CLASSLOWER(a) ;
467
+ }
468
+
469
+ /*
470
+ * call-seq: clone
471
+ *
472
+ * Deep copy
473
+ *
474
+ */
475
+ VALUE rb_CLASSLOWER_clone(VALUE self)
476
+ {
477
+ CLASSUPPER* a ;
478
+ get_CLASSLOWER(a, self) ;
479
+ return wrap_CLASSLOWER(CLASSUPPER_clone(a)) ;
480
+ }
481
+
482
+ /*
483
+ * call-seq:
484
+ * diagonal(array)
485
+ * diagonal(vector)
486
+ * diagonal(n, scalar)
487
+ * diagonal(n) { |i| ... }
488
+ *
489
+ * In the first form, create a diagonal matrix with the elements of
490
+ * +array+ along the diagonal. The second form is like the first but
491
+ * using elements of the column vector +vector+. In the third form,
492
+ * create an +n+ x +n+ diagonal matrix with diagonal elements of value
493
+ * +scalar+. In the fourth form, each element <tt>m[i,i]</tt> gets
494
+ * the block result.
495
+ *
496
+ */
497
+ VALUE rb_CLASSLOWER_s_diagonal(int argc, VALUE* argv, VALUE klass)
498
+ {
499
+ CLASSUPPER* a ;
500
+ VALUE ra ;
501
+ VALUE rb ;
502
+ VALUE rscalar ;
503
+ int scan = rb_scan_args(argc, argv, "11", &rb, &rscalar) ;
504
+
505
+ if( scan == 1 )
506
+ {
507
+ if( rb_block_given_p() )
508
+ {
509
+ int i ;
510
+ int size = num2size(rb) ;
511
+ a = CLASSUPPER_new(size, size) ;
512
+ ra = wrap_CLASSLOWER(a) ;
513
+
514
+ VALUE result ;
515
+
516
+ CLASSUPPER_fill(a, CLASSLOWER_FORTRANTYPE_0) ;
517
+
518
+ for( i = 0 ; i != size ; ++i )
519
+ {
520
+ result = rb_yield(INT2FIX(i)) ;
521
+ a->data[i + i*a->vsize] = RUBY2FORTRAN(result) ;
522
+ }
523
+ }
524
+ else if( rb_obj_is_kind_of(rb, rb_cCLASSUPPER) )
525
+ {
526
+ int i ;
527
+ CLASSUPPER* b ;
528
+
529
+ get_CLASSLOWER(b, rb) ;
530
+
531
+ if( b->hsize != 1 )
532
+ {
533
+ raise_dim_error() ;
534
+ }
535
+
536
+ a = CLASSUPPER_new(b->vsize, b->vsize) ;
537
+ ra = wrap_CLASSLOWER(a) ;
538
+
539
+ CLASSUPPER_fill(a, CLASSLOWER_FORTRANTYPE_0) ;
540
+
541
+ for( i = 0 ; i != b->vsize ; ++i )
542
+ {
543
+ a->data[i + i*a->vsize] = b->data[i] ;
544
+ }
545
+ }
546
+ else if( TYPE(rb) == T_ARRAY )
547
+ {
548
+ VALUE* c_arr ;
549
+ long size ;
550
+ int i ;
551
+
552
+ c_arr = RARRAY_PTR(rb) ;
553
+ size = RARRAY_LEN(rb) ;
554
+
555
+ if( size < 1 )
556
+ {
557
+ raise_dim_error() ;
558
+ }
559
+
560
+ a = CLASSUPPER_new(size, size) ;
561
+ ra = wrap_CLASSLOWER(a) ;
562
+
563
+ CLASSUPPER_fill(a, CLASSLOWER_FORTRANTYPE_0) ;
564
+
565
+ for( i = 0 ; i != size ; ++i )
566
+ {
567
+ a->data[i + i*a->vsize] = RUBY2FORTRAN(c_arr[i]) ;
568
+ }
569
+ }
570
+ else
571
+ {
572
+ rb_raise(rb_eRuntimeError, "not a vector or array") ;
573
+ }
574
+ }
575
+ else
576
+ {
577
+ int size = num2size(rb) ;
578
+ a = CLASSUPPER_new(size, size) ;
579
+ ra = wrap_CLASSLOWER(a) ;
580
+ CLASSUPPER_scalar_diagonal(a, RUBY2FORTRAN(rscalar)) ;
581
+ }
582
+
583
+ return ra ;
584
+ }
585
+
586
+ /*
587
+ * :nodoc:
588
+ */
589
+ VALUE rb_CLASSLOWER_reserve(VALUE klass, VALUE rvsize, VALUE rhsize)/* :nodoc: */
590
+ {
591
+ integer vsize = num2size(rvsize) ;
592
+ integer hsize = num2size(rhsize) ;
593
+ return wrap_CLASSLOWER(CLASSUPPER_new(vsize, hsize)) ;
594
+ }
595
+
596
+ /**************************************************
597
+ *
598
+ * instance methods
599
+ *
600
+ **************************************************/
601
+
602
+ /*
603
+ * call-seq:
604
+ * new(vsize, hsize)
605
+ * new(vsize, hsize, scalar)
606
+ * new(vsize, hsize) { |i, j| ... }
607
+ *
608
+ * Returns a new matrix with dimensions [+vsize+, +hsize+].
609
+ *
610
+ * In the first form, the matrix is filled with zero. In the second
611
+ * form, the matrix is filled with +scalar+. In the third form, each
612
+ * index pair is passed to the block and the respective matrix element
613
+ * is assigned the block result.
614
+ *
615
+ * CLASSUPPER.new(4,4) { |i,j| i == j ? 1 : 0 }
616
+ *
617
+ * is the 4 x 4 identity matrix.
618
+ *
619
+ */
620
+ VALUE rb_CLASSLOWER_initialize(int argc, VALUE* argv, VALUE self)
621
+ {
622
+ CLASSUPPER* a ;
623
+ VALUE rvsize ;
624
+ VALUE rhsize ;
625
+ VALUE rscalar ;
626
+
627
+ int scan = rb_scan_args(argc, argv, "21", &rvsize, &rhsize, &rscalar) ;
628
+
629
+ get_CLASSLOWER(a, self) ;
630
+ CLASSUPPER_init(a, num2size(rvsize), num2size(rhsize)) ;
631
+
632
+ if( scan == 3 )
633
+ {
634
+ CLASSUPPER_fill(a, RUBY2FORTRAN(rscalar)) ;
635
+ }
636
+ else if( rb_block_given_p() == Qtrue )
637
+ {
638
+ int i ;
639
+ int j ;
640
+
641
+ for( j = 0 ; j != a->hsize ; ++j )
642
+ {
643
+ for( i = 0 ; i != a->vsize ; ++i )
644
+ {
645
+ VALUE pair = rb_assoc_new(INT2FIX(i),
646
+ INT2FIX(j)) ;
647
+ a->data[i + j*a->vsize] = RUBY2FORTRAN(rb_yield(pair)) ;
648
+ }
649
+ }
650
+ }
651
+ else
652
+ {
653
+ CLASSUPPER_fill(a, CLASSLOWER_FORTRANTYPE_0) ;
654
+ }
655
+
656
+ return self ;
657
+ }
658
+
659
+ /*
660
+ * call-seq: fill(value)
661
+ *
662
+ * Fill the matrix with +value+.
663
+ */
664
+ VALUE rb_CLASSLOWER_fill(VALUE self, VALUE rval)
665
+ {
666
+ FORTRANTYPE val = RUBY2FORTRAN(rval) ;
667
+ CLASSUPPER* a ;
668
+ get_CLASSLOWER(a, self) ;
669
+ CLASSUPPER_fill(a, val) ;
670
+ return self ;
671
+ }
672
+
673
+ /*
674
+ * call-seq: vsize
675
+ *
676
+ * Vertical size of the matrix (number of rows)
677
+ *
678
+ */
679
+ VALUE rb_CLASSLOWER_vsize(VALUE self)
680
+ {
681
+ CLASSUPPER* a ;
682
+ get_CLASSLOWER(a, self) ;
683
+ return INT2FIX(a->vsize) ;
684
+ }
685
+
686
+ /*
687
+ *
688
+ * call-seq: hsize
689
+ *
690
+ * Horizontal size of the matrix (number of columns)
691
+ *
692
+ */
693
+ VALUE rb_CLASSLOWER_hsize(VALUE self)
694
+ {
695
+ CLASSUPPER* a ;
696
+ get_CLASSLOWER(a, self) ;
697
+ return INT2FIX(a->hsize) ;
698
+ }
699
+
700
+ /*
701
+ * call-seq: dimensions
702
+ *
703
+ * Returns the pair
704
+ *
705
+ * [a.vsize, a.hsize]
706
+ *
707
+ */
708
+ VALUE rb_CLASSLOWER_dimensions(VALUE self)
709
+ {
710
+ CLASSUPPER* a ;
711
+ get_CLASSLOWER(a, self) ;
712
+ return rb_assoc_new(INT2FIX(a->vsize),
713
+ INT2FIX(a->hsize)) ;
714
+ }
715
+
716
+ /*
717
+ *
718
+ * call-seq: [](row, column)
719
+ *
720
+ * Element read. Column vectors are permitted to omit the +column+ index.
721
+ *
722
+ */
723
+ VALUE rb_CLASSLOWER_bracket_get(int argc, VALUE* argv, VALUE self)
724
+ {
725
+ VALUE ri ;
726
+ VALUE rj ;
727
+ int i = 0 ;
728
+ int j = 0 ;
729
+ CLASSUPPER* a ;
730
+ get_CLASSLOWER(a, self) ;
731
+
732
+ if( rb_scan_args(argc, argv, "11", &ri, &rj) == 1 )
733
+ {
734
+ if( a->hsize == 1 )
735
+ {
736
+ i = NUM2INT(ri) ;
737
+ j = 0 ;
738
+ }
739
+ else
740
+ {
741
+ rb_raise(rb_eArgError, "") ;
742
+ }
743
+ }
744
+ else
745
+ {
746
+ i = NUM2INT(ri) ;
747
+ j = NUM2INT(rj) ;
748
+ }
749
+
750
+ if( i < 0 || i >= a->vsize ||
751
+ j < 0 || j >= a->hsize )
752
+ {
753
+ raise_index_error() ;
754
+ }
755
+
756
+ return FORTRAN2RUBY(a->data[i + j*a->vsize]) ;
757
+ }
758
+
759
+ /*
760
+ *
761
+ * call-seq: []=(row, column)
762
+ *
763
+ * Element write. Column vectors are permitted to omit the +column+ index.
764
+ *
765
+ */
766
+ VALUE rb_CLASSLOWER_bracket_set(int argc, VALUE* argv, VALUE self)
767
+ {
768
+ CLASSUPPER* a ;
769
+ int i = 0 ;
770
+ int j = 0 ;
771
+ VALUE ri ;
772
+ VALUE rj ;
773
+ VALUE rv ;
774
+
775
+ get_CLASSLOWER(a, self) ;
776
+
777
+ if( rb_scan_args(argc, argv, "21", &ri, &rj, &rv) == 2 )
778
+ {
779
+ rv = rj ;
780
+
781
+ if( a->hsize == 1 )
782
+ {
783
+ i = NUM2INT(ri) ;
784
+ j = 0 ;
785
+ }
786
+ else
787
+ {
788
+ raise_index_error() ;
789
+ }
790
+ }
791
+ else
792
+ {
793
+ i = NUM2INT(ri) ;
794
+ j = NUM2INT(rj) ;
795
+ }
796
+
797
+ if( i < 0 || i >= a->vsize ||
798
+ j < 0 || j >= a->hsize )
799
+ {
800
+ raise_index_error() ;
801
+ }
802
+
803
+ a->data[i + j*a->vsize] = RUBY2FORTRAN(rv) ;
804
+ return rv ;
805
+ }
806
+
807
+ /*
808
+ * call-seq: *(b)
809
+ *
810
+ * Matrix multiply
811
+ *
812
+ * c = a * b
813
+ *
814
+ * +DimensionError+ is raised unless
815
+ *
816
+ * a.hsize == b.vsize
817
+ *
818
+ */
819
+ VALUE rb_CLASSLOWER_mul(VALUE self, VALUE rb)
820
+ {
821
+ CLASSUPPER* a ;
822
+ get_CLASSLOWER(a, self) ;
823
+
824
+ if( rb_obj_is_kind_of(rb, rb_cCLASSUPPER) )
825
+ {
826
+ CLASSUPPER* b ;
827
+ CLASSUPPER* c ;
828
+
829
+ get_CLASSLOWER(b, rb) ;
830
+
831
+ if( a->hsize != b->vsize )
832
+ {
833
+ raise_dim_error() ;
834
+ }
835
+
836
+ c = CLASSUPPER_new(a->vsize, b->hsize) ;
837
+ CLASSUPPER_mul(c, a, b) ;
838
+ return wrap_CLASSLOWER(c) ;
839
+ }
840
+ else
841
+ {
842
+ CLASSUPPER* c = CLASSUPPER_clone(a) ;
843
+ CLASSUPPER_mul_scalar(c, RUBY2FORTRAN(rb)) ;
844
+ return wrap_CLASSLOWER(c) ;
845
+ }
846
+ }
847
+
848
+ /*
849
+ * call-seq: postmul!(b)
850
+ *
851
+ * In-place multiply
852
+ *
853
+ * c = a * b
854
+ *
855
+ * is equivalent to
856
+ *
857
+ * c = a.postmul!(b)
858
+ *
859
+ * with
860
+ *
861
+ * a.object_id == c.object_id
862
+ *
863
+ * Note this implies +b+ must be square. +DimensionError+ is raised
864
+ * otherwise.
865
+ *
866
+ */
867
+ VALUE rb_CLASSLOWER_postmul_inplace(VALUE self, VALUE rb)
868
+ {
869
+ CLASSUPPER* a ;
870
+ get_CLASSLOWER(a, self) ;
871
+
872
+ if( rb_obj_is_kind_of(rb, rb_cCLASSUPPER) )
873
+ {
874
+ CLASSUPPER* b ;
875
+ CLASSUPPER* c ;
876
+
877
+ get_CLASSLOWER(b, rb) ;
878
+
879
+ if( a->hsize != b->vsize ||
880
+ b->vsize != b->hsize )
881
+ {
882
+ raise_dim_error() ;
883
+ }
884
+
885
+ c = CLASSUPPER_new(a->vsize, b->hsize) ;
886
+ CLASSUPPER_mul(c, a, b) ;
887
+ CLASSUPPER_swap(a, c) ;
888
+ CLASSUPPER_free(c) ;
889
+ }
890
+ else
891
+ {
892
+ CLASSUPPER_mul_scalar(a, RUBY2FORTRAN(rb)) ;
893
+ }
894
+
895
+ return self ;
896
+ }
897
+
898
+ /*
899
+ * call-seq: premul!(a)
900
+ *
901
+ * In-place multiply
902
+ *
903
+ * c = a * b
904
+ *
905
+ * is equivalent to
906
+ *
907
+ * c = b.premul!(a)
908
+ *
909
+ * with
910
+ *
911
+ * b.object_id == c.object_id
912
+ *
913
+ * Note this implies +a+ must be square. +DimensionError+ is raised
914
+ * otherwise.
915
+ *
916
+ */
917
+ VALUE rb_CLASSLOWER_premul_inplace(VALUE self, VALUE ra)
918
+ {
919
+ CLASSUPPER* b ;
920
+ get_CLASSLOWER(b, self) ;
921
+
922
+ if( rb_obj_is_kind_of(ra, rb_cCLASSUPPER) )
923
+ {
924
+ CLASSUPPER* a ;
925
+ CLASSUPPER* c ;
926
+
927
+ get_CLASSLOWER(a, ra) ;
928
+
929
+ if( a->hsize != b->vsize ||
930
+ a->vsize != a->hsize )
931
+ {
932
+ raise_dim_error() ;
933
+ }
934
+
935
+ c = CLASSUPPER_new(a->vsize, b->hsize) ;
936
+ CLASSUPPER_mul(c, a, b) ;
937
+ CLASSUPPER_swap(b, c) ;
938
+ CLASSUPPER_free(c) ;
939
+ }
940
+ else
941
+ {
942
+ CLASSUPPER_mul_scalar(b, RUBY2FORTRAN(ra)) ;
943
+ }
944
+
945
+ return self ;
946
+ }
947
+
948
+ /*
949
+ * call-seq: dot(b)
950
+ *
951
+ * Column vector dot product
952
+ *
953
+ * a.dot(b)
954
+ *
955
+ * +DimensionError+ is raised unless
956
+ *
957
+ * a.hsize == b.hsize and
958
+ * b.hsize == 1 and
959
+ * a.vsize == b.vsize
960
+ *
961
+ */
962
+ VALUE rb_CLASSLOWER_dot(VALUE self, VALUE rb)
963
+ {
964
+ CLASSUPPER* a ;
965
+ CLASSUPPER* b ;
966
+
967
+ get_CLASSLOWER(a, self) ;
968
+ get_CLASSLOWER(b, rb) ;
969
+
970
+ if( a->hsize != 1 ||
971
+ b->hsize != 1 ||
972
+ a->vsize != b->vsize )
973
+ {
974
+ raise_dim_error() ;
975
+ }
976
+
977
+ return FORTRAN2RUBY(CLASSUPPER_dot(a, b)) ;
978
+ }
979
+
980
+ /*
981
+ * call-seq: plus!(b)
982
+ *
983
+ * In-place matrix addition.
984
+ *
985
+ * a.object_id == a.plus!(b).object_id
986
+ *
987
+ */
988
+ VALUE rb_CLASSLOWER_plus_inplace(VALUE self, VALUE rb)
989
+ {
990
+ CLASSUPPER* a ;
991
+ CLASSUPPER* b ;
992
+ get_CLASSLOWER(a, self) ;
993
+ get_CLASSLOWER(b, rb) ;
994
+
995
+ if( a->vsize != b->vsize ||
996
+ a->hsize != b->hsize)
997
+ {
998
+ raise_dim_error() ;
999
+ }
1000
+
1001
+ CLASSUPPER_plus(a, b) ;
1002
+ return self ;
1003
+ }
1004
+
1005
+ /*
1006
+ * call-seq: +(b)
1007
+ *
1008
+ * Matrix addition.
1009
+ *
1010
+ * a + b
1011
+ *
1012
+ * +DimensionError+ is raised unless
1013
+ *
1014
+ * a.dimensions == b.dimensions
1015
+ *
1016
+ */
1017
+ VALUE rb_CLASSLOWER_plus(VALUE self, VALUE ra)
1018
+ {
1019
+ return rb_CLASSLOWER_plus_inplace(rb_CLASSLOWER_clone(self),ra) ;
1020
+ }
1021
+
1022
+ /*
1023
+ * call-seq: minus!(b)
1024
+ *
1025
+ * In-place matrix subtraction.
1026
+ *
1027
+ * c = a - b
1028
+ *
1029
+ * is equivalent to
1030
+ *
1031
+ * c = a.minus!(b)
1032
+ *
1033
+ * with
1034
+ *
1035
+ * a.object_id == c.object_id
1036
+ *
1037
+ */
1038
+ VALUE rb_CLASSLOWER_minus_inplace(VALUE self, VALUE rb)
1039
+ {
1040
+ CLASSUPPER* a ;
1041
+ CLASSUPPER* b ;
1042
+ get_CLASSLOWER(a, self) ;
1043
+ get_CLASSLOWER(b, rb) ;
1044
+
1045
+ if( a->vsize != b->vsize ||
1046
+ a->hsize != b->hsize)
1047
+ {
1048
+ raise_dim_error() ;
1049
+ }
1050
+
1051
+ CLASSUPPER_minus(a, b) ;
1052
+ return self ;
1053
+ }
1054
+
1055
+ /*
1056
+ * call-seq: -(b)
1057
+ *
1058
+ * Matrix subtraction
1059
+ *
1060
+ * a - b
1061
+ *
1062
+ * +DimensionError+ is raised unless
1063
+ *
1064
+ * a.dimensions == b.dimensions
1065
+ *
1066
+ */
1067
+ VALUE rb_CLASSLOWER_minus(VALUE self, VALUE rb)
1068
+ {
1069
+ return rb_CLASSLOWER_minus_inplace(rb_CLASSLOWER_clone(self),rb) ;
1070
+ }
1071
+
1072
+ /*
1073
+ * call-seq: negate!
1074
+ *
1075
+ * In-place unary minus.
1076
+ *
1077
+ */
1078
+ VALUE rb_CLASSLOWER_unary_minus_inplace(VALUE self)
1079
+ {
1080
+ CLASSUPPER* a ;
1081
+ get_CLASSLOWER(a, self) ;
1082
+ CLASSUPPER_mul_scalar(a, CLASSLOWER_FORTRANTYPE_neg_1) ;
1083
+ return self ;
1084
+ }
1085
+
1086
+ /*
1087
+ * call-seq: -@
1088
+ *
1089
+ * Unary minus
1090
+ *
1091
+ */
1092
+ VALUE rb_CLASSLOWER_unary_minus(VALUE self)
1093
+ {
1094
+ return rb_CLASSLOWER_unary_minus_inplace(rb_CLASSLOWER_clone(self)) ;
1095
+ }
1096
+
1097
+ /*
1098
+ * call-seq: +@
1099
+ *
1100
+ * Unary plus. Does nothing.
1101
+ *
1102
+ */
1103
+ VALUE rb_CLASSLOWER_unary_plus(VALUE self)
1104
+ {
1105
+ return self ;
1106
+ }
1107
+
1108
+ /*
1109
+ * call-seq: to_a
1110
+ *
1111
+ * Create an array from the matrix
1112
+ *
1113
+ * a = m.to_a
1114
+ *
1115
+ * is equivalent to
1116
+ *
1117
+ * a = Array.new(m.vsize) { Array.new(m.hsize) }
1118
+ * m.each_index { |i,j|
1119
+ * a[i][j] = m[i,j]
1120
+ * }
1121
+ *
1122
+ */
1123
+ VALUE rb_CLASSLOWER_to_a(VALUE self)
1124
+ {
1125
+ int i ;
1126
+ int j ;
1127
+ VALUE arr ;
1128
+ VALUE row ;
1129
+ CLASSUPPER* a ;
1130
+ get_CLASSLOWER(a, self) ;
1131
+
1132
+ arr = rb_ary_new2(a->vsize) ;
1133
+
1134
+ for( i = 0 ; i != a->vsize ; ++i )
1135
+ {
1136
+ row = rb_ary_new2(a->hsize) ;
1137
+
1138
+ for( j = 0 ; j != a->hsize ; ++j )
1139
+ {
1140
+ rb_ary_store(row,
1141
+ j,
1142
+ FORTRAN2RUBY(a->data[i + j*a->vsize])) ;
1143
+ }
1144
+
1145
+ rb_ary_store(arr, i, row) ;
1146
+ }
1147
+
1148
+ return arr ;
1149
+ }
1150
+
1151
+ /*
1152
+ * call-seq: transpose
1153
+ *
1154
+ * Matrix transpose
1155
+ *
1156
+ */
1157
+ VALUE rb_CLASSLOWER_transpose(VALUE self)
1158
+ {
1159
+ CLASSUPPER* a ;
1160
+ CLASSUPPER* trans ;
1161
+ get_CLASSLOWER(a, self) ;
1162
+ trans = CLASSUPPER_new(a->hsize, a->vsize) ;
1163
+ CLASSUPPER_transpose(trans, a) ;
1164
+ return wrap_CLASSLOWER(trans) ;
1165
+ }
1166
+
1167
+ /*
1168
+ * call-seq: transpose!
1169
+ *
1170
+ * In-place matrix transpose. Guaranteed O(1) trivial cost for column
1171
+ * and row vectors. Note that transpose flags are not implemented;
1172
+ * thus for non-vectors the cost is a temporary copy and assignment.
1173
+ *
1174
+ */
1175
+ VALUE rb_CLASSLOWER_transpose_inplace( VALUE self )
1176
+ {
1177
+ CLASSUPPER* a ;
1178
+ get_CLASSLOWER(a, self) ;
1179
+ CLASSUPPER_transpose_inplace(a) ;
1180
+ return self ;
1181
+ }
1182
+
1183
+ static CLASSUPPER* CLASSLOWER_minor( CLASSUPPER* a,
1184
+ integer i,
1185
+ integer j,
1186
+ integer vsize,
1187
+ integer hsize )
1188
+ {
1189
+ CLASSUPPER* c ;
1190
+
1191
+ if( i < 0 || i + vsize - 1 >= a->vsize ||
1192
+ j < 0 || j + hsize - 1 >= a->hsize )
1193
+ {
1194
+ raise_index_error() ;
1195
+ }
1196
+
1197
+ c = CLASSUPPER_new(vsize, hsize) ;
1198
+ CLASSUPPER_minor(c, a, i, j, vsize, hsize) ;
1199
+ return c ;
1200
+ }
1201
+
1202
+ static void CLASSLOWER_replace_minor( CLASSUPPER* c,
1203
+ integer i,
1204
+ integer j,
1205
+ CLASSUPPER* a )
1206
+ {
1207
+ if( i < 0 || i + a->vsize - 1 >= c->vsize ||
1208
+ j < 0 || j + a->hsize - 1 >= c->hsize )
1209
+ {
1210
+ raise_index_error() ;
1211
+ }
1212
+
1213
+ CLASSUPPER_replace_minor(c, i, j, a) ;
1214
+ }
1215
+
1216
+ /*
1217
+ * call-seq: minor(i, j, vsize, hsize)
1218
+ *
1219
+ * Return the minor with upper-left position <tt>[i, j]</tt> and
1220
+ * dimensions <tt>[vsize, hsize]</tt>.
1221
+ *
1222
+ */
1223
+ VALUE rb_CLASSLOWER_minor( VALUE self,
1224
+ VALUE ri,
1225
+ VALUE rj,
1226
+ VALUE rvsize,
1227
+ VALUE rhsize )
1228
+ {
1229
+ CLASSUPPER* a ;
1230
+ integer i = (integer)NUM2INT(ri) ;
1231
+ integer j = (integer)NUM2INT(rj) ;
1232
+ integer vsize = (integer)num2size(rvsize) ;
1233
+ integer hsize = (integer)num2size(rhsize) ;
1234
+ get_CLASSLOWER(a, self) ;
1235
+ return wrap_CLASSLOWER(CLASSLOWER_minor(a, i, j, vsize, hsize)) ;
1236
+ }
1237
+
1238
+ /*
1239
+ * call-seq: replace_minor(i, j, minor)
1240
+ *
1241
+ * Insert +minor+ into the matrix, where [+i+,+j+] is the location of
1242
+ * the upper-left corner of the minor.
1243
+ *
1244
+ */
1245
+ VALUE rb_CLASSLOWER_replace_minor( VALUE self,
1246
+ VALUE ri,
1247
+ VALUE rj,
1248
+ VALUE rminor )
1249
+ {
1250
+ CLASSUPPER* c ;
1251
+ CLASSUPPER* a ;
1252
+ integer i = (integer)NUM2INT(ri) ;
1253
+ integer j = (integer)NUM2INT(rj) ;
1254
+
1255
+ get_CLASSLOWER(c, self) ;
1256
+ get_CLASSLOWER(a, rminor) ;
1257
+
1258
+ CLASSLOWER_replace_minor(c, i, j, a) ;
1259
+ return self ;
1260
+ }
1261
+
1262
+
1263
+ /*
1264
+ * call-seq: column(j)
1265
+ *
1266
+ * Returns the +j+-th column of the matrix.
1267
+ *
1268
+ */
1269
+ VALUE rb_CLASSLOWER_column( VALUE self, VALUE rj )
1270
+ {
1271
+ CLASSUPPER* c ;
1272
+ integer j = (integer)NUM2INT(rj) ;
1273
+ get_CLASSLOWER(c, self) ;
1274
+ return wrap_CLASSLOWER(CLASSLOWER_minor(c, 0, j, c->vsize, 1)) ;
1275
+ }
1276
+
1277
+ /*
1278
+ * call-seq: row(i)
1279
+ *
1280
+ * Returns the +i+-th row of the matrix.
1281
+ *
1282
+ */
1283
+ VALUE rb_CLASSLOWER_row( VALUE self, VALUE ri )
1284
+ {
1285
+ CLASSUPPER* a ;
1286
+ integer i = (integer)NUM2INT(ri) ;
1287
+ get_CLASSLOWER(a, self) ;
1288
+ return wrap_CLASSLOWER(CLASSLOWER_minor(a, i, 0, 1, a->hsize)) ;
1289
+ }
1290
+
1291
+ /*
1292
+ * call-seq: replace_column(j, v)
1293
+ *
1294
+ * replace the +j+-th column with the column vector +v+.
1295
+ *
1296
+ */
1297
+ VALUE rb_CLASSLOWER_replace_column( VALUE self, VALUE rj, VALUE rv )
1298
+ {
1299
+ CLASSUPPER* a ;
1300
+ integer j = (integer)NUM2INT(rj) ;
1301
+ CLASSUPPER* v ;
1302
+
1303
+ get_CLASSLOWER(a, self) ;
1304
+ get_CLASSLOWER(v, rv) ;
1305
+
1306
+ if( v->hsize != 1 ||
1307
+ v->vsize != a->vsize )
1308
+ {
1309
+ raise_dim_error() ;
1310
+ }
1311
+
1312
+ CLASSLOWER_replace_minor(a, 0, j, v) ;
1313
+ return self ;
1314
+ }
1315
+
1316
+ /*
1317
+ * call-seq: replace_row(i, v)
1318
+ *
1319
+ * replace the +i+-th row with the row vector +v+.
1320
+ *
1321
+ */
1322
+ VALUE rb_CLASSLOWER_replace_row( VALUE self, VALUE ri, VALUE rv )
1323
+ {
1324
+ CLASSUPPER* a ;
1325
+ integer i = (integer)NUM2INT(ri) ;
1326
+ CLASSUPPER* v ;
1327
+
1328
+ get_CLASSLOWER(a, self) ;
1329
+ get_CLASSLOWER(v, rv) ;
1330
+
1331
+ if( v->vsize != 1 ||
1332
+ v->hsize != a->hsize )
1333
+ {
1334
+ raise_dim_error() ;
1335
+ }
1336
+
1337
+ CLASSLOWER_replace_minor(a, i, 0, v) ;
1338
+ return self ;
1339
+ }
1340
+
1341
+ /*
1342
+ * call-seq: to_FORTRANTYPE_ptr
1343
+ *
1344
+ * Actual pointer value of the matrix data. Subject to change after a
1345
+ * bang (!) operation. This is called by the +Lapack+ module.
1346
+ *
1347
+ */
1348
+ VALUE rb_CLASSLOWER_to_FORTRANTYPE_ptr(VALUE self)
1349
+ {
1350
+ CLASSUPPER* a ;
1351
+ get_CLASSLOWER(a, self) ;
1352
+ return LONG2NUM((long)a->data) ;
1353
+ }
1354
+
1355
+ /*
1356
+ * call-seq: coerce(other)
1357
+ *
1358
+ * Internal call from Numeric#coerce.
1359
+ *
1360
+ */
1361
+ VALUE rb_CLASSLOWER_coerce(VALUE self, VALUE other)
1362
+ {
1363
+ return rb_assoc_new(self, other) ;
1364
+ }
1365
+
1366
+ /*
1367
+ * call-seq:
1368
+ * symmetric!
1369
+ *
1370
+ * Force the matrix to be symmetric, reflecting the upper triangle
1371
+ * onto the lower triangle.
1372
+ *
1373
+ */
1374
+ VALUE rb_CLASSLOWER_make_symmetric( VALUE self )
1375
+ {
1376
+ CLASSUPPER* a ;
1377
+ get_CLASSLOWER(a, self) ;
1378
+
1379
+ if( a->vsize != a->hsize )
1380
+ {
1381
+ raise_dim_error() ;
1382
+ }
1383
+
1384
+ {
1385
+ int i ;
1386
+ int j ;
1387
+
1388
+ for( j = 0 ; j < a->hsize ; ++j )
1389
+ {
1390
+ for( i = j + 1 ; i < a->vsize ; ++i )
1391
+ {
1392
+ a->data[i + j*a->vsize] = a->data[j + i*a->vsize] ;
1393
+ }
1394
+ }
1395
+ }
1396
+
1397
+ return self ;
1398
+ }
1399
+
1400
+ /*
1401
+ * call-seq: _dump
1402
+ *
1403
+ * For Marshal. Uses native data format.
1404
+ *
1405
+ */
1406
+ VALUE rb_CLASSLOWER_marshal_dump(VALUE self, VALUE depth)
1407
+ {
1408
+ /*
1409
+ * format:
1410
+ * sizeof(integer) vsize
1411
+ * sizeof(integer) hsize
1412
+ * 40*sizeof(char) reserved
1413
+ * vsize*hsize*sizeof(FORTRANTYPE) data
1414
+ */
1415
+
1416
+ CLASSUPPER* a ;
1417
+ VALUE str ;
1418
+ char reserved[40] = { 0 } ;
1419
+
1420
+ get_CLASSLOWER(a, self) ;
1421
+
1422
+ str = rb_str_buf_new(1*sizeof(integer) +
1423
+ 1*sizeof(integer) +
1424
+ 40*sizeof(char) +
1425
+ a->vsize*a->hsize*sizeof(FORTRANTYPE)) ;
1426
+
1427
+ rb_str_buf_cat(str, (const char*)(&a->vsize), 1*sizeof(integer)) ;
1428
+ rb_str_buf_cat(str, (const char*)(&a->hsize), 1*sizeof(integer)) ;
1429
+ rb_str_buf_cat(str, (const char*)(reserved), 40*sizeof(char)) ;
1430
+ rb_str_buf_cat(str, (const char*)(a->data),
1431
+ a->vsize*a->hsize*sizeof(FORTRANTYPE)) ;
1432
+ return str ;
1433
+ }
1434
+
1435
+ /*
1436
+ * call-seq: _load
1437
+ *
1438
+ * For Marshal. Uses native data format.
1439
+ *
1440
+ */
1441
+ VALUE rb_CLASSLOWER_s_marshal_load(VALUE klass, VALUE str)
1442
+ {
1443
+ CLASSUPPER* a ;
1444
+ integer vsize ;
1445
+ integer hsize ;
1446
+ char* p = RSTRING_PTR(str) ;
1447
+
1448
+ vsize = *((integer*)p) ;
1449
+ p += sizeof(integer) ;
1450
+
1451
+ hsize = *((integer*)p) ;
1452
+ p += sizeof(integer) ;
1453
+
1454
+ p += 40*sizeof(char) ;
1455
+
1456
+ a = CLASSUPPER_new(vsize, hsize) ;
1457
+ memcpy((void*)a->data, (void*)p, vsize*hsize*sizeof(FORTRANTYPE)) ;
1458
+
1459
+ return wrap_CLASSLOWER(a) ;
1460
+ }
1461
+
1462
+ #if 0
1463
+ /*
1464
+ * call-seq: within(epsilon, other)
1465
+ *
1466
+ * Test if each matrix element is within +epsilon+ of the respective
1467
+ * matrix element of +other+.
1468
+ *
1469
+ */
1470
+ VALUE rb_CLASSLOWER_within( VALUE self, VALUE repsilon, VALUE other )
1471
+ {
1472
+ /* rdoc can't find this function */
1473
+ }
1474
+ #endif
1475
+
1476
+ #if 0
1477
+ /*
1478
+ * call-seq: within(epsilon, other)
1479
+ *
1480
+ * Test if each matrix element is within +epsilon+ of the respective
1481
+ * matrix element of +other+.
1482
+ *
1483
+ */
1484
+ VALUE rb_CLASSLOWER_within( VALUE self, VALUE repsilon, VALUE other )
1485
+ {
1486
+ /* rdoc can't find this function */
1487
+ }
1488
+ #endif
1489
+
1490
+ #if 0
1491
+ /*
1492
+ * call-seq: /(s)
1493
+ *
1494
+ * Division by scalar +s+.
1495
+ *
1496
+ */
1497
+ VALUE rb_CLASSLOWER_div(VALUE self, VALUE rs)
1498
+ {
1499
+ /* rdoc can't find this function */
1500
+ }
1501
+ #endif
1502
+
1503
+ #if 0
1504
+ /*
1505
+ *
1506
+ */
1507
+ VALUE rb_CLASSLOWER_symmetric_private( VALUE self, VALUE repsilon )
1508
+ {
1509
+ }
1510
+ #endif
1511
+
1512
+ void Init_CLASSLOWER()
1513
+ {
1514
+ /* Linalg */
1515
+ rb_cLinalg = rb_define_module("Linalg") ;
1516
+
1517
+ /* Linalg::Exception */
1518
+ rb_cLinalgException = rb_define_module_under(rb_cLinalg, "Exception") ;
1519
+
1520
+ /* DimensionError */
1521
+ rb_eDimensionError =
1522
+ rb_define_class_under(rb_cLinalgException,
1523
+ "DimensionError",
1524
+ rb_eRuntimeError) ;
1525
+
1526
+ /* CLASSUPPER */
1527
+ rb_cCLASSUPPER =
1528
+ rb_define_class_under(rb_cLinalg,
1529
+ "CLASSUPPER",
1530
+ rb_cObject) ;
1531
+
1532
+ /* allocate */
1533
+ rb_define_alloc_func(rb_cCLASSUPPER, rb_CLASSLOWER_allocate) ;
1534
+
1535
+ /* singleton methods */
1536
+ rb_define_singleton_method(rb_cCLASSUPPER, "rows",
1537
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_s_rows), 1) ;
1538
+ rb_define_singleton_method(rb_cCLASSUPPER, "identity",
1539
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_s_identity), 1) ;
1540
+ rb_define_singleton_method(rb_cCLASSUPPER, "diagonal",
1541
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_s_diagonal), -1) ;
1542
+ rb_define_singleton_method(rb_cCLASSUPPER, "rand",
1543
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_s_rand), 2) ;
1544
+ rb_define_singleton_method(rb_cCLASSUPPER, "reserve",
1545
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_reserve), 2) ;
1546
+ rb_define_singleton_method(rb_cCLASSUPPER, "_load",
1547
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_s_marshal_load), 1) ;
1548
+
1549
+ /* instance methods */
1550
+ rb_define_method(rb_cCLASSUPPER, "initialize",
1551
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_initialize), -1) ;
1552
+ rb_define_method(rb_cCLASSUPPER, "vsize",
1553
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_vsize), 0) ;
1554
+ rb_define_method(rb_cCLASSUPPER, "hsize",
1555
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_hsize), 0) ;
1556
+ rb_define_method(rb_cCLASSUPPER, "dimensions",
1557
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_dimensions), 0) ;
1558
+ rb_define_method(rb_cCLASSUPPER, "[]",
1559
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_bracket_get), -1) ;
1560
+ rb_define_method(rb_cCLASSUPPER, "[]=",
1561
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_bracket_set), -1) ;
1562
+
1563
+ rb_define_method(rb_cCLASSUPPER, "to_a",
1564
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_to_a), 0) ;
1565
+ rb_define_method(rb_cCLASSUPPER, "_dump",
1566
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_marshal_dump), 1) ;
1567
+ rb_define_method(rb_cCLASSUPPER, "clone",
1568
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_clone), 0) ;
1569
+ rb_define_method(rb_cCLASSUPPER, "to_FORTRANTYPE_ptr",
1570
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_to_FORTRANTYPE_ptr), 0) ;
1571
+ rb_define_method(rb_cCLASSUPPER, "coerce",
1572
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_coerce), 1) ;
1573
+
1574
+ rb_define_method(rb_cCLASSUPPER, "+",
1575
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_plus), 1) ;
1576
+ rb_define_method(rb_cCLASSUPPER, "plus!",
1577
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_plus_inplace), 1) ;
1578
+ rb_define_method(rb_cCLASSUPPER, "+@",
1579
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_unary_plus), 0) ;
1580
+
1581
+ rb_define_method(rb_cCLASSUPPER, "-",
1582
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_minus), 1) ;
1583
+ rb_define_method(rb_cCLASSUPPER, "minus!",
1584
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_minus_inplace), 1) ;
1585
+ rb_define_method(rb_cCLASSUPPER, "-@",
1586
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_unary_minus), 0) ;
1587
+ rb_define_method(rb_cCLASSUPPER, "negate!",
1588
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_unary_minus_inplace), 0) ;
1589
+
1590
+ rb_define_method(rb_cCLASSUPPER, "*",
1591
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_mul), 1) ;
1592
+ rb_define_method(rb_cCLASSUPPER, "postmul!",
1593
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_postmul_inplace), 1) ;
1594
+ rb_define_method(rb_cCLASSUPPER, "premul!",
1595
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_premul_inplace), 1) ;
1596
+
1597
+ rb_define_method(rb_cCLASSUPPER, "/",
1598
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_div), 1) ;
1599
+
1600
+ rb_define_method(rb_cCLASSUPPER, "dot",
1601
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_dot), 1) ;
1602
+ rb_define_method(rb_cCLASSUPPER, "transpose",
1603
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_transpose), 0) ;
1604
+ rb_define_method(rb_cCLASSUPPER, "transpose!",
1605
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_transpose_inplace), 0) ;
1606
+
1607
+ rb_define_method(rb_cCLASSUPPER, "within",
1608
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_within), 2) ;
1609
+
1610
+ rb_define_method(rb_cCLASSUPPER, "column",
1611
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_column), 1) ;
1612
+ rb_define_method(rb_cCLASSUPPER, "row",
1613
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_row), 1) ;
1614
+ rb_define_method(rb_cCLASSUPPER, "replace_column",
1615
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_replace_column), 2) ;
1616
+ rb_define_method(rb_cCLASSUPPER, "replace_row",
1617
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_replace_row), 2) ;
1618
+ rb_define_method(rb_cCLASSUPPER, "minor",
1619
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_minor), 4) ;
1620
+ rb_define_method(rb_cCLASSUPPER, "replace_minor",
1621
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_replace_minor), 3) ;
1622
+ rb_define_method(rb_cCLASSUPPER, "fill",
1623
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_fill), 1) ;
1624
+
1625
+ rb_define_method(rb_cCLASSUPPER, "symmetric!",
1626
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_make_symmetric), 0) ;
1627
+ rb_define_private_method(rb_cCLASSUPPER, "symmetric_private",
1628
+ RUBY_METHOD_FUNC(rb_CLASSLOWER_symmetric_private), 1) ;
1629
+ }
1630
+