openGPMP
Open Source Mathematics Package
mtx_arm_vec_f32.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
33 #include <cassert>
34 #include <cstddef>
35 #include <cstdint>
36 #include <iostream>
37 #include <openGPMP/linalg/mtx.hpp>
38 #include <vector>
39 
40 /************************************************************************
41  *
42  * Matrix Operations for ARM NEON CPUs
43  *
44  ************************************************************************/
45 #if defined(__ARM_ARCH_ISA_A64) || defined(__ARM_NEON) || \
46  defined(__ARM_ARCH) || defined(__aarch64__)
47 
48 // ARM intrinsic function header
49 #include <arm_neon.h>
50 
51 /************************************************************************
52  *
53  * Matrix Operations on vector<vector>
54  *
55  ************************************************************************/
56 // matrix addition using ARM intrinsics, accepts float types
57 void gpmp::linalg::Mtx::mtx_add(const std::vector<std::vector<float>> &A,
58  const std::vector<std::vector<float>> &B,
59  std::vector<std::vector<float>> &C) {
60  const int rows = A.size();
61  const int cols = A[0].size();
62 
63  for (int i = 0; i < rows; ++i) {
64  int j = 0;
65  // requires matrices of size of at least 4x4
66  for (; j < cols - 3; j += 4) {
67  // load 4 elements from A, B, and C matrices using NEON intrinsics
68  float32x4_t a = vld1q_f32(&A[i][j]);
69  float32x4_t b = vld1q_f32(&B[i][j]);
70  float32x4_t c = vld1q_f32(&C[i][j]);
71 
72  // perform vectorized addition
73  c = vaddq_f32(a, b);
74 
75  // store the result back to the C matrix using NEON intrinsics
76  vst1q_f32(&C[i][j], c);
77  }
78 
79  // handle the remaining elements that are not multiples of 4
80  for (; j < cols; ++j) {
81  C[i][j] = A[i][j] + B[i][j];
82  }
83  }
84 }
85 
86 // matrix subtraction using ARM intrinsics, accepts double types
87 void gpmp::linalg::Mtx::mtx_sub(const std::vector<std::vector<float>> &A,
88  const std::vector<std::vector<float>> &B,
89  std::vector<std::vector<float>> &C) {
90  const int rows = A.size();
91  const int cols = A[0].size();
92 
93  for (int i = 0; i < rows; ++i) {
94  int j = 0;
95  // requires matrices of size of at least 4x4
96  for (; j < cols - 3; j += 4) {
97  // load 4 elements from A, B, and C matrices using NEON intrinsics
98  float32x4_t a = vld1q_f32(&A[i][j]);
99  float32x4_t b = vld1q_f32(&B[i][j]);
100  float32x4_t c = vld1q_f32(&C[i][j]);
101 
102  // perform vectorized subtraction
103  c = vsubq_f32(a, b);
104 
105  // store the result back to the C matrix using NEON intrinsics
106  vst1q_f32(&C[i][j], c);
107  }
108 
109  // handle the remaining elements that are not multiples of 4
110  for (; j < cols; ++j) {
111  C[i][j] = A[i][j] - B[i][j];
112  }
113  }
114 }
115 
116 void gpmp::linalg::Mtx::mtx_tpose(std::vector<std::vector<double>> &matrix) {
117  const int rows = matrix.size();
118  const int cols = matrix[0].size();
119 
120  for (int i = 0; i < rows; i += 2) {
121  for (int j = i; j < cols; j += 2) {
122  float64x2x2_t row1 = vld2q_f64(&matrix[i][j]);
123  float64x2x2_t row2 = vld2q_f64(&matrix[i + 1][j]);
124 
125  // Transpose 2x2 submatrix
126  float64x2x2_t transposed;
127  transposed.val[0] = vcombine_f64(vget_low_f64(row1.val[0]),
128  vget_low_f64(row2.val[0]));
129  transposed.val[1] = vcombine_f64(vget_low_f64(row1.val[1]),
130  vget_low_f64(row2.val[1]));
131 
132  // Store the transposed 2x2 submatrix back to the matrix
133  vst2q_f64(&matrix[i][j], transposed);
134  }
135  }
136 }
137 
138 #endif
list C
Definition: linalg.py:24
list A
Definition: linalg.py:22
list B
Definition: linalg.py:23