• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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