1 // Copyright 2017 The Bazel Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "ffi/rust_calling_c/c/matrix.h"
16
17 #include <stdio.h>
18 #include <string.h>
19
matrix_new(size_t rows,size_t cols,const uint64_t * data)20 Matrix* matrix_new(size_t rows, size_t cols, const uint64_t* data) {
21 if (data == NULL) {
22 return NULL;
23 }
24 Matrix* matrix = (Matrix*)malloc(sizeof(*matrix));
25 if (matrix == NULL) {
26 return NULL;
27 }
28 matrix->rows = rows;
29 matrix->cols = cols;
30 matrix->data = (uint64_t*)malloc(rows * cols * sizeof(*(matrix->data)));
31 memcpy(matrix->data, data, rows * cols * sizeof(*data));
32 return matrix;
33 }
34
matrix_at(const Matrix * matrix,size_t row,size_t col,uint64_t * n)35 int matrix_at(const Matrix* matrix, size_t row, size_t col, uint64_t* n) {
36 if (matrix == NULL || matrix->data == NULL || n == NULL) {
37 return 0;
38 }
39 if (row >= matrix->rows || col >= matrix->cols) {
40 return 0;
41 }
42 *n = matrix->data[row * matrix->cols + col];
43 return 1;
44 }
45
matrix_set(const Matrix * matrix,size_t row,size_t col,uint64_t n)46 int matrix_set(const Matrix* matrix, size_t row, size_t col, uint64_t n) {
47 if (matrix == NULL || matrix->data == NULL) {
48 return 0;
49 }
50 if (row >= matrix->rows || col >= matrix->cols) {
51 return 0;
52 }
53 matrix->data[row * matrix->cols + col] = n;
54 return 1;
55 }
56
matrix_transpose(Matrix * matrix)57 void matrix_transpose(Matrix* matrix) {
58 if (matrix == NULL || matrix->data == NULL) {
59 return;
60 }
61
62 size_t len = matrix->rows * matrix->cols;
63 int* visited = (int*)malloc(len * sizeof(*visited));
64 if (visited == NULL) {
65 return;
66 }
67 memset(visited, 0, len * sizeof(*visited));
68
69 // Follow-the-cycles implementation of matrix transposition. Note that we
70 // skip the last element since it always has a cycle of length 1 and thus
71 // does not need to be moved.
72 size_t q = matrix->rows * matrix->cols - 1;
73 for (size_t i = 0; i < q; ++i) {
74 if (visited[i] == 1) {
75 continue;
76 }
77 size_t current_idx = i;
78 size_t next_idx = i;
79 do {
80 visited[current_idx] = 1;
81 next_idx = (current_idx * matrix->cols) % q;
82 if (next_idx == i) {
83 break;
84 }
85
86 uint64_t current_val = matrix->data[current_idx];
87 matrix->data[current_idx] = matrix->data[next_idx];
88 matrix->data[next_idx] = current_val;
89 current_idx = next_idx;
90 } while (1);
91 }
92
93 free(visited);
94 size_t cols = matrix->rows;
95 matrix->rows = matrix->cols;
96 matrix->cols = cols;
97 }
98
matrix_equal(const Matrix * a,const Matrix * b)99 int matrix_equal(const Matrix* a, const Matrix* b) {
100 if (a == NULL || b == NULL || a->data == NULL || b->data == NULL) {
101 return 0;
102 }
103 if (a->rows != b->rows || a->cols != b->cols) {
104 return 0;
105 }
106 size_t len = a->rows * a->cols;
107 for (size_t i = 0; i < len; ++i) {
108 if (a->data[i] != b->data[i]) {
109 return 0;
110 }
111 }
112 return 1;
113 }
114
matrix_free(Matrix * matrix)115 void matrix_free(Matrix* matrix) {
116 if (matrix == NULL) {
117 return;
118 }
119 if (matrix->data != NULL) {
120 free(matrix->data);
121 }
122 free(matrix);
123 }
124