nmatrix 0.0.1
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.
- data/.autotest +23 -0
- data/.gemtest +0 -0
- data/Gemfile +7 -0
- data/History.txt +6 -0
- data/LICENSE.txt +21 -0
- data/Manifest.txt +51 -0
- data/README.rdoc +63 -0
- data/Rakefile +154 -0
- data/ext/nmatrix/cblas.c +150 -0
- data/ext/nmatrix/dense.c +307 -0
- data/ext/nmatrix/dense/blas_header.template.c +52 -0
- data/ext/nmatrix/dense/elementwise.template.c +107 -0
- data/ext/nmatrix/dense/gemm.template.c +159 -0
- data/ext/nmatrix/dense/gemv.template.c +130 -0
- data/ext/nmatrix/dense/rationalmath.template.c +68 -0
- data/ext/nmatrix/depend +18 -0
- data/ext/nmatrix/extconf.rb +143 -0
- data/ext/nmatrix/generator.rb +594 -0
- data/ext/nmatrix/generator/syntax_tree.rb +481 -0
- data/ext/nmatrix/list.c +774 -0
- data/ext/nmatrix/nmatrix.c +1977 -0
- data/ext/nmatrix/nmatrix.h +912 -0
- data/ext/nmatrix/rational.c +98 -0
- data/ext/nmatrix/yale.c +726 -0
- data/ext/nmatrix/yale/complexmath.template.c +71 -0
- data/ext/nmatrix/yale/elementwise.template.c +46 -0
- data/ext/nmatrix/yale/elementwise_op.template.c +73 -0
- data/ext/nmatrix/yale/numbmm.template.c +94 -0
- data/ext/nmatrix/yale/smmp1.template.c +21 -0
- data/ext/nmatrix/yale/smmp1_header.template.c +38 -0
- data/ext/nmatrix/yale/smmp2.template.c +43 -0
- data/ext/nmatrix/yale/smmp2_header.template.c +46 -0
- data/ext/nmatrix/yale/sort_columns.template.c +56 -0
- data/ext/nmatrix/yale/symbmm.template.c +54 -0
- data/ext/nmatrix/yale/transp.template.c +68 -0
- data/lib/array.rb +67 -0
- data/lib/nmatrix.rb +263 -0
- data/lib/string.rb +65 -0
- data/spec/nmatrix_spec.rb +395 -0
- data/spec/nmatrix_yale_spec.rb +239 -0
- data/spec/nvector_spec.rb +43 -0
- data/spec/syntax_tree_spec.rb +46 -0
- metadata +150 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
inline static %%TYPE%% BOOL2%%= dtype.id.to_s.upcase%%(bool expr) {
|
3
|
+
%%TYPE%% result;
|
4
|
+
result.r = expr;
|
5
|
+
result.i = 0;
|
6
|
+
return result;
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_mul(double ar, double ai, double br, double bi) {
|
12
|
+
%%TYPE%% result;
|
13
|
+
|
14
|
+
result.r = ar * br - ai * bi;
|
15
|
+
result.i = ar * bi + br * ai;
|
16
|
+
|
17
|
+
return result;
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_div(double ar, double ai, double br, double bi) {
|
22
|
+
%%TYPE%% result;
|
23
|
+
double denom = br * br + bi * bi;
|
24
|
+
|
25
|
+
result.r = (ar * br + ai * bi) / denom;
|
26
|
+
result.i = (ai * br - ar * bi) / denom;
|
27
|
+
|
28
|
+
return result;
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_add(%%= dtype.sym == :complex128 ? "double ar, double ai, double br, double bi" : "float ar, float ai, float br, float bi"%%) {
|
33
|
+
%%TYPE%% result;
|
34
|
+
|
35
|
+
result.r = ar + br;
|
36
|
+
result.i = ai + bi;
|
37
|
+
|
38
|
+
return result;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_sub(%%= dtype.sym == :complex128 ? "double ar, double ai, double br, double bi" : "float ar, float ai, float br, float bi"%%) {
|
43
|
+
%%TYPE%% result;
|
44
|
+
|
45
|
+
result.r = ar - br;
|
46
|
+
result.i = ai - bi;
|
47
|
+
|
48
|
+
return result;
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_mod(%%= dtype.sym == :complex128 ? "double ar, double ai, double br, double bi" : "float ar, float ai, float br, float bi"%%) {
|
53
|
+
%%TYPE%% result;
|
54
|
+
rb_raise(rb_eNotImpError, "modulo arithmetic for complex numbers not yet implemented");
|
55
|
+
|
56
|
+
return result;
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_bang(%%= dtype.sym == :complex128 ? "double ar, double ai" : "float ar, float ai"%%) {
|
61
|
+
%%TYPE%% result = {!ar, 0};
|
62
|
+
return result;
|
63
|
+
}
|
64
|
+
|
65
|
+
inline static %%TYPE%% %%TYPE_ABBREV%%_negate(%%= dtype.sym == :complex128 ? "double ar, double ai" : "float ar, float ai"%%) {
|
66
|
+
%%TYPE%% result;
|
67
|
+
result.r = -ar;
|
68
|
+
result.i = -ai;
|
69
|
+
return result;
|
70
|
+
}
|
71
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
int %%INT_ABBREV%%_%%TYPE_ABBREV%%_ew(y_size_t n, y_size_t m, enum NMatrix_Ops op, const u_%%INT%%* ija, const u_%%INT%%* ijb, const u_%%INT%%* ijc, %%TYPE%%* a, %%TYPE%%* b, %%TYPE%%* c)
|
3
|
+
{
|
4
|
+
y_size_t i;
|
5
|
+
y_size_t c_jj, a_jj, b_jj;
|
6
|
+
%%TYPE%% left, right;
|
7
|
+
|
8
|
+
for (i = 0; i < n; ++i) {
|
9
|
+
// do operation on diagonals first:
|
10
|
+
if (i < m) {
|
11
|
+
if (b) %%TYPE_ABBREV%%_ew_op_binary(op, &(c[i]), a[i], b[i]);
|
12
|
+
else %%TYPE_ABBREV%%_ew_op_unary(op, &(c[i]), a[i]);
|
13
|
+
}
|
14
|
+
|
15
|
+
c_jj = ijc[i];
|
16
|
+
a_jj = ija[i];
|
17
|
+
if (ijb) b_jj = ijb[i];
|
18
|
+
|
19
|
+
//fprintf(stderr, "i16_f64_ew: n=%d, i=%d, c_jj=%d\n", (int)(n), (int)(i), (int)(c_jj));
|
20
|
+
while (c_jj < ijc[i+1]) {
|
21
|
+
// one or the other has to be the correct column (j = ijc[c_jj] ==? ija[a_jj])
|
22
|
+
if (a_jj < ija[i+1] && ija[a_jj] == ijc[c_jj]) {
|
23
|
+
%%TYPE left = a[a_jj]%%
|
24
|
+
++a_jj;
|
25
|
+
} else {
|
26
|
+
%%TYPE left = 0%%
|
27
|
+
}
|
28
|
+
|
29
|
+
if (b) { // some ops don't have a second vector
|
30
|
+
if (b_jj < ijb[i+1] && ijb[b_jj] == ijc[c_jj]) {
|
31
|
+
%%TYPE right = b[b_jj]%%
|
32
|
+
++b_jj;
|
33
|
+
} else {
|
34
|
+
%%TYPE right = 0%%
|
35
|
+
}
|
36
|
+
|
37
|
+
%%TYPE_ABBREV%%_ew_op_binary(op, &(c[c_jj]), left, right);
|
38
|
+
} else {
|
39
|
+
%%TYPE_ABBREV%%_ew_op_unary(op, &(c[c_jj]), left);
|
40
|
+
}
|
41
|
+
|
42
|
+
++c_jj;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
return 0;
|
46
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
static inline void %%TYPE_ABBREV%%_ew_op_unary(enum NMatrix_Ops op, %%TYPE%%* result, %%TYPE%% left) {
|
3
|
+
switch(op) {
|
4
|
+
case '!':
|
5
|
+
%%TYPE *result = !left%%
|
6
|
+
break;
|
7
|
+
case NM_OP_NEG:
|
8
|
+
%%TYPE *result = -left%%
|
9
|
+
break;
|
10
|
+
case '~':
|
11
|
+
%%TYPE *result = ~left%%
|
12
|
+
break;
|
13
|
+
default:
|
14
|
+
rb_raise(rb_eNotImpError, "Unrecognized element-wise unary operator");
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
static inline void %%TYPE_ABBREV%%_ew_op_binary(enum NMatrix_Ops op, %%TYPE%%* result, %%TYPE%% left, %%TYPE%% right) {
|
21
|
+
switch(op) {
|
22
|
+
case '+':
|
23
|
+
%%TYPE *result = left + right%%
|
24
|
+
break;
|
25
|
+
case '-':
|
26
|
+
%%TYPE *result = left - right%%
|
27
|
+
break;
|
28
|
+
case '*':
|
29
|
+
%%TYPE *result = left * right%%
|
30
|
+
break;
|
31
|
+
case '/':
|
32
|
+
%%TYPE *result = left / right%%
|
33
|
+
break;
|
34
|
+
case '%':
|
35
|
+
%%TYPE *result = left % right%%
|
36
|
+
break;
|
37
|
+
case NM_OP_EQEQ:
|
38
|
+
%%TYPE *result = left == right%%
|
39
|
+
break;
|
40
|
+
case NM_OP_NEQ:
|
41
|
+
%%TYPE *result = left != right%%
|
42
|
+
break;
|
43
|
+
case '>':
|
44
|
+
%%TYPE *result = left > right%%
|
45
|
+
break;
|
46
|
+
case '<':
|
47
|
+
%%TYPE *result = left < right%%
|
48
|
+
break;
|
49
|
+
case NM_OP_GTE:
|
50
|
+
%%TYPE *result = left >= right%%
|
51
|
+
break;
|
52
|
+
case NM_OP_LTE:
|
53
|
+
%%TYPE *result = left <= right%%
|
54
|
+
break;
|
55
|
+
case '&':
|
56
|
+
%%TYPE *result = left & right%%
|
57
|
+
break;
|
58
|
+
case '|':
|
59
|
+
%%TYPE *result = left | right%%
|
60
|
+
break;
|
61
|
+
case '^':
|
62
|
+
%%TYPE *result = left ^ right%%
|
63
|
+
break;
|
64
|
+
case NM_OP_LSH:
|
65
|
+
%%TYPE *result = left << right%%
|
66
|
+
break;
|
67
|
+
case NM_OP_RSH:
|
68
|
+
%%TYPE *result = left >> right%%
|
69
|
+
break;
|
70
|
+
default:
|
71
|
+
rb_raise(rb_eNotImpError, "Unrecognized element-wise binary operator");
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
// numeric matrix multiply c=a*b
|
2
|
+
void %%INT_ABBREV%%_%%TYPE_ABBREV%%_numbmm_(y_size_t n, y_size_t m, YALE_PARAM A, YALE_PARAM B, YALE_PARAM C)
|
3
|
+
{
|
4
|
+
u_%%INT%% next[m];
|
5
|
+
%%TYPE%% sums[m];
|
6
|
+
|
7
|
+
%%TYPE%% v;
|
8
|
+
%%= if [:rational,:complex,:value].include?(dtype.type); "#{dtype.long_dtype.sizeof} temp1;"; end%%
|
9
|
+
|
10
|
+
u_%%INT%% head, length, temp, ndnz = 0;
|
11
|
+
u_%%INT%% jj_start, jj_end, kk_start, kk_end;
|
12
|
+
u_%%INT%% i, j, k, kk, jj;
|
13
|
+
u_%%INT%% minmn = SMMP_MIN(m,n);
|
14
|
+
|
15
|
+
u_%%INT%% *ia = (u_%%INT%%*)(A.ia),
|
16
|
+
*ja = (u_%%INT%%*)(A.ja),
|
17
|
+
*ib = (u_%%INT%%*)(B.ia),
|
18
|
+
*jb = (u_%%INT%%*)(B.ja),
|
19
|
+
*ic = (u_%%INT%%*)(C.ia),
|
20
|
+
*jc = (u_%%INT%%*)(C.ja);
|
21
|
+
%%TYPE%% *a = A.a,
|
22
|
+
*b = B.a,
|
23
|
+
*c = C.a;
|
24
|
+
|
25
|
+
for (i = 0; i < m; ++i) { // initialize scratch arrays
|
26
|
+
next[i] = U%%INT_MAX%%;
|
27
|
+
%%TYPE sums[i] = 0%%
|
28
|
+
}
|
29
|
+
|
30
|
+
for (i = 0; i < n; ++i) { // walk down the rows
|
31
|
+
head = U%%INT_MAX%%-1; // head gets assigned as whichever column of B's row j we last visited
|
32
|
+
length = 0;
|
33
|
+
|
34
|
+
jj_start = ia[i];
|
35
|
+
jj_end = ia[i+1];
|
36
|
+
|
37
|
+
for (jj = jj_start; jj <= jj_end; ++jj) { // walk through entries in each row
|
38
|
+
|
39
|
+
if (jj == jj_end) { // if we're in the last entry for this row:
|
40
|
+
if (!A.diag || i >= minmn) continue;
|
41
|
+
j = i; // if it's a new Yale matrix, and last entry, get the diagonal position (j) and entry (ajj)
|
42
|
+
%%TYPE v = a[i]%%
|
43
|
+
} else {
|
44
|
+
j = ja[jj]; // if it's not the last entry for this row, get the column (j) and entry (ajj)
|
45
|
+
%%TYPE v = a[jj]%%
|
46
|
+
}
|
47
|
+
|
48
|
+
kk_start = ib[j]; // Find the first entry of row j of matrix B
|
49
|
+
kk_end = ib[j+1];
|
50
|
+
for (kk = kk_start; kk <= kk_end; ++kk) {
|
51
|
+
|
52
|
+
if (kk == kk_end) { // Get the column id for that entry
|
53
|
+
if (!B.diag || j >= minmn) continue;
|
54
|
+
k = j;
|
55
|
+
%%TYPE sums[k] += v*b[k]%%
|
56
|
+
} else {
|
57
|
+
k = jb[kk];
|
58
|
+
%%TYPE sums[k] += v*b[kk]%%
|
59
|
+
}
|
60
|
+
|
61
|
+
if (next[k] == U%%INT_MAX%%) {
|
62
|
+
next[k] = head;
|
63
|
+
head = k;
|
64
|
+
++length;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
for (jj = 0; jj < length; ++jj) {
|
70
|
+
if (%%TYPE sums[head] != 0%%) {
|
71
|
+
if (C.diag && head == i) {
|
72
|
+
%%TYPE c[head] = sums[head]%%
|
73
|
+
} else {
|
74
|
+
jc[n+1+ndnz] = head;
|
75
|
+
%%TYPE c[n+1+ndnz] = sums[head]%%
|
76
|
+
++ndnz;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
temp = head;
|
81
|
+
head = next[head];
|
82
|
+
|
83
|
+
next[temp] = U%%INT_MAX%%;
|
84
|
+
%%TYPE sums[temp] = 0%%
|
85
|
+
}
|
86
|
+
|
87
|
+
ic[i+1] = n+1+ndnz;
|
88
|
+
}
|
89
|
+
} /* numbmm_ */
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
void %%TYPE_ABBREV%%_symbmm(y_size_t n, y_size_t m, YALE_PARAM A, YALE_PARAM B, YALE_PARAM C)
|
3
|
+
{
|
4
|
+
if (A.diag && A.ia != A.ja) {
|
5
|
+
fprintf(stderr, "A.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
6
|
+
return;
|
7
|
+
}
|
8
|
+
|
9
|
+
if (B.diag && B.ia != B.ja) {
|
10
|
+
fprintf(stderr, "B.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
11
|
+
return;
|
12
|
+
}
|
13
|
+
|
14
|
+
if (C.diag && C.ia != C.ja) {
|
15
|
+
fprintf(stderr, "C.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
%%TYPE_ABBREV%%_symbmm_(n, m, A, B, C);
|
21
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012, Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == smmp1.c
|
25
|
+
//
|
26
|
+
// smmp1.c is automatically generated by generator.rb. Do not modify
|
27
|
+
// it directly!
|
28
|
+
//
|
29
|
+
// This file ensures that all SMMP functions have the same signature,
|
30
|
+
// so we can call them using arrays of function pointers.
|
31
|
+
|
32
|
+
#include "nmatrix.h"
|
33
|
+
|
34
|
+
#include <stdlib.h>
|
35
|
+
#include <stdio.h>
|
36
|
+
|
37
|
+
|
38
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
void %%INT_ABBREV%%_%%TYPE_ABBREV%%_numbmm(y_size_t n, y_size_t m, YALE_PARAM A, YALE_PARAM B, YALE_PARAM C)
|
3
|
+
{
|
4
|
+
if (A.diag && A.ia != A.ja) {
|
5
|
+
fprintf(stderr, "A.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
6
|
+
return;
|
7
|
+
}
|
8
|
+
|
9
|
+
if (B.diag && B.ia != B.ja) {
|
10
|
+
fprintf(stderr, "B.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
11
|
+
return;
|
12
|
+
}
|
13
|
+
|
14
|
+
if (C.diag && C.ia != C.ja) {
|
15
|
+
fprintf(stderr, "C.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
|
19
|
+
%%INT_ABBREV%%_%%TYPE_ABBREV%%_numbmm_(n, m, A, B, C);
|
20
|
+
}
|
21
|
+
|
22
|
+
// Perform both the symbolic and numeric steps together.
|
23
|
+
void %%INT_ABBREV%%_%%TYPE_ABBREV%%_smmp(y_size_t n, y_size_t m, YALE_PARAM A, YALE_PARAM B, YALE_PARAM C)
|
24
|
+
{
|
25
|
+
if (A.diag && A.ia != A.ja) {
|
26
|
+
fprintf(stderr, "A.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
|
30
|
+
if (B.diag && B.ia != B.ja) {
|
31
|
+
fprintf(stderr, "B.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
if (C.diag && C.ia != C.ja) {
|
36
|
+
fprintf(stderr, "C.diag=true, but ia!=ja. For new yale, ia must equal ja.");
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
|
40
|
+
%%INT_ABBREV%%_symbmm_(n, m, A, B, C);
|
41
|
+
%%INT_ABBREV%%_%%TYPE_ABBREV%%_numbmm_(n, m, A, B, C);
|
42
|
+
%%INT_ABBREV%%_%%TYPE_ABBREV%%_smmp_sort_columns_(n, C);
|
43
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012, Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == smmp2.c
|
25
|
+
//
|
26
|
+
/* ======================================================================= *
|
27
|
+
* Sparse Matrix Multiplication Package *
|
28
|
+
* Randolph E. Bank and Craig C. Douglas *
|
29
|
+
* na.bank@na-net.ornl.gov and na.cdouglas@na-net.ornl.gov *
|
30
|
+
* ======================================================================= */
|
31
|
+
// This was originally derived from the above paper, but the algorithm they
|
32
|
+
// give, in Fortran, uses 1-based indexing, and I simply could not make it
|
33
|
+
// work. So I went back to where I found the link to that paper -- SciPy's
|
34
|
+
// CSR type -- and looked at what they had done:
|
35
|
+
//
|
36
|
+
// https://github.com/scipy/scipy/blob/master/scipy/sparse/sparsetools/csr.h
|
37
|
+
//
|
38
|
+
// However, the SciPy version does not use the "new Yale" format, but rather
|
39
|
+
// "old Yale." Thus, some modification was necessary -- reincorporating some
|
40
|
+
// stuff from the original Bank & Douglas paper.
|
41
|
+
//
|
42
|
+
//
|
43
|
+
// DO NOT MODIFY smmp2.c DIRECTLY, as it is autogenerated by generator.rb.
|
44
|
+
|
45
|
+
#include <stdio.h>
|
46
|
+
#include "nmatrix.h"
|
@@ -0,0 +1,56 @@
|
|
1
|
+
//TODO: More efficient sorting algorithm than selection sort would be nice, probably.
|
2
|
+
// Remember, we're dealing with unique keys, which simplifies things.
|
3
|
+
// Doesn't have to be in-place, since we probably just multiplied and that wasn't in-place.
|
4
|
+
|
5
|
+
void %%INT_ABBREV%%_%%TYPE_ABBREV%%_smmp_sort_columns_(y_size_t n, YALE_PARAM A)
|
6
|
+
{
|
7
|
+
u_%%INT%% i, jj, jj_start, jj_end, min, min_jj;
|
8
|
+
%%TYPE%% temp_val;
|
9
|
+
|
10
|
+
u_%%INT%% *ia = (u_%%INT%%*)(A.ia),
|
11
|
+
*ja = (u_%%INT%%*)(A.ja);
|
12
|
+
%%TYPE%% *a = (%%TYPE%%*)(A.a);
|
13
|
+
|
14
|
+
for (i = 0; i < n; ++i) {
|
15
|
+
// No need to sort if there are 0 or 1 entries in the row
|
16
|
+
if (ia[i+1] - ia[i] < 2) continue;
|
17
|
+
|
18
|
+
jj_end = ia[i+1];
|
19
|
+
for (jj_start = ia[i]; jj_start < jj_end; ++jj_start) {
|
20
|
+
|
21
|
+
// If the previous min is just current-1, this key/value pair is already in sorted order.
|
22
|
+
// This follows from the unique condition on our column keys.
|
23
|
+
if (jj_start > ia[i] && min+1 == ja[jj_start]) {
|
24
|
+
min = ja[jj_start];
|
25
|
+
continue;
|
26
|
+
}
|
27
|
+
|
28
|
+
// find the minimum key (column index) between jj_start and jj_end
|
29
|
+
min = ja[jj_start];
|
30
|
+
min_jj = jj_start;
|
31
|
+
for (jj = jj_start+1; jj < jj_end; ++jj) {
|
32
|
+
if (ja[jj] < min) {
|
33
|
+
min_jj = jj;
|
34
|
+
min = ja[jj];
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
// if min is already first, skip this iteration
|
39
|
+
if (min_jj == jj_start) continue;
|
40
|
+
|
41
|
+
for (jj = jj_start; jj < jj_end; ++jj) {
|
42
|
+
// swap minimum key/value pair with key/value pair in the first position.
|
43
|
+
if (min_jj != jj) {
|
44
|
+
// min already = ja[min_jj], so use this as temp_key
|
45
|
+
%%TYPE temp_val = a[min_jj]%%
|
46
|
+
|
47
|
+
ja[min_jj] = ja[jj];
|
48
|
+
%%TYPE a[min_jj] = a[jj]%%
|
49
|
+
|
50
|
+
ja[jj] = min;
|
51
|
+
%%TYPE a[jj] = temp_val%%
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|