nmatrix 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|