diff options
Diffstat (limited to 'src/lib/src/matrix.c')
-rw-r--r-- | src/lib/src/matrix.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/lib/src/matrix.c b/src/lib/src/matrix.c new file mode 100644 index 0000000..a7a4ce6 --- /dev/null +++ b/src/lib/src/matrix.c | |||
@@ -0,0 +1,298 @@ | |||
1 | #include <neuralnet/matrix.h> | ||
2 | |||
3 | #include <assert.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | |||
7 | nnMatrix nnMatrixMake(int rows, int cols) { | ||
8 | R* values = calloc(rows * cols, sizeof(R)); | ||
9 | assert(values != 0); | ||
10 | |||
11 | return (nnMatrix) { | ||
12 | .rows = rows, | ||
13 | .cols = cols, | ||
14 | .values = values, | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | void nnMatrixDel(nnMatrix* matrix) { | ||
19 | assert(matrix != 0); | ||
20 | |||
21 | if (matrix->values != 0) { | ||
22 | free(matrix->values); | ||
23 | matrix->values = 0; | ||
24 | matrix->rows = 0; | ||
25 | matrix->cols = 0; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | void nnMatrixMove(nnMatrix* in, nnMatrix* out) { | ||
30 | assert(in); | ||
31 | assert(out); | ||
32 | |||
33 | out->rows = in->rows; | ||
34 | out->cols = in->cols; | ||
35 | out->values = in->values; | ||
36 | |||
37 | in->rows = 0; | ||
38 | in->cols = 0; | ||
39 | in->values = 0; | ||
40 | } | ||
41 | |||
42 | void nnMatrixCopy(const nnMatrix* in, nnMatrix* out) { | ||
43 | assert(in); | ||
44 | assert(out); | ||
45 | assert(in->rows == out->rows); | ||
46 | assert(in->cols == out->cols); | ||
47 | |||
48 | const R* in_value = in->values; | ||
49 | R* out_value = out->values; | ||
50 | |||
51 | for (int i = 0; i < in->rows * in->cols; ++i) { | ||
52 | *out_value++ = *in_value++; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | void nnMatrixToArray(const nnMatrix* in, R* out) { | ||
57 | assert(in); | ||
58 | assert(out); | ||
59 | |||
60 | const R* values = in->values; | ||
61 | for (int i = 0; i < in->rows * in->cols; ++i) { | ||
62 | *out++ = *values++; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | void nnMatrixRowToArray(const nnMatrix* in, int row, R* out) { | ||
67 | assert(in); | ||
68 | assert(out); | ||
69 | |||
70 | const R* values = in->values + row * in->cols; | ||
71 | for (int i = 0; i < in->cols; ++i) { | ||
72 | *out++ = *values++; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | void nnMatrixCopyCol(const nnMatrix* in, nnMatrix* out, int col_in, int col_out) { | ||
77 | assert(in); | ||
78 | assert(out); | ||
79 | assert(in->rows == out->rows); | ||
80 | assert(col_in < in->cols); | ||
81 | assert(col_out < out->cols); | ||
82 | |||
83 | for (int row = 0; row < in->rows; ++row) { | ||
84 | nnMatrixSet(out, row, col_out, nnMatrixAt(in, row, col_in)); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | nnMatrix nnMatrixBorrow(nnMatrix* in) { | ||
89 | assert(in); | ||
90 | |||
91 | nnMatrix out; | ||
92 | out.rows = in->rows; | ||
93 | out.cols = in->cols; | ||
94 | out.values = in->values; | ||
95 | return out; | ||
96 | } | ||
97 | |||
98 | nnMatrix nnMatrixBorrowRows(nnMatrix* in, int row_start, int num_rows) { | ||
99 | assert(in); | ||
100 | assert(row_start < in->rows); | ||
101 | assert(row_start + num_rows <= in->rows); | ||
102 | |||
103 | nnMatrix out; | ||
104 | out.rows = num_rows; | ||
105 | out.cols = in->cols; | ||
106 | out.values = nnMatrixRow_mut(in, row_start); | ||
107 | return out; | ||
108 | } | ||
109 | |||
110 | void nnMatrixInit(nnMatrix* matrix, const R* values) { | ||
111 | assert(matrix); | ||
112 | assert(values); | ||
113 | memcpy(matrix->values, values, matrix->rows * matrix->cols * sizeof(R)); | ||
114 | } | ||
115 | |||
116 | void nnMatrixInitConstant(nnMatrix* matrix, R value) { | ||
117 | assert(matrix); | ||
118 | for (int i = 0; i < matrix->rows * matrix->cols; ++i) { | ||
119 | matrix->values[i] = value; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void nnMatrixMul(const nnMatrix* left, const nnMatrix* right, nnMatrix* out) { | ||
124 | assert(left != 0); | ||
125 | assert(right != 0); | ||
126 | assert(out != 0); | ||
127 | assert(out != left); | ||
128 | assert(out != right); | ||
129 | assert(left->cols == right->rows); | ||
130 | assert(out->rows == left->rows); | ||
131 | assert(out->cols == right->cols); | ||
132 | |||
133 | R* out_value = out->values; | ||
134 | |||
135 | for (int i = 0; i < left->rows; ++i) { | ||
136 | const R* left_row = &left->values[i * left->cols]; | ||
137 | |||
138 | for (int j = 0; j < right->cols; ++j) { | ||
139 | const R* right_col = &right->values[j]; | ||
140 | *out_value = 0; | ||
141 | |||
142 | // Vector dot product. | ||
143 | for (int k = 0; k < left->cols; ++k) { | ||
144 | *out_value += left_row[k] * right_col[0]; | ||
145 | right_col += right->cols; // Next row in the column. | ||
146 | } | ||
147 | |||
148 | out_value++; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | void nnMatrixMulAdd(const nnMatrix* left, const nnMatrix* right, R scale, nnMatrix* out) { | ||
154 | assert(left); | ||
155 | assert(right); | ||
156 | assert(out); | ||
157 | assert(left->rows == right->rows); | ||
158 | assert(left->cols == right->cols); | ||
159 | assert(left->rows == out->rows); | ||
160 | assert(left->cols == out->cols); | ||
161 | |||
162 | const R* left_value = left->values; | ||
163 | const R* right_value = right->values; | ||
164 | R* out_value = out->values; | ||
165 | |||
166 | for (int i = 0; i < left->rows * left->cols; ++i) { | ||
167 | *out_value++ = *left_value++ + *right_value++ * scale; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | void nnMatrixMulSub(const nnMatrix* left, const nnMatrix* right, R scale, nnMatrix* out) { | ||
172 | assert(left); | ||
173 | assert(right); | ||
174 | assert(out); | ||
175 | assert(left->rows == right->rows); | ||
176 | assert(left->cols == right->cols); | ||
177 | assert(left->rows == out->rows); | ||
178 | assert(left->cols == out->cols); | ||
179 | |||
180 | const R* left_value = left->values; | ||
181 | const R* right_value = right->values; | ||
182 | R* out_value = out->values; | ||
183 | |||
184 | for (int i = 0; i < left->rows * left->cols; ++i) { | ||
185 | *out_value++ = *left_value++ - *right_value++ * scale; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | void nnMatrixMulPairs(const nnMatrix* left, const nnMatrix* right, nnMatrix* out) { | ||
190 | assert(left != 0); | ||
191 | assert(right != 0); | ||
192 | assert(out != 0); | ||
193 | assert(left->rows == right->rows); | ||
194 | assert(left->cols == right->cols); | ||
195 | assert(left->rows == out->rows); | ||
196 | assert(left->cols == out->cols); | ||
197 | |||
198 | R* left_value = left->values; | ||
199 | R* right_value = right->values; | ||
200 | R* out_value = out->values; | ||
201 | |||
202 | for (int i = 0; i < left->rows * left->cols; ++i) { | ||
203 | *out_value++ = *left_value++ * *right_value++; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | void nnMatrixAdd(const nnMatrix* left, const nnMatrix* right, nnMatrix* out) { | ||
208 | assert(left); | ||
209 | assert(right); | ||
210 | assert(out); | ||
211 | assert(left->rows == right->rows); | ||
212 | assert(left->cols == right->cols); | ||
213 | assert(left->rows == out->rows); | ||
214 | assert(left->cols == out->cols); | ||
215 | |||
216 | const R* left_value = left->values; | ||
217 | const R* right_value = right->values; | ||
218 | R* out_value = out->values; | ||
219 | |||
220 | for (int i = 0; i < left->rows * left->cols; ++i) { | ||
221 | *out_value++ = *left_value++ + *right_value++; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | void nnMatrixSub(const nnMatrix* left, const nnMatrix* right, nnMatrix* out) { | ||
226 | assert(left); | ||
227 | assert(right); | ||
228 | assert(out); | ||
229 | assert(left->rows == right->rows); | ||
230 | assert(left->cols == right->cols); | ||
231 | assert(left->rows == out->rows); | ||
232 | assert(left->cols == out->cols); | ||
233 | |||
234 | const R* left_value = left->values; | ||
235 | const R* right_value = right->values; | ||
236 | R* out_value = out->values; | ||
237 | |||
238 | for (int i = 0; i < left->rows * left->cols; ++i) { | ||
239 | *out_value++ = *left_value++ - *right_value++; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | void nnMatrixAddRow(const nnMatrix* matrix, const nnMatrix* row, nnMatrix* out) { | ||
244 | assert(matrix); | ||
245 | assert(row); | ||
246 | assert(out); | ||
247 | assert(row->rows == 1); | ||
248 | assert(matrix->cols == row->cols); | ||
249 | assert(matrix->rows == out->rows); | ||
250 | assert(matrix->cols == out->cols); | ||
251 | |||
252 | const R* matrix_value = matrix->values; | ||
253 | R* out_value = out->values; | ||
254 | |||
255 | for (int i = 0; i < matrix->rows; ++i) { | ||
256 | const R* row_value = row->values; | ||
257 | for (int j = 0; j < row->cols; ++j) { | ||
258 | *out_value++ = *matrix_value++ + *row_value++; | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | void nnMatrixScale(nnMatrix* matrix, R scale) { | ||
264 | assert(matrix); | ||
265 | |||
266 | R* value = matrix->values; | ||
267 | for (int i = 0; i < matrix->rows * matrix->cols; ++i) { | ||
268 | *value++ *= scale; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | void nnMatrixTranspose(const nnMatrix* in, nnMatrix* out) { | ||
273 | assert(in); | ||
274 | assert(out); | ||
275 | assert(in != out); | ||
276 | assert(in->rows == out->cols); | ||
277 | assert(in->cols == out->rows); | ||
278 | |||
279 | for (int i = 0; i < in->rows; ++i) { | ||
280 | for (int j = 0; j < in->cols; ++j) { | ||
281 | nnMatrixSet(out, j, i, nnMatrixAt(in, i, j)); | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | void nnMatrixGt(const nnMatrix* in, R threshold, nnMatrix* out) { | ||
287 | assert(in); | ||
288 | assert(out); | ||
289 | assert(in->rows == out->rows); | ||
290 | assert(in->cols == out->cols); | ||
291 | |||
292 | const R* in_value = in->values; | ||
293 | R* out_value = out->values; | ||
294 | |||
295 | for (int i = 0; i < in->rows * in->cols; ++i) { | ||
296 | *out_value++ = (*in_value++) > threshold ? 1 : 0; | ||
297 | } | ||
298 | } | ||