unmtx_gpu/lib.rs
1//
2// Copyright (c) 2025 Łukasz Szpakowski
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7//
8//! Micro neural matrix library for GPU is small library that operates on matrices.
9//!
10//! This library uses GPU by the following computing platforms:
11//!
12//! - OpenCL
13//! - CUDA
14//!
15//! If this library uses CUDA, this library can use the cuBLAS library to multiplication of
16//! matrices.
17//!
18//! A frontend-backend architecture is used by this library. The frontend of this library can use
19//! one of two backends (OpenCL or CUDA). These backends allow to use GPU by the computing
20//! platforms. The frontend and the backend can have many instances. This library provides a
21//! high-level interfece to operations of matrices by the frontend and methods of a [`Matrix`]
22//! structure.
23//!
24//! # Examples
25//!
26//! ```
27//! # use unmtx_gpu::*;
28//! let a = matrix![
29//! [1.0, 2.0],
30//! [3.0, 4.0]
31//! ];
32//! let x = matrix![
33//! [5.0],
34//! [6.0]
35//! ];
36//! let b = matrix![
37//! [7.0],
38//! [8.0]
39//! ];
40//! let c = a * x + b;
41//! assert_eq!(vec![1.0 * 5.0 + 2.0 * 6.0 + 7.0, 3.0 * 5.0 + 4.0 * 6.0 + 8.0], c.elems());
42//! ```
43use std::ops::Neg;
44use std::ops::Add;
45use std::ops::AddAssign;
46use std::ops::Sub;
47use std::ops::SubAssign;
48use std::ops::Mul;
49use std::ops::MulAssign;
50use std::ops::Div;
51use std::ops::DivAssign;
52use std::error;
53use std::fmt;
54use std::result;
55use std::sync::Arc;
56use std::sync::Mutex;
57use std::sync::MutexGuard;
58
59#[cfg(feature = "opencl")]
60pub mod opencl;
61#[cfg(feature = "cuda")]
62pub mod cuda;
63
64/// A backend trait.
65///
66/// The backend provides a low-level interface to computing platform (OpenCL or CUDA) for basic
67/// operations and functions on matrices. The backend methods operate on backend arrays which
68/// refers to areas of the device memory. The backend is low-level layer between a frontend and
69/// computing platform.
70pub trait Backend
71{
72 /// Returns the backend name.
73 fn name(&self) -> &'static str;
74
75 /// Returns `true` if the backend uses cuBLAS, otherwise `false`.
76 fn has_cublas(&self) -> bool;
77
78 /// Allocates a backend array.
79 unsafe fn alloc(&self, n: usize) -> Result<BackendArray>;
80
81 /// Allocates a backend array and stores zeros in the backend array.
82 fn alloc_and_store_zeros(&self, n: usize) -> Result<BackendArray>;
83
84 /// Allocates a backend array and stores the elements in the backend array.
85 fn alloc_and_store(&self, elems: &[f32]) -> Result<BackendArray>;
86
87 /// Loads elements from the backenc array.
88 fn load(&self, a: &BackendArray, elems: &mut [f32]) -> Result<()>;
89
90 /// Stores elements in the backend array.
91 fn store(&self, a: &BackendArray, elems: &[f32]) -> Result<()>;
92
93 /// Copies the `a` backend array to the `b` backend array.
94 fn copy(&self, a: &BackendArray, b: &BackendArray) -> Result<()>;
95
96 /// Transposes the `a` matrix and then the result is in the `b` matrix
97 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
98 fn transpose_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
99
100 /// Adds the `b` matrix to the `a` matrix and then the result is in the `c` matrix
101 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>+</mo><mi mathvariant="bold">B</mi></mrow></math>).
102 fn add_a_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
103
104 /// Adds the `b` matrix to the transposed `a` matrix and then the result is in the `c` matrix
105 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>+</mo><mi mathvariant="bold">B</mi></mrow></math>).
106 fn add_at_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
107
108 /// Adds the transposed `b` matrix to the `a` matrix and then the result is in the `c` matrix
109 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>+</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
110 fn add_a_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
111
112 /// Adds the transposed `b` matrix to the transposed `a` matrix and then the result is in the
113 /// `c` matrix
114 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>+</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
115 fn add_at_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
116
117 /// Subtracts the `b` matrix from the `a` matrix and then the result is in the `c` matrix
118 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>-</mo><mi mathvariant="bold">B</mi></mrow></math>).
119 fn sub_a_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
120
121 /// Subtracts the `b` matrix from the transposed `a` matrix and then the result is in the `c`
122 /// matrix
123 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>-</mo><mi mathvariant="bold">B</mi></mrow></math>).
124 fn sub_at_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
125
126 /// Subtracts the transposed `b` matrix from the `a` matrix and then the result is in the `c`
127 /// matrix
128 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>-</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
129 fn sub_a_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
130
131 /// Subtracts the transposed `b` matrix from the transposed `a` matrix and then the result is
132 /// in the `c` matrix
133 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>-</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
134 fn sub_at_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
135
136 /// Multiplies the `a` matrix by the `b` matrix and then the result is in the `c` matrix
137 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>·</mo><mi mathvariant="bold">B</mi></mrow></math>).
138 fn mul_a_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize, l: usize) -> Result<()>;
139
140 /// Multiplies the transposed `a` matrix by the `b` matrix and then the result is in the `c`
141 /// matrix
142 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>·</mo><mi mathvariant="bold">B</mi></mrow></math>).
143 fn mul_at_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize, l: usize) -> Result<()>;
144
145 /// Multiplies the `a` matrix by the transposed `b` matrix and then the result is in the `c`
146 /// matrix
147 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>·</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
148 fn mul_a_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize, l: usize) -> Result<()>;
149
150 /// Multiplies the transposed `a` matrix by the transposed `b` matrix and then the result is in
151 /// the `c` matrix
152 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>·</mo><msup><mi mathvariant="bold">B</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
153 fn mul_at_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize, l: usize) -> Result<()>;
154
155 /// Multiplies the `a` matrix elements by the `b` matrix elements and then the result is in the
156 /// `c` matrix
157 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
158 fn mul_a_b_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
159
160 /// Multiplies the transposed `a` matrix elements by the `b` matrix elements and saves the
161 /// result to the `c` matrix
162 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
163 fn mul_at_b_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
164
165 /// Multiplies the `a` matrix elements by the transposed `b` matrix elements and then the
166 /// result is in the `c` matrix
167 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mrow></math>).
168 fn mul_a_bt_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
169
170 /// Multiplies the transposed `a` matrix elements by the transposed `b` matrix elements and
171 /// then the result is in the `c` matrix.
172 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mrow></math>).
173 fn mul_at_bt_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
174
175 /// Divides the `a` matrix elements by the `b` matrix elements and then the result is in the
176 /// `c` matrix
177 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
178 fn div_a_b_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
179
180 /// Divides the transposed `a` matrix elements by the `b` matrix elements and then the result
181 /// is in the `c` matrix
182 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
183 fn div_at_b_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
184
185 /// Divides the`a` matrix elements by the transposed `b` matrix elements and then the result
186 /// is in the `c` matrix
187 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac></mrow></math>).
188 fn div_a_bt_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
189
190 /// Divides the transposed `a` matrix elements by the transposed `b` matrix elements and then
191 /// the result is in the `c` matrix
192 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac></mrow></math>).
193 fn div_at_bt_for_elems(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
194
195 /// Adds the `b` scalar to the `a` matrix and then the result is in the `c` matrix
196 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>+</mo><mi>b</mi></mrow></math>).
197 fn add_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
198
199 /// Adds the `b` scalar to the transposed `a` matrix and then the result is in the `c` matrix
200 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>+</mo><mi>b</mi></mrow></math>).
201 fn add_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
202
203 /// Subtracts the `b` scalar from the `a` matrix and then the result is in the `c` matrix.
204 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>-</mo><mi>b</mi></mrow></math>).
205 fn sub_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
206
207 /// Subtracts the `b` scalar from the transposed `a` matrix and then the result is in the `c`
208 /// matrix
209 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>-</mo><mi>b</mi></mrow></math>).
210 fn sub_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
211
212 /// Subtracts the `a` matrix from the `b` scalar and then the result is in the `c` matrix
213 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi>b</mi><mo>-</mo><mi mathvariant="bold">A</mi></mrow></math>).
214 fn rsub_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
215
216 /// Subtracts the transposed `a` matrix from the `b` scalar and then the result is in the `c`
217 /// matrix
218 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi>b</mi><mo>-</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
219 fn rsub_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
220
221 /// Multiplies the `a` matrix by the `b` scalar and then the result is in the `c` matrix
222 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>·</mo><mi>b</mi></mrow></math>).
223 fn mul_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
224
225 /// Multiplies the transposed `a` matrix by the `b` scalar and then the result is in the `c`
226 /// matrix
227 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo>·</mo><mi>b</mi></mrow></math>).
228 fn mul_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
229
230 /// Divides the `a` matrix by the `b` scalar and then the result is in the `c` matrix
231 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mfrac><mi mathvariant="bold">A</mi><mi>b</mi></mfrac></mrow></math>).
232 fn div_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
233
234 /// Divides the transposed `a` matrix by the `b` scalar and then the result is in the `c`
235 /// matrix
236 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mfrac><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mi>b</mi></mfrac></mrow></math>).
237 fn div_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
238
239 /// Divides the `b` scalar by the `a` matrix elements and then the result is in the `c` matrix
240 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
241 fn rdiv_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
242
243 /// Divides the `b` scalar by the transposed `a` matrix elements and then the result is in the
244 /// `c` matrix
245 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac></mrow></math>).
246 fn rdiv_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
247
248 /// Calculates sigmoid function for the `a` matrix and then the result is in the `b` matrix
249 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sigmoid</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
250 fn sigmoid_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
251
252 /// Calculates sigmoid function for the transposed `a` matrix and then the result is in the
253 /// `b` matrix
254 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sigmoid</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
255 fn sigmoid_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
256
257 /// Calculates hyperbolic tangent function for the `a` matrix and then the result is in `b`
258 /// matrix
259 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
260 fn tanh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
261
262 /// Calculates hyperbolic tangent function for the transposed `a` matrix and then the result
263 /// is in the `b` matrix
264 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tanh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
265 fn tanh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
266
267 /// Calculates swish function for the `a` matrix and then the result is in the `b` matrix
268 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>swish</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
269 fn swish_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
270
271 /// Calculates swish function for the transposed `a` matrix and then the result is in the `b`
272 /// matrix
273 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>swish</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
274 fn swish_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
275
276 /// Calculates softmax function for the `a` matrix and then the result is in the `b` matrix
277 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>softmax</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
278 fn softmax_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
279
280 /// Calculates softmax function for the transposed `a` matrix and then the result is in the `b`
281 /// matrix
282 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>softmax</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
283 fn softmax_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
284
285 /// Calculates square roots of the `a` matrix elements and then the result is in the `b` matrix
286 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msqrt><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msqrt></mrow></math>).
287 fn sqrt_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
288
289 /// Calculates square roots of the transposed `a` matrix elements and then the result is in the
290 /// `b` matrix
291 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msqrt><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></msqrt></mrow></math>).
292 fn sqrt_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
293
294 /// Repeats the `a` vector as column
295 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mi>i</mi></msub></mrow></math>).
296 fn repeat_col_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
297
298 /// Repeats the `a` vector as row
299 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mi>j</mi></msub></mrow></math>).
300 fn repeat_row_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
301
302 /// Calculates absolute values of the `a` matrix elements and then the result is in the `b`
303 /// matrix
304 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mo fence="true">|</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo fence="true">|</mo></mrow></math>).
305 fn abs_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
306
307 /// Calculates absolute values of the transposed `a` matrix elements and then the result is in
308 /// the `b` matrix
309 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mo fence="true">|</mo><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><mo fence="true">|</mo></mrow></math>).
310 fn abs_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
311
312 /// Raises the `a` matrix elements to the power of the `b` matrix elements and then the result
313 /// is in the `c` matrix
314 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
315 fn pow_a_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
316
317 /// Raises the transposed `a` matrix elements to the power of the `b` matrix elements and then
318 /// the result is in the `c` matrix
319 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
320 fn pow_at_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
321
322 /// Raises the `a` matrix elements to the power of the transposed `b` matrix elements and then
323 /// the result is in the `c` matrix
324 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></msup></mrow></math>).
325 fn pow_a_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
326
327 /// Raises the transposed `a` matrix elements to the power of the transposed `b` matrix
328 /// elements and then the result is in the `c` matrix
329 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></msup></mrow></math>).
330 fn pow_at_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
331
332 /// Raises the `a` matrix elements to the power of the `b` scalar and then the result is in
333 /// the `c` matrix
334 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></msup></mrow></math>).
335 fn pow_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
336
337 /// Raises the transposed `a` matrix elements to the power of the `b` scalar and then the
338 /// result is in the `c` matrix
339 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><mi>b</mi></msup></mrow></math>).
340 fn pow_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
341
342 /// Raises the `b` scalar to the power of the `a` matrix elements and then the result is in
343 /// the `c` matrix
344 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
345 fn rpow_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
346
347 /// Raises the `b` scalar to the power of the transposed `a` matrix elements and then the
348 /// result is in the `c` matrix
349 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>b</mi><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></msup></mrow></math>).
350 fn rpow_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
351
352 /// Calculates exponential function for the `a` matrix and then the result is in the `b`
353 /// matrix
354 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>e</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
355 fn exp_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
356
357 /// Calculates exponential function for the transposed `a` matrix elements and then the result
358 /// is in the `b` matrix
359 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>e</mi><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></msup></mrow></math>).
360 fn exp_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
361
362 /// Calculates natural logarithm of the `a` matrix elements and then the result is in the `b`
363 /// matrix
364 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>ln</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
365 fn ln_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
366
367 /// Calculates natural logarithm of the transposed `a` matrix elements and then the result is
368 /// in the `b` matrix
369 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>ln</mi><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mrow></math>).
370 fn ln_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
371
372 /// Calculates base 2 logarithm of the `a` matrix elements and then the result is in the `b`
373 /// matrix
374 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>2</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
375 fn log2_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
376
377 /// Calculates base 2 logarithm of the transposed `a` matrix elements and then the result is
378 /// in the `b` matrix
379 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>2</mn></msub><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mrow></math>).
380 fn log2_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
381
382 /// Calculates base 10 logarithm of the `a` matrix elements and then the result is in the `b`
383 /// matrix
384 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>10</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
385 fn log10_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
386
387 /// Calculates base 10 logarithm of the transposed `a` matrix elements and then the result is
388 /// in the `b` matrix
389 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>10</mn></msub><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mrow></math>).
390 fn log10_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
391
392 /// Calculates sine function for the `a` matrix and then the result is in the `b` matrix
393 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
394 fn sin_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
395
396 /// Calculates sine function for the transposed `a` matrix and then the result is in the `b`
397 /// matrix
398 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sin</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
399 fn sin_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
400
401 /// Calculates cosine function for the `a` matrix and then the result is in the `b` matrix
402 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
403 fn cos_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
404
405 /// Calculates cosine function for the transposed `a` matrix and then the result is in the `b`
406 /// matrix
407 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cos</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
408 fn cos_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
409
410 /// Calculates tangent function for the `a` matrix and then the result is in the `b` matrix
411 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
412 fn tan_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
413
414 /// Calculates tangent function for the transposed `a` matrix and then the result is in the
415 /// `b` matrix
416 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tan</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
417 fn tan_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
418
419 /// Calculates arcsine function for the `a` matrix and then the result is in the `b` matrix
420 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcsin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
421 fn asin_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
422
423 /// Calculates arcsine function for the transposed `a` matrix and then the result is in the
424 /// `b` matrix
425 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcsin</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
426 fn asin_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
427
428 /// Calculates arccosine function for the `a` matrix and then the result is in the `b` matrix
429 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arccos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
430 fn acos_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
431
432 /// Calculates arccosine function for the transposed `a` matrix and then the result is in the
433 /// `b` matrix
434 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arccos</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
435 fn acos_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
436
437 /// Calculates arctangent function for the `a` matrix and then the result is in the `b` matrix
438 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
439 fn atan_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
440
441 /// Calculates arctangent function for the transposed `a` matrix and then the result is in the
442 /// `b` matrix
443 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
444 fn atan_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
445
446 /// Calculates arctangent function for the `a` matrix elements and the `b` matrix elements and
447 /// then the result is in the `c` matrix
448 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
449 fn atan2_a_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
450
451 /// Calculates arctangent function for the transposed `a` matrix elements and the `b` matrix
452 /// elements and then the result is in the `c` matrix
453 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
454 fn atan2_at_b(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
455
456 /// Calculates arctangent function for the `a` matrix elements and the transposed `b` matrix
457 /// elements and then the result is in the `c` matrix
458 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
459 fn atan2_a_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
460
461 /// Calculates arctangent function for the transposed`a` matrix elements and the transposed
462 /// `b` matrix elements and then the result is in the `c` matrix
463 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><msub><mi>b</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
464 fn atan2_at_bt(&self, a: &BackendArray, b: &BackendArray, c: &BackendArray, n: usize, m: usize) -> Result<()>;
465
466 /// Calculates arctangent function for the `a` matrix elements and the `b` scalar and then the
467 /// result is in the `c` matrix
468 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></mfrac><mo fence="true">)</mo></mrow></math>).
469 fn atan2_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
470
471 /// Calculates arctangent function for the transposed `a` matrix elements and the `b` scalar
472 /// and then the result is in the `c` matrix
473 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub><mi>b</mi></mfrac><mo fence="true">)</mo></mrow></math>).
474 fn atan2_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
475
476 /// Calculates arctangent function for the `b` scalar and the `a` matrix elements and then the
477 /// result is in the `c` matrix
478 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
479 fn ratan2_a_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
480
481 /// Calculates arctangent function for the `b` scalar and the transposed `a` matrix elements
482 /// and then the result is in the `c` matrix
483 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>j</mi><mi>i</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
484 fn ratan2_at_b_for_scalar(&self, a: &BackendArray, b: f32, c: &BackendArray, n: usize, m: usize) -> Result<()>;
485
486 /// Calculates hyperbolic sine function for the `a` matrix and then the result is in the `b`
487 /// matrix
488 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
489 fn sinh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
490
491 /// Calculates hyperbolic sine function for the transposed `a` matrix and then the result is
492 /// in the `b` matrix
493 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sinh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
494 fn sinh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
495
496 /// Calculates hyperbolic cosine function for the `a` matrix and then the result is in the `b`
497 /// matrix
498 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
499 fn cosh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
500
501 /// Calculates hyperbolic cosine function for the transposed `a` matrix and then the result is
502 /// in the `b` matrix
503 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cosh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
504 fn cosh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
505
506 /// Calculates inverse hyperbolic sine function for the `a` matrix and then the result is in
507 /// the `b` matrix
508 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arsinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
509 fn asinh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
510
511 /// Calculates inverse hyperbolic sine function for the transposed `a` matrix and then the
512 /// result is in the `b` matrix
513 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arsinh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
514 fn asinh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
515
516 /// Calculates inverse hyperbolic cosine function for the `a` matrix and then the result is in
517 /// the `b` matrix
518 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
519 fn acosh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
520
521 /// Calculates inverse hyperbolic cosine function for the transposed `a` matrix and then the
522 /// result is in the `b` matrix
523 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcosh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
524 fn acosh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
525
526 /// Calculates inverse hyperbolic tangent function for the `a` matrix and then the result is
527 /// in the `b` matrix
528 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>artanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
529 fn atanh_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
530
531 /// Calculates inverse hyperbolic tangent function for the transposed `a` matrix and then the
532 /// result is in the `b` matrix
533 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>artanh</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
534 fn atanh_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
535
536 /// Calculates signum function for the `a` matrix and then the result is in the `b` matrix
537 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sgn</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
538 fn signum_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
539
540 /// Calculates signum function for the transposed `a` matrix and then the result is in the `b`
541 /// matrix
542 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sgn</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
543 fn signum_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
544
545 /// Calculates ceil function for the `a` matrix and then the result is in the `b` matrix
546 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>ceil</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
547 fn ceil_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
548
549 /// Calculates ceil function for the transposed `a` matrix and then the result is in the `b`
550 /// matrix
551 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>ceil</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
552 fn ceil_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
553
554 /// Calculates floor function for the `a` matrix and then the result is in the `b` matrix
555 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>floor</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
556 fn floor_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
557
558 /// Calculates floor function for the transposed `a` matrix and then the result is in the `b`
559 /// matrix
560 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>floor</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
561 fn floor_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
562
563 /// Calculates round function for the `a` matrix and then the result is in the `b` matrix
564 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>round</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
565 fn round_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
566
567 /// Calculates round function for the transposed `a` matrix and then the result is in the `b`
568 /// matrix
569 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>round</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
570 fn round_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
571
572 /// Calculates trunc function for the `a` matrix and then the result is in the `b` matrix
573 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>trunc</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
574 fn trunc_a(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
575
576 /// Calculates trunc function for the transposed `a` matrix and then the result is in the `b`
577 /// matrix
578 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>trunc</mi><mo fence="true">(</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup><mo fence="true">)</mo></mrow></math>).
579 fn trunc_at(&self, a: &BackendArray, b: &BackendArray, n: usize, m: usize) -> Result<()>;
580}
581
582/// An error enumeration.
583#[derive(Debug)]
584pub enum Error
585{
586 /// Can't initialize a default backend.
587 DefaultBackendInitialization,
588 /// Mismatched sizes of matrices for a matrix operation.
589 OpSize(usize, usize, usize, usize),
590 /// Mismatched sizes of matrices for a matrix multiplication.
591 MulSize(usize, usize, usize, usize, usize, usize),
592 /// Mismatched sizes of matrices for a matrix transposition.
593 TransposeSize(usize, usize, usize, usize),
594 /// An argument matrix is transposed.
595 ArgTransposition,
596 /// A result matrix is transposed.
597 ResTransposition,
598 /// A number of matrix elements isn't equal to a number of elements.
599 MatrixElemCount(usize, usize),
600 /// A matrix isn't a vector.
601 IsNotVector,
602 /// A mutex can't be locked.
603 Mutex,
604 /// An OpenCL error.
605 #[cfg(feature = "opencl")]
606 OpenCl(opencl::ClError),
607 /// A CUDA error.
608 #[cfg(feature = "cuda")]
609 Cuda(cuda::DriverError),
610 /// A cuBLAS error.
611 #[cfg(feature = "cuda")]
612 Cublas(cuda::CublasError),
613 /// No a cuBLAS.
614 #[cfg(feature = "cuda")]
615 NoCublas,
616 /// A compilation error.
617 Compilation(String),
618 /// No a platform.
619 NoPlatform,
620 /// No a device.
621 NoDevice,
622 /// No a kernel.
623 NoKernel(String),
624 /// A type of device information is invalid.
625 InvalidDeviceInfoType,
626 /// A number of backend array elements isn't equal to a number of elements.
627 BackendArrayElemCount(usize, usize),
628 /// Two numbers of elements of backend arrays aren't equal.
629 TwoBackendArrayElemCounts(usize, usize),
630 /// A backend array is invalid.
631 InvalidBackendArray,
632}
633
634impl error::Error for Error
635{}
636
637impl fmt::Display for Error
638{
639 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
640 {
641 match self {
642 Error::DefaultBackendInitialization => write!(f, "can't initialize default backend"),
643 Error::OpSize(n1, m1, n2, m2) => write!(f, "mismatched sizes of matrices ({}x{}, {}x{})", n1, m1, n2, m2),
644 Error::MulSize(n1, m1, n2, m2, n3, m3) => write!(f, "mismatched sizes of matrices for multiplication ({}x{}, {}x{}, {}x{})", n1, m1, n2, m2, n3, m3),
645 Error::TransposeSize(n1, m1, n2, m2) => write!(f, "mismatched sizes of matrices for transposition ({}x{}, {}x{})", n1, m1, n2, m2),
646 Error::ArgTransposition => write!(f, "argument matrix is transposed"),
647 Error::ResTransposition => write!(f, "result matrix is transposed"),
648 Error::MatrixElemCount(n1, n2) => write!(f, "number of matrix elements isn't equal to number of elements ({}, {})", n1, n2),
649 Error::IsNotVector => write!(f, "matrix isn't vector"),
650 Error::Mutex => write!(f, "can't lock mutex"),
651 #[cfg(feature = "opencl")]
652 Error::OpenCl(err) => write!(f, "OpenCL error: {}", err),
653 #[cfg(feature = "cuda")]
654 Error::Cuda(err) => write!(f, "CUDA error: {}", err),
655 #[cfg(feature = "cuda")]
656 Error::Cublas(err) => write!(f, "cuBLAS error: {}", err),
657 #[cfg(feature = "cuda")]
658 Error::NoCublas => write!(f, "no cuBLAS"),
659 Error::Compilation(msg) => write!(f, "{}", msg),
660 Error::NoPlatform => write!(f, "no platform"),
661 Error::NoDevice => write!(f, "no device"),
662 Error::NoKernel(name) => write!(f, "no kernel {}", name),
663 Error::InvalidDeviceInfoType => write!(f, "invalid device info type"),
664 Error::BackendArrayElemCount(n1, n2) => write!(f, "number of backend array elements isn't equal to number of elements ({}, {})", n1, n2),
665 Error::TwoBackendArrayElemCounts(n1, n2) => write!(f, "two numbers of elements of backend arrays aren't equal ({}, {})", n1, n2),
666 Error::InvalidBackendArray => write!(f, "invalid backend array"),
667 }
668 }
669}
670
671/// A result type.
672pub type Result<T> = result::Result<T, Error>;
673
674/// An enumeration of backend array.
675///
676/// This enumeration contains the reference to the area of the device memory for computing
677/// platform (OpenCL or CUDA).
678#[derive(Debug)]
679pub enum BackendArray
680{
681 /// A backend array for OpenCL.
682 #[cfg(feature = "opencl")]
683 OpenCl(opencl::ClBackendArray),
684 /// A backend array for CUDA.
685 #[cfg(feature = "cuda")]
686 Cuda(cuda::CudaBackendArray),
687}
688
689static DEFAULT_BACKEND: Mutex<Option<Arc<dyn Backend + Send + Sync>>> = Mutex::new(None);
690
691fn mutex_lock<T>(mutex: &Mutex<T>) -> Result<MutexGuard<'_, T>>
692{
693 match mutex.lock() {
694 Ok(guard) => Ok(guard),
695 Err(_) => return Err(Error::Mutex),
696 }
697}
698
699/// Returns a default backend.
700pub fn get_default_backend() -> Result<Option<Arc<dyn Backend + Send + Sync>>>
701{
702 let default_backend_g = mutex_lock(&DEFAULT_BACKEND)?;
703 Ok(default_backend_g.clone())
704}
705
706/// Sets a default backend.
707pub fn set_default_backend(backend: Arc<dyn Backend + Send + Sync>) -> Result<()>
708{
709 let mut default_backend_g = mutex_lock(&DEFAULT_BACKEND)?;
710 *default_backend_g = Some(backend);
711 Ok(())
712}
713
714/// Unsets a default backend.
715pub fn unset_default_backend() -> Result<()>
716{
717 let mut default_backend_g = mutex_lock(&DEFAULT_BACKEND)?;
718 *default_backend_g = None;
719 Ok(())
720}
721
722/// Sets a default backend if the default backend is uninitialized and returns the default
723/// backend.
724///
725/// This method takes a closure that returns the backend and then the backend is set as the
726/// default backend if the default backend is uninitialized. The closure is only called if the
727/// backend is to be set.
728pub fn set_default_backend_for_uninitialized<F>(f: F) -> Result<Arc<dyn Backend + Send + Sync>>
729 where F: FnOnce() -> Result<Arc<dyn Backend + Send + Sync>>
730{
731 let mut default_backend_g = mutex_lock(&DEFAULT_BACKEND)?;
732 match &*default_backend_g {
733 Some(default_backend) => Ok(default_backend.clone()),
734 None => {
735 let backend = f()?;
736 *default_backend_g = Some(backend.clone());
737 Ok(backend)
738 },
739 }
740}
741
742/// Initializes a default backend if the default backend is uninitialized and returns the default
743/// backend.
744pub fn initialize_default_backend_for_uninitialized() -> Result<Arc<dyn Backend + Send + Sync>>
745{
746 #[cfg(feature = "opencl")]
747 let res = set_default_backend_for_uninitialized(|| Ok(Arc::new(opencl::ClBackend::new()?)));
748 #[cfg(all(not(feature = "opencl"), feature = "cuda"))]
749 let res = set_default_backend_for_uninitialized(|| Ok(Arc::new(cuda::CudaBackend::new()?)));
750 #[cfg(all(not(feature = "opencl"), not(feature = "cuda")))]
751 let res: Result<Arc<dyn Backend + Send + Sync>> = Err(Error::DefaultBackendInitialization);
752 res
753}
754
755/// Finalizes a default backend.
756pub fn finalize_default_backend() -> Result<()>
757{ unset_default_backend() }
758
759/// Creates a matrix from the arguments.
760///
761/// # Examples
762///
763/// ```
764/// # use unmtx_gpu::*;
765/// let a = matrix![
766/// [1.0, 2.0, 3.0],
767/// [4.0, 5.0, 6.0]
768/// ];
769/// assert_eq!(2, a.row_count());
770/// assert_eq!(3, a.col_count());
771/// assert_eq!(false, a.is_transposed());
772/// assert_eq!(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], a.elems());
773/// ```
774#[macro_export]
775macro_rules! matrix {
776 ($([$($elem:expr),* $(,)*]),* $(,)*) => {
777 $crate::Matrix::new_with_elem_vecs(vec![$(vec![$($elem),*]),*].as_slice())
778 };
779}
780
781/// A matrix structure.
782#[derive(Clone, Debug)]
783pub struct Matrix
784{
785 row_count: usize,
786 col_count: usize,
787 is_transposed: bool,
788 array: Arc<BackendArray>,
789}
790
791impl Matrix
792{
793 /// Creates a matrix with the number of rows and the number of columns.
794 pub fn new(row_count: usize, col_count: usize) -> Self
795 {
796 let frontend = Frontend::new().unwrap();
797 frontend.create_matrix_and_set_zeros(row_count, col_count).unwrap()
798 }
799
800 /// Creates a matrix with the number of rows, the number of columns, and the elements.
801 pub fn new_with_elems(row_count: usize, col_count: usize, elems: &[f32]) -> Self
802 {
803 let frontend = Frontend::new().unwrap();
804 frontend.create_matrix_and_set_elems(row_count, col_count, elems).unwrap()
805 }
806
807 /// Creates a matrix with the vector of rows.
808 pub fn new_with_elem_vecs(elem_vecs: &[Vec<f32>]) -> Self
809 {
810 let frontend = Frontend::new().unwrap();
811 let col_count = match elem_vecs.first() {
812 Some(elems) => elems.len(),
813 None => 0,
814 };
815 for row in elem_vecs {
816 assert_eq!(col_count, row.len());
817 }
818 let row_count = elem_vecs.len();
819 let elems: Vec<f32> = elem_vecs.iter().flatten().map(|e| *e).collect();
820 frontend.create_matrix_and_set_elems(row_count, col_count, elems.as_slice()).unwrap()
821 }
822
823 /// Returns the number of matrix rows.
824 pub fn row_count(&self) -> usize
825 { self.row_count }
826
827 /// Returns the number of matrix columns.
828 pub fn col_count(&self) -> usize
829 { self.col_count }
830
831 /// Returns `true` if the matrix is transposed, otherwise `false`.
832 ///
833 /// This method indeed returns the transpose flag of matrix that is changed by
834 /// [`transpose`](Self::transpose).
835 pub fn is_transposed(&self) -> bool
836 { self.is_transposed }
837
838 /// Returns the matrix elements.
839 pub fn elems(&self) -> Vec<f32>
840 {
841 let frontend = Frontend::new().unwrap();
842 frontend.elems_and_transpose_flag(self).unwrap().0
843 }
844
845 /// Creates a matrix copy.
846 ///
847 /// This method indeed copies the matrix array to a new matrix array.
848 pub fn copy(&self) -> Self
849 {
850 let frontend = Frontend::new().unwrap();
851 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
852 frontend.copy(self, &res).unwrap();
853 res
854 }
855
856 /// Transposes the matrix
857 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
858 ///
859 /// This method doesn't indeed transpose the matrix but changes the transpose flag and
860 /// exchanges the number of matrix rows with the number of matrix columns.
861 ///
862 /// # Examples
863 ///
864 /// ```
865 /// # use unmtx_gpu::*;
866 /// let a = matrix![
867 /// [1.0, 2.0, 3.0],
868 /// [4.0, 5.0, 6.0]
869 /// ];
870 /// let b = a.transpose();
871 /// assert_eq!(3, b.row_count());
872 /// assert_eq!(2, b.col_count());
873 /// assert_eq!(true, b.is_transposed());
874 /// assert_eq!(a.elems(), b.elems());
875 /// let c = b.transpose();
876 /// assert_eq!(2, c.row_count());
877 /// assert_eq!(3, c.col_count());
878 /// assert_eq!(false, c.is_transposed());
879 /// assert_eq!(a.elems(), c.elems());
880 /// ```
881 pub fn transpose(&self) -> Self
882 {
883 Matrix {
884 row_count: self.col_count,
885 col_count: self.row_count,
886 is_transposed: !self.is_transposed,
887 array: self.array.clone(),
888 }
889 }
890
891 /// See [`transpose`](Self::transpose).
892 pub fn t(&self) -> Self
893 { self.transpose() }
894
895 /// Indeed transposes the matrix
896 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
897 ///
898 /// This method indeed transposes the matrix without changing the transpose flag.
899 ///
900 /// # Examples
901 ///
902 /// ```
903 /// # use unmtx_gpu::*;
904 /// let a = matrix![
905 /// [1.0, 2.0, 3.0],
906 /// [4.0, 5.0, 6.0]
907 /// ];
908 /// let b = a.really_transpose();
909 /// assert_eq!(3, b.row_count());
910 /// assert_eq!(2, b.col_count());
911 /// assert_eq!(false, b.is_transposed());
912 /// assert_eq!(vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0], b.elems());
913 /// ```
914 pub fn really_transpose(&self) -> Self
915 {
916 let frontend = Frontend::new().unwrap();
917 let res = unsafe { frontend.create_matrix(self.col_count, self.row_count) }.unwrap();
918 frontend.really_transpose(self, &res).unwrap();
919 res
920 }
921
922 /// See [`really_transpose`](Self::really_transpose).
923 pub fn rt(&self) -> Self
924 { self.really_transpose() }
925
926 /// Multiplies the matrix elements by the `b` matrix elements
927 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
928 ///
929 /// # Examples
930 ///
931 /// ```
932 /// # use unmtx_gpu::*;
933 /// let a = matrix![
934 /// [1.0, 2.0],
935 /// [3.0, 4.0]
936 /// ];
937 /// let b = matrix![
938 /// [5.0, 6.0],
939 /// [7.0, 8.0]
940 /// ];
941 /// let c = a.mul_elems(&b);
942 /// assert_eq!(vec![1.0 * 5.0, 2.0 * 6.0, 3.0 * 7.0, 4.0 * 8.0], c.elems());
943 /// ```
944 pub fn mul_elems(&self, b: &Self) -> Self
945 {
946 let frontend = Frontend::new().unwrap();
947 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
948 frontend.mul_elems(self, b, &res).unwrap();
949 res
950 }
951
952 /// Divides the matrix elements by the `b` matrix elements
953 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
954 ///
955 /// # Examples
956 ///
957 /// ```
958 /// # use unmtx_gpu::*;
959 /// let a = matrix![
960 /// [1.0, 2.0],
961 /// [3.0, 4.0]
962 /// ];
963 /// let b = matrix![
964 /// [5.0, 6.0],
965 /// [7.0, 8.0]
966 /// ];
967 /// let c = a.div_elems(&b);
968 /// let elems = c.elems();
969 /// assert!((1.0 / 5.0 - elems[0]).abs() < 0.001);
970 /// assert!((2.0 / 6.0 - elems[1]).abs() < 0.001);
971 /// assert!((3.0 / 7.0 - elems[2]).abs() < 0.001);
972 /// assert!((4.0 / 8.0 - elems[3]).abs() < 0.001);
973 /// ```
974 pub fn div_elems(&self, b: &Self) -> Self
975 {
976 let frontend = Frontend::new().unwrap();
977 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
978 frontend.div_elems(self, b, &res).unwrap();
979 res
980 }
981
982 /// Subtracts the matrix from the `b` scalar
983 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>b</mi><mo>-</mo><mi mathvariant="bold">A</mi></mrow></math>).
984 ///
985 /// # Examples
986 ///
987 /// ```
988 /// # use unmtx_gpu::*;
989 /// let a = matrix![
990 /// [1.0, 2.0],
991 /// [3.0, 4.0]
992 /// ];
993 /// let b = a.rsub(10.5);
994 /// assert_eq!(vec![10.5 - 1.0, 10.5 - 2.0, 10.5 - 3.0, 10.5 - 4.0], b.elems());
995 /// ```
996 pub fn rsub(&self, b: f32) -> Self
997 {
998 let frontend = Frontend::new().unwrap();
999 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1000 frontend.rsub_for_scalar(self, b, &res).unwrap();
1001 res
1002 }
1003
1004 /// Divides the `b` scalar by the matrix elements
1005 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
1006 ///
1007 /// # Examples
1008 ///
1009 /// ```
1010 /// # use unmtx_gpu::*;
1011 /// let a = matrix![
1012 /// [1.0, 2.0],
1013 /// [3.0, 4.0]
1014 /// ];
1015 /// let b = a.rdiv(10.5);
1016 /// let elems = b.elems();
1017 /// assert!((10.5 / 1.0 - elems[0]).abs() < 0.001);
1018 /// assert!((10.5 / 2.0 - elems[1]).abs() < 0.001);
1019 /// assert!((10.5 / 3.0 - elems[2]).abs() < 0.001);
1020 /// assert!((10.5 / 4.0 - elems[3]).abs() < 0.001);
1021 /// ```
1022 pub fn rdiv(&self, b: f32) -> Self
1023 {
1024 let frontend = Frontend::new().unwrap();
1025 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1026 frontend.rdiv_for_scalar(self, b, &res).unwrap();
1027 res
1028 }
1029
1030 /// Calculates sigmoid function for the matrix
1031 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>sigmoid</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```
1036 /// # use unmtx_gpu::*;
1037 /// let a = matrix![
1038 /// [1.0, 2.0],
1039 /// [3.0, 4.0]
1040 /// ];
1041 /// let b = a.sigmoid();
1042 /// let elems = b.elems();
1043 /// assert!((1.0 / (1.0 + (-1.0f32).exp()) - elems[0]).abs() < 0.001);
1044 /// assert!((1.0 / (1.0 + (-2.0f32).exp()) - elems[1]).abs() < 0.001);
1045 /// assert!((1.0 / (1.0 + (-3.0f32).exp()) - elems[2]).abs() < 0.001);
1046 /// assert!((1.0 / (1.0 + (-4.0f32).exp()) - elems[3]).abs() < 0.001);
1047 /// ```
1048 pub fn sigmoid(&self) -> Self
1049 {
1050 let frontend = Frontend::new().unwrap();
1051 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1052 frontend.sigmoid(self, &res).unwrap();
1053 res
1054 }
1055
1056 /// Calculates hyperbolic tangent function for the matrix
1057 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>tanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1058 ///
1059 /// # Examples
1060 ///
1061 /// ```
1062 /// # use unmtx_gpu::*;
1063 /// let a = matrix![
1064 /// [1.0, 2.0],
1065 /// [3.0, 4.0]
1066 /// ];
1067 /// let b = a.tanh();
1068 /// let elems = b.elems();
1069 /// assert!((1.0f32.tanh() - elems[0]).abs() < 0.001);
1070 /// assert!((2.0f32.tanh() - elems[1]).abs() < 0.001);
1071 /// assert!((3.0f32.tanh() - elems[2]).abs() < 0.001);
1072 /// assert!((4.0f32.tanh() - elems[3]).abs() < 0.001);
1073 /// ```
1074 pub fn tanh(&self) -> Self
1075 {
1076 let frontend = Frontend::new().unwrap();
1077 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1078 frontend.tanh(self, &res).unwrap();
1079 res
1080 }
1081
1082 /// Calculates swish function for the matrix
1083 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>swish</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1084 ///
1085 /// # Examples
1086 ///
1087 /// ```
1088 /// # use unmtx_gpu::*;
1089 /// let a = matrix![
1090 /// [1.0, 2.0],
1091 /// [3.0, 4.0]
1092 /// ];
1093 /// let b = a.swish();
1094 /// let elems = b.elems();
1095 /// assert!((1.0 / (1.0 + (-1.0f32).exp()) - elems[0]).abs() < 0.001);
1096 /// assert!((2.0 / (1.0 + (-2.0f32).exp()) - elems[1]).abs() < 0.001);
1097 /// assert!((3.0 / (1.0 + (-3.0f32).exp()) - elems[2]).abs() < 0.001);
1098 /// assert!((4.0 / (1.0 + (-4.0f32).exp()) - elems[3]).abs() < 0.001);
1099 /// ```
1100 pub fn swish(&self) -> Self
1101 {
1102 let frontend = Frontend::new().unwrap();
1103 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1104 frontend.swish(self, &res).unwrap();
1105 res
1106 }
1107
1108 /// Calculates softmax function for the matrix
1109 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>softmax</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1110 ///
1111 /// # Examples
1112 ///
1113 /// ```
1114 /// # use unmtx_gpu::*;
1115 /// let a = matrix![
1116 /// [1.0, 2.0],
1117 /// [3.0, 4.0]
1118 /// ];
1119 /// let b = a.softmax();
1120 /// let elems = b.elems();
1121 /// let sum1 = 1.0f32.exp() + 3.0f32.exp();
1122 /// let sum2 = 2.0f32.exp() + 4.0f32.exp();
1123 /// assert!((1.0f32.exp() / sum1 - elems[0]).abs() < 0.001);
1124 /// assert!((2.0f32.exp() / sum2 - elems[1]).abs() < 0.001);
1125 /// assert!((3.0f32.exp() / sum1 - elems[2]).abs() < 0.001);
1126 /// assert!((4.0f32.exp() / sum2 - elems[3]).abs() < 0.001);
1127 /// ```
1128 pub fn softmax(&self) -> Self
1129 {
1130 let frontend = Frontend::new().unwrap();
1131 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1132 frontend.softmax(self, &res).unwrap();
1133 res
1134 }
1135
1136 /// Calculates square roots of the matrix elements
1137 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msqrt><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msqrt></mrow></math>).
1138 ///
1139 /// # Examples
1140 ///
1141 /// ```
1142 /// # use unmtx_gpu::*;
1143 /// let a = matrix![
1144 /// [1.0, 2.0],
1145 /// [3.0, 4.0]
1146 /// ];
1147 /// let b = a.sqrt();
1148 /// let elems = b.elems();
1149 /// assert!((1.0f32.sqrt() - elems[0]).abs() < 0.001);
1150 /// assert!((2.0f32.sqrt() - elems[1]).abs() < 0.001);
1151 /// assert!((3.0f32.sqrt() - elems[2]).abs() < 0.001);
1152 /// assert!((4.0f32.sqrt() - elems[3]).abs() < 0.001);
1153 /// ```
1154 pub fn sqrt(&self) -> Self
1155 {
1156 let frontend = Frontend::new().unwrap();
1157 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1158 frontend.sqrt(self, &res).unwrap();
1159 res
1160 }
1161
1162 /// Repeats the vector as column or a row.
1163 ///
1164 /// # Examples
1165 ///
1166 /// ```
1167 /// # use unmtx_gpu::*;
1168 /// let a = matrix![
1169 /// [1.0],
1170 /// [2.0]
1171 /// ];
1172 /// let b = a.repeat(3);
1173 /// assert_eq!(vec![1.0, 1.0, 1.0, 2.0, 2.0, 2.0], b.elems());
1174 /// let c = matrix![[1.0, 2.0, 3.0]];
1175 /// let d = c.repeat(2);
1176 /// assert_eq!(vec![1.0, 2.0, 3.0, 1.0, 2.0, 3.0], d.elems());
1177 /// ```
1178 pub fn repeat(&self, n: usize) -> Self
1179 {
1180 assert!(self.col_count == 1 || self.row_count == 1);
1181 let frontend = Frontend::new().unwrap();
1182 let res = if self.col_count == 1 {
1183 unsafe { frontend.create_matrix(self.row_count, n) }.unwrap()
1184 } else {
1185 unsafe { frontend.create_matrix(n, self.col_count) }.unwrap()
1186 };
1187 frontend.repeat(self, &res).unwrap();
1188 res
1189 }
1190
1191 /// Calculates absolute values of the matrix elements
1192 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mo fence="true">|</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo fence="true">|</mo></mrow></math>).
1193 ///
1194 /// # Examples
1195 ///
1196 /// ```
1197 /// # use unmtx_gpu::*;
1198 /// let a = matrix![
1199 /// [-2.0, -1.0],
1200 /// [1.0, 2.0]
1201 /// ];
1202 /// let b = a.abs();
1203 /// assert_eq!(vec![2.0, 1.0, 1.0, 2.0], b.elems());
1204 /// ```
1205 pub fn abs(&self) -> Self
1206 {
1207 let frontend = Frontend::new().unwrap();
1208 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1209 frontend.abs(self, &res).unwrap();
1210 res
1211 }
1212
1213 /// Raises the matrix elements to the power of the `b` matrix elements
1214 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
1215 ///
1216 /// # Examples
1217 ///
1218 /// ```
1219 /// # use unmtx_gpu::*;
1220 /// let a = matrix![
1221 /// [1.0, 2.0],
1222 /// [3.0, 4.0]
1223 /// ];
1224 /// let b = matrix![
1225 /// [3.0, 4.0],
1226 /// [5.0, 6.0]
1227 /// ];
1228 /// let c = a.powm(&b);
1229 /// let elems = c.elems();
1230 /// assert!((1.0f32.powf(3.0) - elems[0]).abs() < 0.001);
1231 /// assert!((2.0f32.powf(4.0) - elems[1]).abs() < 0.001);
1232 /// assert!((3.0f32.powf(5.0) - elems[2]).abs() < 0.001);
1233 /// assert!((4.0f32.powf(6.0) - elems[3]).abs() < 0.001);
1234 /// ```
1235 pub fn powm(&self, b: &Self) -> Self
1236 {
1237 let frontend = Frontend::new().unwrap();
1238 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1239 frontend.pow(self, b, &res).unwrap();
1240 res
1241 }
1242
1243 /// Raises the matrix elements to the power of the `b` scalar
1244 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></msup></mrow></math>).
1245 ///
1246 /// # Examples
1247 ///
1248 /// ```
1249 /// # use unmtx_gpu::*;
1250 /// let a = matrix![
1251 /// [1.0, 2.0],
1252 /// [3.0, 4.0]
1253 /// ];
1254 /// let b = a.powf(2.5);
1255 /// let elems = b.elems();
1256 /// assert!((1.0f32.powf(2.5) - elems[0]).abs() < 0.001);
1257 /// assert!((2.0f32.powf(2.5) - elems[1]).abs() < 0.001);
1258 /// assert!((3.0f32.powf(2.5) - elems[2]).abs() < 0.001);
1259 /// assert!((4.0f32.powf(2.5) - elems[3]).abs() < 0.001);
1260 /// ```
1261 pub fn powf(&self, b: f32) -> Self
1262 {
1263 let frontend = Frontend::new().unwrap();
1264 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1265 frontend.pow_for_scalar(self, b, &res).unwrap();
1266 res
1267 }
1268
1269 /// Raises the `b` scalar to the power of the matrix elements
1270 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
1271 ///
1272 /// # Examples
1273 ///
1274 /// ```
1275 /// # use unmtx_gpu::*;
1276 /// let a = matrix![
1277 /// [1.0, 2.0],
1278 /// [3.0, 4.0]
1279 /// ];
1280 /// let b = a.rpowf(10.5);
1281 /// let elems = b.elems();
1282 /// assert!((10.5f32.powf(1.0) - elems[0]).abs() < 0.001);
1283 /// assert!((10.5f32.powf(2.0) - elems[1]).abs() < 0.001);
1284 /// assert!((10.5f32.powf(3.0) - elems[2]).abs() < 0.001);
1285 /// assert!((10.5f32.powf(4.0) - elems[3]).abs() < 0.001);
1286 /// ```
1287 pub fn rpowf(&self, b: f32) -> Self
1288 {
1289 let frontend = Frontend::new().unwrap();
1290 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1291 frontend.rpow_for_scalar(self, b, &res).unwrap();
1292 res
1293 }
1294
1295 /// Calculates exponential function for the matrix elements
1296 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msup><mi>e</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
1297 ///
1298 /// # Examples
1299 ///
1300 /// ```
1301 /// # use unmtx_gpu::*;
1302 /// let a = matrix![
1303 /// [1.0, 2.0],
1304 /// [3.0, 4.0]
1305 /// ];
1306 /// let b = a.exp();
1307 /// let elems = b.elems();
1308 /// assert!((1.0f32.exp() - elems[0]).abs() < 0.001);
1309 /// assert!((2.0f32.exp() - elems[1]).abs() < 0.001);
1310 /// assert!((3.0f32.exp() - elems[2]).abs() < 0.001);
1311 /// assert!((4.0f32.exp() - elems[3]).abs() < 0.001);
1312 /// ```
1313 pub fn exp(&self) -> Self
1314 {
1315 let frontend = Frontend::new().unwrap();
1316 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1317 frontend.exp(self, &res).unwrap();
1318 res
1319 }
1320
1321 /// Calculates natural logarithm of the matrix elements
1322 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>ln</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
1323 ///
1324 /// # Examples
1325 ///
1326 /// ```
1327 /// # use unmtx_gpu::*;
1328 /// let a = matrix![
1329 /// [1.0, 2.0],
1330 /// [3.0, 4.0]
1331 /// ];
1332 /// let b = a.ln();
1333 /// let elems = b.elems();
1334 /// assert!((1.0f32.ln() - elems[0]).abs() < 0.001);
1335 /// assert!((2.0f32.ln() - elems[1]).abs() < 0.001);
1336 /// assert!((3.0f32.ln() - elems[2]).abs() < 0.001);
1337 /// assert!((4.0f32.ln() - elems[3]).abs() < 0.001);
1338 /// ```
1339 pub fn ln(&self) -> Self
1340 {
1341 let frontend = Frontend::new().unwrap();
1342 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1343 frontend.ln(self, &res).unwrap();
1344 res
1345 }
1346
1347 /// Calculates base 2 logarithm of the matrix elements
1348 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>log</mi><mn>2</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
1349 ///
1350 /// # Examples
1351 ///
1352 /// ```
1353 /// # use unmtx_gpu::*;
1354 /// let a = matrix![
1355 /// [1.0, 2.0],
1356 /// [3.0, 4.0]
1357 /// ];
1358 /// let b = a.log2();
1359 /// let elems = b.elems();
1360 /// assert!((1.0f32.log2() - elems[0]).abs() < 0.001);
1361 /// assert!((2.0f32.log2() - elems[1]).abs() < 0.001);
1362 /// assert!((3.0f32.log2() - elems[2]).abs() < 0.001);
1363 /// assert!((4.0f32.log2() - elems[3]).abs() < 0.001);
1364 /// ```
1365 pub fn log2(&self) -> Self
1366 {
1367 let frontend = Frontend::new().unwrap();
1368 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1369 frontend.log2(self, &res).unwrap();
1370 res
1371 }
1372
1373 /// Calculates base 10 logarithm of the matrix elements
1374 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>log</mi><mn>10</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
1375 ///
1376 /// # Examples
1377 ///
1378 /// ```
1379 /// # use unmtx_gpu::*;
1380 /// let a = matrix![
1381 /// [1.0, 2.0],
1382 /// [3.0, 4.0]
1383 /// ];
1384 /// let b = a.log10();
1385 /// let elems = b.elems();
1386 /// assert!((1.0f32.log10() - elems[0]).abs() < 0.001);
1387 /// assert!((2.0f32.log10() - elems[1]).abs() < 0.001);
1388 /// assert!((3.0f32.log10() - elems[2]).abs() < 0.001);
1389 /// assert!((4.0f32.log10() - elems[3]).abs() < 0.001);
1390 /// ```
1391 pub fn log10(&self) -> Self
1392 {
1393 let frontend = Frontend::new().unwrap();
1394 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1395 frontend.log10(self, &res).unwrap();
1396 res
1397 }
1398
1399 /// Calculates sine function for the matrix
1400 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>sin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1401 ///
1402 /// # Examples
1403 ///
1404 /// ```
1405 /// # use unmtx_gpu::*;
1406 /// let a = matrix![
1407 /// [1.0, 2.0],
1408 /// [3.0, 4.0]
1409 /// ];
1410 /// let b = a.sin();
1411 /// let elems = b.elems();
1412 /// assert!((1.0f32.sin() - elems[0]).abs() < 0.001);
1413 /// assert!((2.0f32.sin() - elems[1]).abs() < 0.001);
1414 /// assert!((3.0f32.sin() - elems[2]).abs() < 0.001);
1415 /// assert!((4.0f32.sin() - elems[3]).abs() < 0.001);
1416 /// ```
1417 pub fn sin(&self) -> Self
1418 {
1419 let frontend = Frontend::new().unwrap();
1420 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1421 frontend.sin(self, &res).unwrap();
1422 res
1423 }
1424
1425 /// Calculates cosine function for the matrix
1426 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>cos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1427 ///
1428 /// # Examples
1429 ///
1430 /// ```
1431 /// # use unmtx_gpu::*;
1432 /// let a = matrix![
1433 /// [1.0, 2.0],
1434 /// [3.0, 4.0]
1435 /// ];
1436 /// let b = a.cos();
1437 /// let elems = b.elems();
1438 /// assert!((1.0f32.cos() - elems[0]).abs() < 0.001);
1439 /// assert!((2.0f32.cos() - elems[1]).abs() < 0.001);
1440 /// assert!((3.0f32.cos() - elems[2]).abs() < 0.001);
1441 /// assert!((4.0f32.cos() - elems[3]).abs() < 0.001);
1442 /// ```
1443 pub fn cos(&self) -> Self
1444 {
1445 let frontend = Frontend::new().unwrap();
1446 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1447 frontend.cos(self, &res).unwrap();
1448 res
1449 }
1450
1451 /// Calculates tangent function for the matrix
1452 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>tan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1453 ///
1454 /// # Examples
1455 ///
1456 /// ```
1457 /// # use unmtx_gpu::*;
1458 /// let a = matrix![
1459 /// [1.0, 2.0],
1460 /// [3.0, 4.0]
1461 /// ];
1462 /// let b = a.tan();
1463 /// let elems = b.elems();
1464 /// assert!((1.0f32.tan() - elems[0]).abs() < 0.001);
1465 /// assert!((2.0f32.tan() - elems[1]).abs() < 0.001);
1466 /// assert!((3.0f32.tan() - elems[2]).abs() < 0.001);
1467 /// assert!((4.0f32.tan() - elems[3]).abs() < 0.001);
1468 /// ```
1469 pub fn tan(&self) -> Self
1470 {
1471 let frontend = Frontend::new().unwrap();
1472 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1473 frontend.tan(self, &res).unwrap();
1474 res
1475 }
1476
1477 /// Calculates arcsine function for the matrix
1478 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arcsin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1479 ///
1480 /// # Examples
1481 ///
1482 /// ```
1483 /// # use unmtx_gpu::*;
1484 /// let a = matrix![
1485 /// [0.25, 0.5],
1486 /// [0.75, 1.0]
1487 /// ];
1488 /// let b = a.asin();
1489 /// let elems = b.elems();
1490 /// assert!((0.25f32.asin() - elems[0]).abs() < 0.001);
1491 /// assert!((0.5f32.asin() - elems[1]).abs() < 0.001);
1492 /// assert!((0.75f32.asin() - elems[2]).abs() < 0.001);
1493 /// assert!((1.0f32.asin() - elems[3]).abs() < 0.001);
1494 /// ```
1495 pub fn asin(&self) -> Self
1496 {
1497 let frontend = Frontend::new().unwrap();
1498 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1499 frontend.asin(self, &res).unwrap();
1500 res
1501 }
1502
1503 /// Calculates arccosine function for the matrix
1504 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arccos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1505 ///
1506 /// # Examples
1507 ///
1508 /// ```
1509 /// # use unmtx_gpu::*;
1510 /// let a = matrix![
1511 /// [0.25, 0.5],
1512 /// [0.75, 1.0]
1513 /// ];
1514 /// let b = a.acos();
1515 /// let elems = b.elems();
1516 /// assert!((0.25f32.acos() - elems[0]).abs() < 0.001);
1517 /// assert!((0.5f32.acos() - elems[1]).abs() < 0.001);
1518 /// assert!((0.75f32.acos() - elems[2]).abs() < 0.001);
1519 /// assert!((1.0f32.acos() - elems[3]).abs() < 0.001);
1520 /// ```
1521 pub fn acos(&self) -> Self
1522 {
1523 let frontend = Frontend::new().unwrap();
1524 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1525 frontend.acos(self, &res).unwrap();
1526 res
1527 }
1528
1529 /// Calculates arctangent function for the `a` matrix
1530 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arctan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1531 ///
1532 /// # Examples
1533 ///
1534 /// ```
1535 /// # use unmtx_gpu::*;
1536 /// let a = matrix![
1537 /// [1.0, 2.0],
1538 /// [3.0, 4.0]
1539 /// ];
1540 /// let b = a.atan();
1541 /// let elems = b.elems();
1542 /// assert!((1.0f32.atan() - elems[0]).abs() < 0.001);
1543 /// assert!((2.0f32.atan() - elems[1]).abs() < 0.001);
1544 /// assert!((3.0f32.atan() - elems[2]).abs() < 0.001);
1545 /// assert!((4.0f32.atan() - elems[3]).abs() < 0.001);
1546 /// ```
1547 pub fn atan(&self) -> Self
1548 {
1549 let frontend = Frontend::new().unwrap();
1550 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1551 frontend.atan(self, &res).unwrap();
1552 res
1553 }
1554
1555 /// Calculates arctangent function for the matrix elements and the `b` matrix elements
1556 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
1557 ///
1558 /// # Examples
1559 ///
1560 /// ```
1561 /// # use unmtx_gpu::*;
1562 /// let a = matrix![
1563 /// [1.0, 2.0],
1564 /// [3.0, 4.0]
1565 /// ];
1566 /// let b = matrix![
1567 /// [5.0, 6.0],
1568 /// [7.0, 8.0]
1569 /// ];
1570 /// let c = a.atan2(&b);
1571 /// let elems = c.elems();
1572 /// assert!((1.0f32.atan2(5.0) - elems[0]).abs() < 0.001);
1573 /// assert!((2.0f32.atan2(6.0) - elems[1]).abs() < 0.001);
1574 /// assert!((3.0f32.atan2(7.0) - elems[2]).abs() < 0.001);
1575 /// assert!((4.0f32.atan2(8.0) - elems[3]).abs() < 0.001);
1576 /// ```
1577 pub fn atan2(&self, b: &Self) -> Self
1578 {
1579 let frontend = Frontend::new().unwrap();
1580 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1581 frontend.atan2(self, b, &res).unwrap();
1582 res
1583 }
1584
1585 /// Calculates arctangent function for the matrix elements and the `b` scalar
1586 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></mfrac><mo fence="true">)</mo></mrow></math>).
1587 ///
1588 /// # Examples
1589 ///
1590 /// ```
1591 /// # use unmtx_gpu::*;
1592 /// let a = matrix![
1593 /// [1.0, 2.0],
1594 /// [3.0, 4.0]
1595 /// ];
1596 /// let b = a.atan2f(10.5);
1597 /// let elems = b.elems();
1598 /// assert!((1.0f32.atan2(10.5) - elems[0]).abs() < 0.001);
1599 /// assert!((2.0f32.atan2(10.5) - elems[1]).abs() < 0.001);
1600 /// assert!((3.0f32.atan2(10.5) - elems[2]).abs() < 0.001);
1601 /// assert!((4.0f32.atan2(10.5) - elems[3]).abs() < 0.001);
1602 /// ```
1603 pub fn atan2f(&self, b: f32) -> Self
1604 {
1605 let frontend = Frontend::new().unwrap();
1606 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1607 frontend.atan2_for_scalar(self, b, &res).unwrap();
1608 res
1609 }
1610
1611 /// Calculates arctangent function for the `b` scalar and the matrix elements
1612 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arctan</mi><mo fence="true">(</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
1613 ///
1614 /// # Examples
1615 ///
1616 /// ```
1617 /// # use unmtx_gpu::*;
1618 /// let a = matrix![
1619 /// [1.0, 2.0],
1620 /// [3.0, 4.0]
1621 /// ];
1622 /// let b = a.ratan2f(10.5);
1623 /// let elems = b.elems();
1624 /// assert!((10.5f32.atan2(1.0) - elems[0]).abs() < 0.001);
1625 /// assert!((10.5f32.atan2(2.0) - elems[1]).abs() < 0.001);
1626 /// assert!((10.5f32.atan2(3.0) - elems[2]).abs() < 0.001);
1627 /// assert!((10.5f32.atan2(4.0) - elems[3]).abs() < 0.001);
1628 /// ```
1629 pub fn ratan2f(&self, b: f32) -> Self
1630 {
1631 let frontend = Frontend::new().unwrap();
1632 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1633 frontend.ratan2_for_scalar(self, b, &res).unwrap();
1634 res
1635 }
1636
1637 /// Calculates hyperbolic sine function for the matrix
1638 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>sinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1639 ///
1640 /// # Examples
1641 ///
1642 /// ```
1643 /// # use unmtx_gpu::*;
1644 /// let a = matrix![
1645 /// [1.0, 2.0],
1646 /// [3.0, 4.0]
1647 /// ];
1648 /// let b = a.sinh();
1649 /// let elems = b.elems();
1650 /// assert!((1.0f32.sinh() - elems[0]).abs() < 0.001);
1651 /// assert!((2.0f32.sinh() - elems[1]).abs() < 0.001);
1652 /// assert!((3.0f32.sinh() - elems[2]).abs() < 0.001);
1653 /// assert!((4.0f32.sinh() - elems[3]).abs() < 0.001);
1654 /// ```
1655 pub fn sinh(&self) -> Self
1656 {
1657 let frontend = Frontend::new().unwrap();
1658 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1659 frontend.sinh(self, &res).unwrap();
1660 res
1661 }
1662
1663 /// Calculates hyperbolic cosine function for the matrix
1664 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>cosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1665 ///
1666 /// # Examples
1667 ///
1668 /// ```
1669 /// # use unmtx_gpu::*;
1670 /// let a = matrix![
1671 /// [1.0, 2.0],
1672 /// [3.0, 4.0]
1673 /// ];
1674 /// let b = a.cosh();
1675 /// let elems = b.elems();
1676 /// assert!((1.0f32.cosh() - elems[0]).abs() < 0.001);
1677 /// assert!((2.0f32.cosh() - elems[1]).abs() < 0.001);
1678 /// assert!((3.0f32.cosh() - elems[2]).abs() < 0.001);
1679 /// assert!((4.0f32.cosh() - elems[3]).abs() < 0.001);
1680 /// ```
1681 pub fn cosh(&self) -> Self
1682 {
1683 let frontend = Frontend::new().unwrap();
1684 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1685 frontend.cosh(self, &res).unwrap();
1686 res
1687 }
1688
1689 /// Calculates inverse hyperbolic sine function for the matrix
1690 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arsinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1691 ///
1692 /// # Examples
1693 ///
1694 /// ```
1695 /// # use unmtx_gpu::*;
1696 /// let a = matrix![
1697 /// [1.0, 2.0],
1698 /// [3.0, 4.0]
1699 /// ];
1700 /// let b = a.asinh();
1701 /// let elems = b.elems();
1702 /// assert!((1.0f32.asinh() - elems[0]).abs() < 0.001);
1703 /// assert!((2.0f32.asinh() - elems[1]).abs() < 0.001);
1704 /// assert!((3.0f32.asinh() - elems[2]).abs() < 0.001);
1705 /// assert!((4.0f32.asinh() - elems[3]).abs() < 0.001);
1706 /// ```
1707 pub fn asinh(&self) -> Self
1708 {
1709 let frontend = Frontend::new().unwrap();
1710 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1711 frontend.asinh(self, &res).unwrap();
1712 res
1713 }
1714
1715 /// Calculates inverse hyperbolic cosine function for the matrix
1716 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>arcosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1717 ///
1718 /// # Examples
1719 ///
1720 /// ```
1721 /// # use unmtx_gpu::*;
1722 /// let a = matrix![
1723 /// [1.0, 2.0],
1724 /// [3.0, 4.0]
1725 /// ];
1726 /// let b = a.acosh();
1727 /// let elems = b.elems();
1728 /// assert!((1.0f32.acosh() - elems[0]).abs() < 0.001);
1729 /// assert!((2.0f32.acosh() - elems[1]).abs() < 0.001);
1730 /// assert!((3.0f32.acosh() - elems[2]).abs() < 0.001);
1731 /// assert!((4.0f32.acosh() - elems[3]).abs() < 0.001);
1732 /// ```
1733 pub fn acosh(&self) -> Self
1734 {
1735 let frontend = Frontend::new().unwrap();
1736 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1737 frontend.acosh(self, &res).unwrap();
1738 res
1739 }
1740
1741 /// Calculates inverse hyperbolic tangent function for the matrix
1742 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>artanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1743 ///
1744 /// # Examples
1745 ///
1746 /// ```
1747 /// # use unmtx_gpu::*;
1748 /// let a = matrix![
1749 /// [0.25, 0.5],
1750 /// [0.75, 1.0]
1751 /// ];
1752 /// let b = a.atanh();
1753 /// let elems = b.elems();
1754 /// assert!((0.25f32.atanh() - elems[0]).abs() < 0.001);
1755 /// assert!((0.5f32.atanh() - elems[1]).abs() < 0.001);
1756 /// assert!((0.75f32.atanh() - elems[2]).abs() < 0.001);
1757 /// assert_eq!(f32::INFINITY, elems[3]);
1758 /// ```
1759 pub fn atanh(&self) -> Self
1760 {
1761 let frontend = Frontend::new().unwrap();
1762 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1763 frontend.atanh(self, &res).unwrap();
1764 res
1765 }
1766
1767 /// Calculates signum function for the matrix
1768 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>sgn</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1769 ///
1770 /// # Examples
1771 ///
1772 /// ```
1773 /// # use unmtx_gpu::*;
1774 /// let a = matrix![
1775 /// [-2.0, -1.0],
1776 /// [1.0, 2.0]
1777 /// ];
1778 /// let b = a.signum();
1779 /// assert_eq!(vec![-1.0, -1.0, 1.0, 1.0], b.elems());
1780 /// ```
1781 pub fn signum(&self) -> Self
1782 {
1783 let frontend = Frontend::new().unwrap();
1784 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1785 frontend.signum(self, &res).unwrap();
1786 res
1787 }
1788
1789 /// Calculates ceil function for the matrix
1790 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>ceil</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1791 ///
1792 /// # Examples
1793 ///
1794 /// ```
1795 /// # use unmtx_gpu::*;
1796 /// let a = matrix![
1797 /// [-2.6, -1.3],
1798 /// [1.3, 2.6]
1799 /// ];
1800 /// let b = a.ceil();
1801 /// assert_eq!(vec![-2.0, -1.0, 2.0, 3.0], b.elems());
1802 /// ```
1803 pub fn ceil(&self) -> Self
1804 {
1805 let frontend = Frontend::new().unwrap();
1806 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1807 frontend.ceil(self, &res).unwrap();
1808 res
1809 }
1810
1811 /// Calculates floor function for the matrix
1812 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>floor</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1813 ///
1814 /// # Examples
1815 ///
1816 /// ```
1817 /// # use unmtx_gpu::*;
1818 /// let a = matrix![
1819 /// [-2.6, -1.3],
1820 /// [1.3, 2.6]
1821 /// ];
1822 /// let b = a.floor();
1823 /// assert_eq!(vec![-3.0, -2.0, 1.0, 2.0], b.elems());
1824 /// ```
1825 pub fn floor(&self) -> Self
1826 {
1827 let frontend = Frontend::new().unwrap();
1828 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1829 frontend.floor(self, &res).unwrap();
1830 res
1831 }
1832
1833 /// Calculates round function for the matrix
1834 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>round</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1835 ///
1836 /// # Examples
1837 ///
1838 /// ```
1839 /// # use unmtx_gpu::*;
1840 /// let a = matrix![
1841 /// [-2.6, -1.3],
1842 /// [1.3, 2.6]
1843 /// ];
1844 /// let b = a.round();
1845 /// assert_eq!(vec![-3.0, -1.0, 1.0, 3.0], b.elems());
1846 /// ```
1847 pub fn round(&self) -> Self
1848 {
1849 let frontend = Frontend::new().unwrap();
1850 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1851 frontend.round(self, &res).unwrap();
1852 res
1853 }
1854
1855 /// Calculates trunc function for the matrix
1856 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi>trunc</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
1857 ///
1858 /// # Examples
1859 ///
1860 /// ```
1861 /// # use unmtx_gpu::*;
1862 /// let a = matrix![
1863 /// [-2.6, -1.3],
1864 /// [1.3, 2.6]
1865 /// ];
1866 /// let b = a.trunc();
1867 /// assert_eq!(vec![-2.0, -1.0, 1.0, 2.0], b.elems());
1868 /// ```
1869 pub fn trunc(&self) -> Self
1870 {
1871 let frontend = Frontend::new().unwrap();
1872 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1873 frontend.trunc(self, &res).unwrap();
1874 res
1875 }
1876}
1877
1878impl Neg for Matrix
1879{
1880 type Output = Self;
1881
1882 fn neg(self) -> Self::Output
1883 {
1884 let frontend = Frontend::new().unwrap();
1885 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1886 frontend.rsub_for_scalar(&self, 0.0, &res).unwrap();
1887 res
1888 }
1889}
1890
1891impl Neg for &Matrix
1892{
1893 type Output = Matrix;
1894
1895 fn neg(self) -> Self::Output
1896 {
1897 let frontend = Frontend::new().unwrap();
1898 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1899 frontend.rsub_for_scalar(self, 0.0, &res).unwrap();
1900 res
1901 }
1902}
1903
1904impl Add for Matrix
1905{
1906 type Output = Self;
1907
1908 fn add(self, rhs: Self) -> Self::Output
1909 {
1910 let frontend = Frontend::new().unwrap();
1911 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1912 frontend.add(&self, &rhs, &res).unwrap();
1913 res
1914 }
1915}
1916
1917impl Add<&Matrix> for Matrix
1918{
1919 type Output = Self;
1920
1921 fn add(self, rhs: &Matrix) -> Self::Output
1922 {
1923 let frontend = Frontend::new().unwrap();
1924 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1925 frontend.add(&self, rhs, &res).unwrap();
1926 res
1927 }
1928}
1929
1930impl Add<f32> for Matrix
1931{
1932 type Output = Self;
1933
1934 fn add(self, rhs: f32) -> Self::Output
1935 {
1936 let frontend = Frontend::new().unwrap();
1937 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1938 frontend.add_for_scalar(&self, rhs, &res).unwrap();
1939 res
1940 }
1941}
1942
1943impl Add<&f32> for Matrix
1944{
1945 type Output = Self;
1946
1947 fn add(self, rhs: &f32) -> Self::Output
1948 {
1949 let frontend = Frontend::new().unwrap();
1950 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1951 frontend.add_for_scalar(&self, *rhs, &res).unwrap();
1952 res
1953 }
1954}
1955
1956impl Add<Matrix> for &Matrix
1957{
1958 type Output = Matrix;
1959
1960 fn add(self, rhs: Matrix) -> Self::Output
1961 {
1962 let frontend = Frontend::new().unwrap();
1963 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1964 frontend.add(self, &rhs, &res).unwrap();
1965 res
1966 }
1967}
1968
1969impl Add<&Matrix> for &Matrix
1970{
1971 type Output = Matrix;
1972
1973 fn add(self, rhs: &Matrix) -> Self::Output
1974 {
1975 let frontend = Frontend::new().unwrap();
1976 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1977 frontend.add(self, rhs, &res).unwrap();
1978 res
1979 }
1980}
1981
1982impl Add<f32> for &Matrix
1983{
1984 type Output = Matrix;
1985
1986 fn add(self, rhs: f32) -> Self::Output
1987 {
1988 let frontend = Frontend::new().unwrap();
1989 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
1990 frontend.add_for_scalar(self, rhs, &res).unwrap();
1991 res
1992 }
1993}
1994
1995impl Add<&f32> for &Matrix
1996{
1997 type Output = Matrix;
1998
1999 fn add(self, rhs: &f32) -> Self::Output
2000 {
2001 let frontend = Frontend::new().unwrap();
2002 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2003 frontend.add_for_scalar(self, *rhs, &res).unwrap();
2004 res
2005 }
2006}
2007
2008impl AddAssign for Matrix
2009{
2010 fn add_assign(&mut self, rhs: Self)
2011 {
2012 let frontend = Frontend::new().unwrap();
2013 frontend.add(self, &rhs, &self).unwrap();
2014 }
2015}
2016
2017impl AddAssign<&Matrix> for Matrix
2018{
2019 fn add_assign(&mut self, rhs: &Self)
2020 {
2021 let frontend = Frontend::new().unwrap();
2022 frontend.add(&self, rhs, &self).unwrap();
2023 }
2024}
2025
2026impl AddAssign<f32> for Matrix
2027{
2028 fn add_assign(&mut self, rhs: f32)
2029 {
2030 let frontend = Frontend::new().unwrap();
2031 frontend.add_for_scalar(&self, rhs, &self).unwrap();
2032 }
2033}
2034
2035impl AddAssign<&f32> for Matrix
2036{
2037 fn add_assign(&mut self, rhs: &f32)
2038 {
2039 let frontend = Frontend::new().unwrap();
2040 frontend.add_for_scalar(&self, *rhs, &self).unwrap();
2041 }
2042}
2043
2044impl Sub for Matrix
2045{
2046 type Output = Self;
2047
2048 fn sub(self, rhs: Self) -> Self::Output
2049 {
2050 let frontend = Frontend::new().unwrap();
2051 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2052 frontend.sub(&self, &rhs, &res).unwrap();
2053 res
2054 }
2055}
2056
2057impl Sub<&Matrix> for Matrix
2058{
2059 type Output = Self;
2060
2061 fn sub(self, rhs: &Matrix) -> Self::Output
2062 {
2063 let frontend = Frontend::new().unwrap();
2064 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2065 frontend.sub(&self, rhs, &res).unwrap();
2066 res
2067 }
2068}
2069
2070impl Sub<f32> for Matrix
2071{
2072 type Output = Self;
2073
2074 fn sub(self, rhs: f32) -> Self::Output
2075 {
2076 let frontend = Frontend::new().unwrap();
2077 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2078 frontend.sub_for_scalar(&self, rhs, &res).unwrap();
2079 res
2080 }
2081}
2082
2083impl Sub<&f32> for Matrix
2084{
2085 type Output = Self;
2086
2087 fn sub(self, rhs: &f32) -> Self::Output
2088 {
2089 let frontend = Frontend::new().unwrap();
2090 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2091 frontend.sub_for_scalar(&self, *rhs, &res).unwrap();
2092 res
2093 }
2094}
2095
2096impl Sub<Matrix> for &Matrix
2097{
2098 type Output = Matrix;
2099
2100 fn sub(self, rhs: Matrix) -> Self::Output
2101 {
2102 let frontend = Frontend::new().unwrap();
2103 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2104 frontend.sub(self, &rhs, &res).unwrap();
2105 res
2106 }
2107}
2108
2109impl Sub<&Matrix> for &Matrix
2110{
2111 type Output = Matrix;
2112
2113 fn sub(self, rhs: &Matrix) -> Self::Output
2114 {
2115 let frontend = Frontend::new().unwrap();
2116 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2117 frontend.sub(self, rhs, &res).unwrap();
2118 res
2119 }
2120}
2121
2122impl Sub<f32> for &Matrix
2123{
2124 type Output = Matrix;
2125
2126 fn sub(self, rhs: f32) -> Self::Output
2127 {
2128 let frontend = Frontend::new().unwrap();
2129 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2130 frontend.sub_for_scalar(self, rhs, &res).unwrap();
2131 res
2132 }
2133}
2134
2135impl Sub<&f32> for &Matrix
2136{
2137 type Output = Matrix;
2138
2139 fn sub(self, rhs: &f32) -> Self::Output
2140 {
2141 let frontend = Frontend::new().unwrap();
2142 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2143 frontend.sub_for_scalar(self, *rhs, &res).unwrap();
2144 res
2145 }
2146}
2147
2148impl SubAssign for Matrix
2149{
2150 fn sub_assign(&mut self, rhs: Self)
2151 {
2152 let frontend = Frontend::new().unwrap();
2153 frontend.sub(&self, &rhs, &self).unwrap();
2154 }
2155}
2156
2157impl SubAssign<&Matrix> for Matrix
2158{
2159 fn sub_assign(&mut self, rhs: &Self)
2160 {
2161 let frontend = Frontend::new().unwrap();
2162 frontend.sub(&self, rhs, &self).unwrap();
2163 }
2164}
2165
2166impl SubAssign<f32> for Matrix
2167{
2168 fn sub_assign(&mut self, rhs: f32)
2169 {
2170 let frontend = Frontend::new().unwrap();
2171 frontend.sub_for_scalar(&self, rhs, &self).unwrap();
2172 }
2173}
2174
2175impl SubAssign<&f32> for Matrix
2176{
2177 fn sub_assign(&mut self, rhs: &f32)
2178 {
2179 let frontend = Frontend::new().unwrap();
2180 frontend.sub_for_scalar(&self, *rhs, &self).unwrap();
2181 }
2182}
2183
2184impl Mul for Matrix
2185{
2186 type Output = Self;
2187
2188 fn mul(self, rhs: Self) -> Self::Output
2189 {
2190 let frontend = Frontend::new().unwrap();
2191 let res = if frontend.backend().has_cublas() {
2192 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2193 } else {
2194 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2195 };
2196 frontend.mul(&self, &rhs, &res).unwrap();
2197 res
2198 }
2199}
2200
2201impl Mul<&Matrix> for Matrix
2202{
2203 type Output = Self;
2204
2205 fn mul(self, rhs: &Matrix) -> Self::Output
2206 {
2207 let frontend = Frontend::new().unwrap();
2208 let res = if frontend.backend().has_cublas() {
2209 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2210 } else {
2211 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2212 };
2213 frontend.mul(&self, rhs, &res).unwrap();
2214 res
2215 }
2216}
2217
2218impl Mul<f32> for Matrix
2219{
2220 type Output = Self;
2221
2222 fn mul(self, rhs: f32) -> Self::Output
2223 {
2224 let frontend = Frontend::new().unwrap();
2225 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2226 frontend.mul_for_scalar(&self, rhs, &res).unwrap();
2227 res
2228 }
2229}
2230
2231impl Mul<&f32> for Matrix
2232{
2233 type Output = Self;
2234
2235 fn mul(self, rhs: &f32) -> Self::Output
2236 {
2237 let frontend = Frontend::new().unwrap();
2238 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2239 frontend.mul_for_scalar(&self, *rhs, &res).unwrap();
2240 res
2241 }
2242}
2243
2244impl Mul<Matrix> for &Matrix
2245{
2246 type Output = Matrix;
2247
2248 fn mul(self, rhs: Matrix) -> Self::Output
2249 {
2250 let frontend = Frontend::new().unwrap();
2251 let res = if frontend.backend().has_cublas() {
2252 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2253 } else {
2254 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2255 };
2256 frontend.mul(self, &rhs, &res).unwrap();
2257 res
2258 }
2259}
2260
2261impl Mul<&Matrix> for &Matrix
2262{
2263 type Output = Matrix;
2264
2265 fn mul(self, rhs: &Matrix) -> Self::Output
2266 {
2267 let frontend = Frontend::new().unwrap();
2268 let res = if frontend.backend().has_cublas() {
2269 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2270 } else {
2271 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2272 };
2273 frontend.mul(self, rhs, &res).unwrap();
2274 res
2275 }
2276}
2277
2278impl Mul<f32> for &Matrix
2279{
2280 type Output = Matrix;
2281
2282 fn mul(self, rhs: f32) -> Self::Output
2283 {
2284 let frontend = Frontend::new().unwrap();
2285 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2286 frontend.mul_for_scalar(self, rhs, &res).unwrap();
2287 res
2288 }
2289}
2290
2291impl Mul<&f32> for &Matrix
2292{
2293 type Output = Matrix;
2294
2295 fn mul(self, rhs: &f32) -> Self::Output
2296 {
2297 let frontend = Frontend::new().unwrap();
2298 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2299 frontend.mul_for_scalar(self, *rhs, &res).unwrap();
2300 res
2301 }
2302}
2303
2304impl MulAssign for Matrix
2305{
2306 fn mul_assign(&mut self, rhs: Self)
2307 {
2308 let frontend = Frontend::new().unwrap();
2309 let res = if frontend.backend().has_cublas() {
2310 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2311 } else {
2312 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2313 };
2314 frontend.mul(&self, &rhs, &res).unwrap();
2315 *self = res;
2316 }
2317}
2318
2319impl MulAssign<&Matrix> for Matrix
2320{
2321 fn mul_assign(&mut self, rhs: &Self)
2322 {
2323 let frontend = Frontend::new().unwrap();
2324 let res = if frontend.backend().has_cublas() {
2325 frontend.create_matrix_and_set_zeros(self.row_count, rhs.col_count).unwrap()
2326 } else {
2327 unsafe { frontend.create_matrix(self.row_count, rhs.col_count) }.unwrap()
2328 };
2329 frontend.mul(&self, rhs, &res).unwrap();
2330 *self = res;
2331 }
2332}
2333
2334impl MulAssign<f32> for Matrix
2335{
2336 fn mul_assign(&mut self, rhs: f32)
2337 {
2338 let frontend = Frontend::new().unwrap();
2339 frontend.mul_for_scalar(&self, rhs, &self).unwrap();
2340 }
2341}
2342
2343impl MulAssign<&f32> for Matrix
2344{
2345 fn mul_assign(&mut self, rhs: &f32)
2346 {
2347 let frontend = Frontend::new().unwrap();
2348 frontend.mul_for_scalar(&self, *rhs, &self).unwrap();
2349 }
2350}
2351
2352impl Div<f32> for Matrix
2353{
2354 type Output = Self;
2355
2356 fn div(self, rhs: f32) -> Self::Output
2357 {
2358 let frontend = Frontend::new().unwrap();
2359 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2360 frontend.div_for_scalar(&self, rhs, &res).unwrap();
2361 res
2362 }
2363}
2364
2365impl Div<&f32> for Matrix
2366{
2367 type Output = Self;
2368
2369 fn div(self, rhs: &f32) -> Self::Output
2370 {
2371 let frontend = Frontend::new().unwrap();
2372 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2373 frontend.div_for_scalar(&self, *rhs, &res).unwrap();
2374 res
2375 }
2376}
2377
2378impl Div<f32> for &Matrix
2379{
2380 type Output = Matrix;
2381
2382 fn div(self, rhs: f32) -> Self::Output
2383 {
2384 let frontend = Frontend::new().unwrap();
2385 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2386 frontend.div_for_scalar(self, rhs, &res).unwrap();
2387 res
2388 }
2389}
2390
2391impl Div<&f32> for &Matrix
2392{
2393 type Output = Matrix;
2394
2395 fn div(self, rhs: &f32) -> Self::Output
2396 {
2397 let frontend = Frontend::new().unwrap();
2398 let res = unsafe { frontend.create_matrix(self.row_count, self.col_count) }.unwrap();
2399 frontend.div_for_scalar(self, *rhs, &res).unwrap();
2400 res
2401 }
2402}
2403
2404impl DivAssign<f32> for Matrix
2405{
2406 fn div_assign(&mut self, rhs: f32)
2407 {
2408 initialize_default_backend_for_uninitialized().unwrap();
2409 let frontend = Frontend::new().unwrap();
2410 frontend.div_for_scalar(&self, rhs, &self).unwrap();
2411 }
2412}
2413
2414impl DivAssign<&f32> for Matrix
2415{
2416 fn div_assign(&mut self, rhs: &f32)
2417 {
2418 initialize_default_backend_for_uninitialized().unwrap();
2419 let frontend = Frontend::new().unwrap();
2420 frontend.div_for_scalar(&self, *rhs, &self).unwrap();
2421 }
2422}
2423
2424/// A frontend structure.
2425///
2426/// The frontend contains methods which operate on matrices or calculate functions for the
2427/// matrices. Backend methods are called by the frontend to operate the matrices. The frontend is
2428/// high-level layer that can be directly used by programmer or a [`Matrix`] structure.
2429pub struct Frontend
2430{
2431 backend: Arc<dyn Backend + Send + Sync>,
2432}
2433
2434impl Frontend
2435{
2436 /// Creates a frontend with a default backend.
2437 ///
2438 /// This method also automatically initializes a default backend if the default backend is
2439 /// uninitialized.
2440 pub fn new() -> Result<Frontend>
2441 { Ok(Frontend { backend: initialize_default_backend_for_uninitialized()?, }) }
2442
2443 /// Creates a frotend with the backend.
2444 pub fn new_with_backend(backend: Arc<dyn Backend + Send + Sync>) -> Frontend
2445 { Frontend { backend, } }
2446
2447 /// Returns the backend.
2448 pub fn backend(&self) -> Arc<dyn Backend + Send + Sync>
2449 { self.backend.clone() }
2450
2451 /// Creates a matrix with unset elements.
2452 pub unsafe fn create_matrix(&self, row_count: usize, col_count: usize) -> Result<Matrix>
2453 {
2454 Ok(Matrix {
2455 row_count,
2456 col_count,
2457 is_transposed: false,
2458 array: Arc::new(self.backend.alloc(row_count * col_count)?),
2459 })
2460 }
2461
2462 /// Creates a matrix and sets the matrix elements on zeros.
2463 pub fn create_matrix_and_set_zeros(&self, row_count: usize, col_count: usize) -> Result<Matrix>
2464 {
2465 Ok(Matrix {
2466 row_count,
2467 col_count,
2468 is_transposed: false,
2469 array: Arc::new(self.backend.alloc_and_store_zeros(row_count * col_count)?),
2470 })
2471 }
2472
2473 /// Creates a matrix and sets the matrix elements.
2474 pub fn create_matrix_and_set_elems(&self, row_count: usize, col_count: usize, elems: &[f32]) -> Result<Matrix>
2475 {
2476 if row_count * col_count != elems.len() {
2477 return Err(Error::MatrixElemCount(row_count * col_count, elems.len()));
2478 }
2479 Ok(Matrix {
2480 row_count,
2481 col_count,
2482 is_transposed: false,
2483 array: Arc::new(self.backend.alloc_and_store(elems)?),
2484 })
2485 }
2486
2487 /// Sets the matrix elements.
2488 pub fn set_elems(&self, a: &Matrix, elems: &[f32]) -> Result<()>
2489 {
2490 if a.row_count() * a.col_count() != elems.len() {
2491 return Err(Error::MatrixElemCount(a.row_count() * a.col_count(), elems.len()));
2492 }
2493 self.backend.store(&*a.array, elems)
2494 }
2495
2496 /// Copies the `a` matrix to the `b` matrix.
2497 ///
2498 /// This method indeed copies the `a` matrix array to the `b` matrix array.
2499 pub fn copy(&self, a: &Matrix, b: &Matrix) -> Result<()>
2500 {
2501 if a.row_count != b.row_count || a.col_count != b.col_count {
2502 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2503 }
2504 self.backend.copy(&*a.array, &*b.array)
2505 }
2506
2507 /// Copies the matrix elements to the mutable slice and the transpose flag to the object that
2508 /// is referred by the reference.
2509 pub fn get_elems_and_transpose_flag(&self, a: &Matrix, elems: &mut [f32], is_transposed: &mut bool) -> Result<()>
2510 {
2511 if a.row_count * a.col_count != elems.len() {
2512 return Err(Error::MatrixElemCount(a.row_count * a.col_count, elems.len()));
2513 }
2514 self.backend.load(&*a.array, elems)?;
2515 *is_transposed = a.is_transposed;
2516 Ok(())
2517 }
2518
2519 /// Returns the elements and the transpose flag of matrix.
2520 pub fn elems_and_transpose_flag(&self, a: &Matrix) -> Result<(Vec<f32>, bool)>
2521 {
2522 let mut elems: Vec<f32> = vec![0.0; a.row_count * a.col_count];
2523 let mut is_transposed = false;
2524 self.get_elems_and_transpose_flag(a, elems.as_mut_slice(), &mut is_transposed)?;
2525 Ok((elems, is_transposed))
2526 }
2527
2528 /// Adds the `b` matrix to the `a` matrix and then the result is in the `c` matrix
2529 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>+</mo><mi mathvariant="bold">B</mi></mrow></math>).
2530 ///
2531 /// # Examples
2532 ///
2533 /// ```
2534 /// # use unmtx_gpu::*;
2535 /// let a = matrix![
2536 /// [1.0, 2.0],
2537 /// [3.0, 4.0]
2538 /// ];
2539 /// let b = matrix![
2540 /// [5.0, 6.0],
2541 /// [7.0, 8.0]
2542 /// ];
2543 /// let c = Matrix::new(2, 2);
2544 /// let frontend = Frontend::new().unwrap();
2545 /// frontend.add(&a, &b, &c).unwrap();
2546 /// assert_eq!(vec![1.0 + 5.0, 2.0 + 6.0, 3.0 + 7.0, 4.0 + 8.0], c.elems());
2547 /// ```
2548 pub fn add(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
2549 {
2550 if a.row_count != b.row_count || a.col_count != b.col_count {
2551 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2552 }
2553 if a.row_count != c.row_count || a.col_count != c.col_count {
2554 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2555 }
2556 if c.is_transposed {
2557 return Err(Error::ResTransposition);
2558 }
2559 match (a.is_transposed, b.is_transposed) {
2560 (false, false) => self.backend.add_a_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2561 (true, false) => self.backend.add_at_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2562 (false, true) => self.backend.add_a_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2563 (true, true) => self.backend.add_at_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2564 }
2565 }
2566
2567 /// Subtracts the `b` matrix from the `a` matrix and then the result is in the `c` matrix
2568 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>-</mo><mi mathvariant="bold">B</mi></mrow></math>).
2569 ///
2570 /// # Examples
2571 ///
2572 /// ```
2573 /// # use unmtx_gpu::*;
2574 /// let a = matrix![
2575 /// [1.0, 2.0],
2576 /// [3.0, 4.0]
2577 /// ];
2578 /// let b = matrix![
2579 /// [5.0, 6.0],
2580 /// [7.0, 8.0]
2581 /// ];
2582 /// let c = Matrix::new(2, 2);
2583 /// let frontend = Frontend::new().unwrap();
2584 /// frontend.sub(&a, &b, &c).unwrap();
2585 /// assert_eq!(vec![1.0 - 5.0, 2.0 - 6.0, 3.0 - 7.0, 4.0 - 8.0], c.elems());
2586 /// ```
2587 pub fn sub(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
2588 {
2589 if a.row_count != b.row_count || a.col_count != b.col_count {
2590 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2591 }
2592 if a.row_count != c.row_count || a.col_count != c.col_count {
2593 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2594 }
2595 if c.is_transposed {
2596 return Err(Error::ResTransposition);
2597 }
2598 match (a.is_transposed, b.is_transposed) {
2599 (false, false) => self.backend.sub_a_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2600 (true, false) => self.backend.sub_at_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2601 (false, true) => self.backend.sub_a_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2602 (true, true) => self.backend.sub_at_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2603 }
2604 }
2605
2606 /// Multiplies the `a` matrix by the `b` matrix and then the result is in the `c` matrix
2607 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>·</mo><mi mathvariant="bold">B</mi></mrow></math>).
2608 ///
2609 /// # Examples
2610 ///
2611 /// ```
2612 /// # use unmtx_gpu::*;
2613 /// let a = matrix![
2614 /// [1.0, 2.0, 3.0],
2615 /// [4.0, 5.0, 6.0]
2616 /// ];
2617 /// let b = matrix![
2618 /// [7.0, 8.0],
2619 /// [9.0, 10.0],
2620 /// [11.0, 12.0]
2621 /// ];
2622 /// let c = Matrix::new(2, 2);
2623 /// let frontend = Frontend::new().unwrap();
2624 /// frontend.mul(&a, &b, &c).unwrap();
2625 /// let c11: f32 = 1.0 * 7.0 + 2.0 * 9.0 + 3.0 * 11.0;
2626 /// let c12: f32 = 1.0 * 8.0 + 2.0 * 10.0 + 3.0 * 12.0;
2627 /// let c21: f32 = 4.0 * 7.0 + 5.0 * 9.0 + 6.0 * 11.0;
2628 /// let c22: f32 = 4.0 * 8.0 + 5.0 * 10.0 + 6.0 * 12.0;
2629 /// assert_eq!(vec![c11, c12, c21, c22], c.elems());
2630 /// ```
2631 pub fn mul(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
2632 {
2633 if a.row_count != c.row_count {
2634 return Err(Error::MulSize(a.row_count, a.col_count, b.row_count, b.col_count, c.row_count, c.col_count));
2635 }
2636 if b.col_count != c.col_count {
2637 return Err(Error::MulSize(a.row_count, a.col_count, b.row_count, b.col_count, c.row_count, c.col_count));
2638 }
2639 if a.col_count != b.row_count {
2640 return Err(Error::MulSize(a.row_count, a.col_count, b.row_count, b.col_count, c.row_count, c.col_count));
2641 }
2642 if c.is_transposed {
2643 return Err(Error::ResTransposition);
2644 }
2645 match (a.is_transposed, b.is_transposed) {
2646 (false, false) => self.backend.mul_a_b(&*a.array, &*b.array, &*c.array, a.row_count, b.col_count, a.col_count),
2647 (true, false) => self.backend.mul_at_b(&*a.array, &*b.array, &*c.array, a.row_count, b.col_count, a.col_count),
2648 (false, true) => self.backend.mul_a_bt(&*a.array, &*b.array, &*c.array, a.row_count, b.col_count, a.col_count),
2649 (true, true) => self.backend.mul_at_bt(&*a.array, &*b.array, &*c.array, a.row_count, b.col_count, a.col_count),
2650 }
2651 }
2652
2653 /// Multiplies the `a` matrix elements by the `b` matrix elements and then the result is in
2654 /// the `c` matrix
2655 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>·</mo><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
2656 ///
2657 /// # Examples
2658 ///
2659 /// ```
2660 /// # use unmtx_gpu::*;
2661 /// let a = matrix![
2662 /// [1.0, 2.0],
2663 /// [3.0, 4.0]
2664 /// ];
2665 /// let b = matrix![
2666 /// [5.0, 6.0],
2667 /// [7.0, 8.0]
2668 /// ];
2669 /// let c = Matrix::new(2, 2);
2670 /// let frontend = Frontend::new().unwrap();
2671 /// frontend.mul_elems(&a, &b, &c).unwrap();
2672 /// assert_eq!(vec![1.0 * 5.0, 2.0 * 6.0, 3.0 * 7.0, 4.0 * 8.0], c.elems());
2673 /// ```
2674 pub fn mul_elems(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
2675 {
2676 if a.row_count != b.row_count || a.col_count != b.col_count {
2677 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2678 }
2679 if a.row_count != c.row_count || a.col_count != c.col_count {
2680 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2681 }
2682 if c.is_transposed {
2683 return Err(Error::ResTransposition);
2684 }
2685 match (a.is_transposed, b.is_transposed) {
2686 (false, false) => self.backend.mul_a_b_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2687 (true, false) => self.backend.mul_at_b_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2688 (false, true) => self.backend.mul_a_bt_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2689 (true, true) => self.backend.mul_at_bt_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2690 }
2691 }
2692
2693 /// Divides the `a` matrix elements by the `b` matrix elements and then the result is in the
2694 /// `c` matrix
2695 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
2696 ///
2697 /// # Examples
2698 ///
2699 /// ```
2700 /// # use unmtx_gpu::*;
2701 /// let a = matrix![
2702 /// [1.0, 2.0],
2703 /// [3.0, 4.0]
2704 /// ];
2705 /// let b = matrix![
2706 /// [5.0, 6.0],
2707 /// [7.0, 8.0]
2708 /// ];
2709 /// let c = Matrix::new(2, 2);
2710 /// let frontend = Frontend::new().unwrap();
2711 /// frontend.div_elems(&a, &b, &c).unwrap();
2712 /// let elems = c.elems();
2713 /// assert!((1.0 / 5.0 - elems[0]).abs() < 0.001);
2714 /// assert!((2.0 / 6.0 - elems[1]).abs() < 0.001);
2715 /// assert!((3.0 / 7.0 - elems[2]).abs() < 0.001);
2716 /// assert!((4.0 / 8.0 - elems[3]).abs() < 0.001);
2717 /// ```
2718 pub fn div_elems(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
2719 {
2720 if a.row_count != b.row_count || a.col_count != b.col_count {
2721 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2722 }
2723 if a.row_count != c.row_count || a.col_count != c.col_count {
2724 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2725 }
2726 if c.is_transposed {
2727 return Err(Error::ResTransposition);
2728 }
2729 match (a.is_transposed, b.is_transposed) {
2730 (false, false) => self.backend.div_a_b_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2731 (true, false) => self.backend.div_at_b_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2732 (false, true) => self.backend.div_a_bt_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2733 (true, true) => self.backend.div_at_bt_for_elems(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
2734 }
2735 }
2736
2737 /// Adds the `b` scalar to the `a` matrix and then the result is in the `c` matrix
2738 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>+</mo><mi>b</mi></mrow></math>).
2739 ///
2740 /// # Examples
2741 ///
2742 /// ```
2743 /// # use unmtx_gpu::*;
2744 /// let a = matrix![
2745 /// [1.0, 2.0],
2746 /// [3.0, 4.0]
2747 /// ];
2748 /// let c = Matrix::new(2, 2);
2749 /// let frontend = Frontend::new().unwrap();
2750 /// frontend.add_for_scalar(&a, 10.5, &c).unwrap();
2751 /// assert_eq!(vec![1.0 + 10.5, 2.0 + 10.5, 3.0 + 10.5, 4.0 + 10.5], c.elems());
2752 /// ```
2753 pub fn add_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2754 {
2755 if a.row_count != c.row_count || a.col_count != c.col_count {
2756 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2757 }
2758 if c.is_transposed {
2759 return Err(Error::ResTransposition);
2760 }
2761 if !a.is_transposed {
2762 self.backend.add_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2763 } else {
2764 self.backend.add_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2765 }
2766 }
2767
2768 /// Subtracts the `b` scalar from the `a` matrix and then the result is in the `c` matrix
2769 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>-</mo><mi>b</mi></mrow></math>).
2770 ///
2771 /// # Examples
2772 ///
2773 /// ```
2774 /// # use unmtx_gpu::*;
2775 /// let a = matrix![
2776 /// [1.0, 2.0],
2777 /// [3.0, 4.0]
2778 /// ];
2779 /// let c = Matrix::new(2, 2);
2780 /// let frontend = Frontend::new().unwrap();
2781 /// frontend.sub_for_scalar(&a, 10.5, &c).unwrap();
2782 /// assert_eq!(vec![1.0 - 10.5, 2.0 - 10.5, 3.0 - 10.5, 4.0 - 10.5], c.elems());
2783 /// ```
2784 pub fn sub_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2785 {
2786 if a.row_count != c.row_count || a.col_count != c.col_count {
2787 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2788 }
2789 if c.is_transposed {
2790 return Err(Error::ResTransposition);
2791 }
2792 if !a.is_transposed {
2793 self.backend.sub_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2794 } else {
2795 self.backend.sub_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2796 }
2797 }
2798
2799 /// Subtracts the `a` matrix from the `b` scalar and then the result is in the `c` matrix
2800 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi>b</mi><mo>-</mo><mi mathvariant="bold">A</mi></mrow></math>).
2801 ///
2802 /// # Examples
2803 ///
2804 /// ```
2805 /// # use unmtx_gpu::*;
2806 /// let a = matrix![
2807 /// [1.0, 2.0],
2808 /// [3.0, 4.0]
2809 /// ];
2810 /// let c = Matrix::new(2, 2);
2811 /// let frontend = Frontend::new().unwrap();
2812 /// frontend.rsub_for_scalar(&a, 10.5, &c).unwrap();
2813 /// assert_eq!(vec![10.5 - 1.0, 10.5 - 2.0, 10.5 - 3.0, 10.5 - 4.0], c.elems());
2814 /// ```
2815 pub fn rsub_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2816 {
2817 if a.row_count != c.row_count || a.col_count != c.col_count {
2818 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2819 }
2820 if c.is_transposed {
2821 return Err(Error::ResTransposition);
2822 }
2823 if !a.is_transposed {
2824 self.backend.rsub_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2825 } else {
2826 self.backend.rsub_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2827 }
2828 }
2829
2830 /// Multiplies the `a` matrix by the `b` scalar and then the result is in the `c` matrix
2831 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mi mathvariant="bold">A</mi><mo>·</mo><mi>b</mi></mrow></math>).
2832 ///
2833 /// # Examples
2834 ///
2835 /// ```
2836 /// # use unmtx_gpu::*;
2837 /// let a = matrix![
2838 /// [1.0, 2.0],
2839 /// [3.0, 4.0]
2840 /// ];
2841 /// let c = Matrix::new(2, 2);
2842 /// let frontend = Frontend::new().unwrap();
2843 /// frontend.mul_for_scalar(&a, 10.5, &c).unwrap();
2844 /// assert_eq!(vec![1.0 * 10.5, 2.0 * 10.5, 3.0 * 10.5, 4.0 * 10.5], c.elems());
2845 /// ```
2846 pub fn mul_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2847 {
2848 if a.row_count != c.row_count || a.col_count != c.col_count {
2849 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2850 }
2851 if c.is_transposed {
2852 return Err(Error::ResTransposition);
2853 }
2854 if !a.is_transposed {
2855 self.backend.mul_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2856 } else {
2857 self.backend.mul_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2858 }
2859 }
2860
2861 /// Divides the `a` matrix by the `b` scalar and then the result is in the `c` matrix
2862 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">C</mi><mo>=</mo><mfrac><mi mathvariant="bold">A</mi><mi>b</mi></mfrac></mrow></math>).
2863 ///
2864 /// # Examples
2865 ///
2866 /// ```
2867 /// # use unmtx_gpu::*;
2868 /// let a = matrix![
2869 /// [1.0, 2.0],
2870 /// [3.0, 4.0]
2871 /// ];
2872 /// let c = Matrix::new(2, 2);
2873 /// let frontend = Frontend::new().unwrap();
2874 /// frontend.div_for_scalar(&a, 10.5, &c).unwrap();
2875 /// let elems = c.elems();
2876 /// assert!((1.0 / 10.5 - elems[0]).abs() < 0.001);
2877 /// assert!((2.0 / 10.5 - elems[1]).abs() < 0.001);
2878 /// assert!((3.0 / 10.5 - elems[2]).abs() < 0.001);
2879 /// assert!((4.0 / 10.5 - elems[3]).abs() < 0.001);
2880 /// ```
2881 pub fn div_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2882 {
2883 if a.row_count != c.row_count || a.col_count != c.col_count {
2884 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2885 }
2886 if c.is_transposed {
2887 return Err(Error::ResTransposition);
2888 }
2889 if !a.is_transposed {
2890 self.backend.div_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2891 } else {
2892 self.backend.div_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2893 }
2894 }
2895
2896 /// Divides the `b` scalar by the `a` matrix elements and then the result is in the `c` matrix
2897 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac></mrow></math>).
2898 ///
2899 /// # Examples
2900 ///
2901 /// ```
2902 /// # use unmtx_gpu::*;
2903 /// let a = matrix![
2904 /// [1.0, 2.0],
2905 /// [3.0, 4.0]
2906 /// ];
2907 /// let c = Matrix::new(2, 2);
2908 /// let frontend = Frontend::new().unwrap();
2909 /// frontend.rdiv_for_scalar(&a, 10.5, &c).unwrap();
2910 /// let elems = c.elems();
2911 /// assert!((10.5 / 1.0- elems[0]).abs() < 0.001);
2912 /// assert!((10.5 / 2.0 - elems[1]).abs() < 0.001);
2913 /// assert!((10.5 / 3.0 - elems[2]).abs() < 0.001);
2914 /// assert!((10.5 / 4.0 - elems[3]).abs() < 0.001);
2915 /// ```
2916 pub fn rdiv_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
2917 {
2918 if a.row_count != c.row_count || a.col_count != c.col_count {
2919 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
2920 }
2921 if c.is_transposed {
2922 return Err(Error::ResTransposition);
2923 }
2924 if !a.is_transposed {
2925 self.backend.rdiv_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2926 } else {
2927 self.backend.rdiv_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
2928 }
2929 }
2930
2931 /// Calculates sigmoid function for the `a` matrix and then the result is in the `b` matrix
2932 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sigmoid</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
2933 ///
2934 /// # Examples
2935 ///
2936 /// ```
2937 /// # use unmtx_gpu::*;
2938 /// let a = matrix![
2939 /// [1.0, 2.0],
2940 /// [3.0, 4.0]
2941 /// ];
2942 /// let b = Matrix::new(2, 2);
2943 /// let frontend = Frontend::new().unwrap();
2944 /// frontend.sigmoid(&a, &b).unwrap();
2945 /// let elems = b.elems();
2946 /// assert!((1.0 / (1.0 + (-1.0f32).exp()) - elems[0]).abs() < 0.001);
2947 /// assert!((1.0 / (1.0 + (-2.0f32).exp()) - elems[1]).abs() < 0.001);
2948 /// assert!((1.0 / (1.0 + (-3.0f32).exp()) - elems[2]).abs() < 0.001);
2949 /// assert!((1.0 / (1.0 + (-4.0f32).exp()) - elems[3]).abs() < 0.001);
2950 /// ```
2951 pub fn sigmoid(&self, a: &Matrix, b: &Matrix) -> Result<()>
2952 {
2953 if a.row_count != b.row_count || a.col_count != b.col_count {
2954 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2955 }
2956 if b.is_transposed {
2957 return Err(Error::ResTransposition);
2958 }
2959 if !a.is_transposed {
2960 self.backend.sigmoid_a(&*a.array, &*b.array, a.row_count, a.col_count)
2961 } else {
2962 self.backend.sigmoid_at(&*a.array, &*b.array, a.row_count, a.col_count)
2963 }
2964 }
2965
2966 /// Calculates hyperbolic tangent function for the `a` matrix and then the result is in the
2967 /// `b` matrix
2968 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
2969 ///
2970 /// # Examples
2971 ///
2972 /// ```
2973 /// # use unmtx_gpu::*;
2974 /// let a = matrix![
2975 /// [1.0, 2.0],
2976 /// [3.0, 4.0]
2977 /// ];
2978 /// let b = Matrix::new(2, 2);
2979 /// let frontend = Frontend::new().unwrap();
2980 /// frontend.tanh(&a, &b).unwrap();
2981 /// let elems = b.elems();
2982 /// assert!((1.0f32.tanh() - elems[0]).abs() < 0.001);
2983 /// assert!((2.0f32.tanh() - elems[1]).abs() < 0.001);
2984 /// assert!((3.0f32.tanh() - elems[2]).abs() < 0.001);
2985 /// assert!((4.0f32.tanh() - elems[3]).abs() < 0.001);
2986 /// ```
2987 pub fn tanh(&self, a: &Matrix, b: &Matrix) -> Result<()>
2988 {
2989 if a.row_count != b.row_count || a.col_count != b.col_count {
2990 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
2991 }
2992 if b.is_transposed {
2993 return Err(Error::ResTransposition);
2994 }
2995 if !a.is_transposed {
2996 self.backend.tanh_a(&*a.array, &*b.array, a.row_count, a.col_count)
2997 } else {
2998 self.backend.tanh_at(&*a.array, &*b.array, a.row_count, a.col_count)
2999 }
3000 }
3001
3002 /// Calculates swish function for the `a` matrix and then the result is in the `b` matrix
3003 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>swish</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3004 ///
3005 /// # Examples
3006 ///
3007 /// ```
3008 /// # use unmtx_gpu::*;
3009 /// let a = matrix![
3010 /// [1.0, 2.0],
3011 /// [3.0, 4.0]
3012 /// ];
3013 /// let b = Matrix::new(2, 2);
3014 /// let frontend = Frontend::new().unwrap();
3015 /// frontend.swish(&a, &b).unwrap();
3016 /// let elems = b.elems();
3017 /// assert!((1.0 / (1.0 + (-1.0f32).exp()) - elems[0]).abs() < 0.001);
3018 /// assert!((2.0 / (1.0 + (-2.0f32).exp()) - elems[1]).abs() < 0.001);
3019 /// assert!((3.0 / (1.0 + (-3.0f32).exp()) - elems[2]).abs() < 0.001);
3020 /// assert!((4.0 / (1.0 + (-4.0f32).exp()) - elems[3]).abs() < 0.001);
3021 /// ```
3022 pub fn swish(&self, a: &Matrix, b: &Matrix) -> Result<()>
3023 {
3024 if a.row_count != b.row_count || a.col_count != b.col_count {
3025 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3026 }
3027 if b.is_transposed {
3028 return Err(Error::ResTransposition);
3029 }
3030 if !a.is_transposed {
3031 self.backend.swish_a(&*a.array, &*b.array, a.row_count, a.col_count)
3032 } else {
3033 self.backend.swish_at(&*a.array, &*b.array, a.row_count, a.col_count)
3034 }
3035 }
3036
3037 /// Calculates softmax function for the `a` matrix and then the result is in the `b` matrix
3038 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>softmax</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3039 ///
3040 /// # Examples
3041 ///
3042 /// ```
3043 /// # use unmtx_gpu::*;
3044 /// let a = matrix![
3045 /// [1.0, 2.0],
3046 /// [3.0, 4.0]
3047 /// ];
3048 /// let b = Matrix::new(2, 2);
3049 /// let frontend = Frontend::new().unwrap();
3050 /// frontend.softmax(&a, &b).unwrap();
3051 /// let elems = b.elems();
3052 /// let sum1 = 1.0f32.exp() + 3.0f32.exp();
3053 /// let sum2 = 2.0f32.exp() + 4.0f32.exp();
3054 /// assert!((1.0f32.exp() / sum1 - elems[0]).abs() < 0.001);
3055 /// assert!((2.0f32.exp() / sum2 - elems[1]).abs() < 0.001);
3056 /// assert!((3.0f32.exp() / sum1 - elems[2]).abs() < 0.001);
3057 /// assert!((4.0f32.exp() / sum2 - elems[3]).abs() < 0.001);
3058 /// ```
3059 pub fn softmax(&self, a: &Matrix, b: &Matrix) -> Result<()>
3060 {
3061 if a.row_count != b.row_count || a.col_count != b.col_count {
3062 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3063 }
3064 if b.is_transposed {
3065 return Err(Error::ResTransposition);
3066 }
3067 if !a.is_transposed {
3068 self.backend.softmax_a(&*a.array, &*b.array, a.row_count, a.col_count)
3069 } else {
3070 self.backend.softmax_at(&*a.array, &*b.array, a.row_count, a.col_count)
3071 }
3072 }
3073
3074 /// Calculates square roots of the `a` matrix elements and then the result is in the `b`
3075 /// matrix
3076 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msqrt><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msqrt></mrow></math>).
3077 ///
3078 /// # Examples
3079 ///
3080 /// ```
3081 /// # use unmtx_gpu::*;
3082 /// let a = matrix![
3083 /// [1.0, 2.0],
3084 /// [3.0, 4.0]
3085 /// ];
3086 /// let b = Matrix::new(2, 2);
3087 /// let frontend = Frontend::new().unwrap();
3088 /// frontend.sqrt(&a, &b).unwrap();
3089 /// let elems = b.elems();
3090 /// assert!((1.0f32.sqrt() - elems[0]).abs() < 0.001);
3091 /// assert!((2.0f32.sqrt() - elems[1]).abs() < 0.001);
3092 /// assert!((3.0f32.sqrt() - elems[2]).abs() < 0.001);
3093 /// assert!((4.0f32.sqrt() - elems[3]).abs() < 0.001);
3094 /// ```
3095 pub fn sqrt(&self, a: &Matrix, b: &Matrix) -> Result<()>
3096 {
3097 if a.row_count != b.row_count || a.col_count != b.col_count {
3098 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3099 }
3100 if b.is_transposed {
3101 return Err(Error::ResTransposition);
3102 }
3103 if !a.is_transposed {
3104 self.backend.sqrt_a(&*a.array, &*b.array, a.row_count, a.col_count)
3105 } else {
3106 self.backend.sqrt_at(&*a.array, &*b.array, a.row_count, a.col_count)
3107 }
3108 }
3109
3110 /// Indeed transposes the `a` matrix and then the result is in the `b` matrix
3111 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><msup><mi mathvariant="bold">A</mi><mi mathvariant="normal">T</mi></msup></mrow></math>).
3112 ///
3113 /// This method indeed transposes the `a` matrix without changing the transpose flag.
3114 ///
3115 /// # Examples
3116 ///
3117 /// ```
3118 /// # use unmtx_gpu::*;
3119 /// let a = matrix![
3120 /// [1.0, 2.0, 3.0],
3121 /// [4.0, 5.0, 6.0]
3122 /// ];
3123 /// let b = Matrix::new(3, 2);
3124 /// let frontend = Frontend::new().unwrap();
3125 /// frontend.really_transpose(&a, &b).unwrap();
3126 /// assert_eq!(vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0], b.elems());
3127 /// ```
3128 pub fn really_transpose(&self, a: &Matrix, b: &Matrix) -> Result<()>
3129 {
3130 if a.row_count != b.col_count || a.col_count != b.row_count {
3131 return Err(Error::TransposeSize(a.row_count, a.col_count, b.row_count, b.col_count));
3132 }
3133 if a.is_transposed {
3134 return Err(Error::ArgTransposition);
3135 }
3136 if b.is_transposed {
3137 return Err(Error::ResTransposition);
3138 }
3139 self.backend.transpose_a(&*a.array, &*b.array, a.col_count, a.row_count)
3140 }
3141
3142 /// Repeats the `a` vector as column or a row
3143 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mi>i</mi></msub></mrow></math> or
3144 /// <math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>a</mi><mi>j</mi></msub></mrow></math>).
3145 ///
3146 /// # Examples
3147 ///
3148 /// ```
3149 /// # use unmtx_gpu::*;
3150 /// let a = matrix![
3151 /// [1.0],
3152 /// [2.0]
3153 /// ];
3154 /// let b = Matrix::new(2, 3);
3155 /// let frontend = Frontend::new().unwrap();
3156 /// frontend.repeat(&a, &b).unwrap();
3157 /// assert_eq!(vec![1.0, 1.0, 1.0, 2.0, 2.0, 2.0], b.elems());
3158 /// let c = matrix![[1.0, 2.0, 3.0]];
3159 /// let d = Matrix::new(2, 3);
3160 /// let frontend = Frontend::new().unwrap();
3161 /// frontend.repeat(&c, &d).unwrap();
3162 /// assert_eq!(vec![1.0, 2.0, 3.0, 1.0, 2.0, 3.0], d.elems());
3163 /// ```
3164 pub fn repeat(&self, a: &Matrix, b: &Matrix) -> Result<()>
3165 {
3166 if b.is_transposed {
3167 return Err(Error::ResTransposition);
3168 }
3169 if a.col_count == 1 {
3170 if a.row_count != b.row_count {
3171 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3172 }
3173 self.backend.repeat_col_a(&*a.array, &*b.array, a.row_count, b.col_count)
3174 } else if a.row_count == 1 {
3175 if a.col_count != b.col_count {
3176 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3177 }
3178 self.backend.repeat_row_a(&*a.array, &*b.array, b.row_count, a.col_count)
3179 } else {
3180 Err(Error::IsNotVector)
3181 }
3182 }
3183
3184 /// Calculates absolute values of the `a` matrix elements and then the result is in the `b`
3185 /// matrix
3186 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mo fence="true">|</mo><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo fence="true">|</mo></mrow></math>).
3187 ///
3188 /// # Examples
3189 ///
3190 /// ```
3191 /// # use unmtx_gpu::*;
3192 /// let a = matrix![
3193 /// [-2.0, -1.0],
3194 /// [1.0, 2.0]
3195 /// ];
3196 /// let b = Matrix::new(2, 2);
3197 /// let frontend = Frontend::new().unwrap();
3198 /// frontend.abs(&a, &b).unwrap();
3199 /// assert_eq!(vec![2.0, 1.0, 1.0, 2.0], b.elems());
3200 /// ```
3201 pub fn abs(&self, a: &Matrix, b: &Matrix) -> Result<()>
3202 {
3203 if a.row_count != b.row_count || a.col_count != b.col_count {
3204 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3205 }
3206 if b.is_transposed {
3207 return Err(Error::ResTransposition);
3208 }
3209 if !a.is_transposed {
3210 self.backend.abs_a(&*a.array, &*b.array, a.row_count, a.col_count)
3211 } else {
3212 self.backend.abs_at(&*a.array, &*b.array, a.row_count, a.col_count)
3213 }
3214 }
3215
3216 /// Raises the `a` matrix elements to the power of the `b` matrix elements and then the result
3217 /// is in the `c` matrix
3218 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
3219 ///
3220 /// # Examples
3221 ///
3222 /// ```
3223 /// # use unmtx_gpu::*;
3224 /// let a = matrix![
3225 /// [1.0, 2.0],
3226 /// [3.0, 4.0]
3227 /// ];
3228 /// let b = matrix![
3229 /// [3.0, 4.0],
3230 /// [5.0, 6.0]
3231 /// ];
3232 /// let c = Matrix::new(2, 2);
3233 /// let frontend = Frontend::new().unwrap();
3234 /// frontend.pow(&a, &b, &c).unwrap();
3235 /// let elems = c.elems();
3236 /// assert!((1.0f32.powf(3.0) - elems[0]).abs() < 0.001);
3237 /// assert!((2.0f32.powf(4.0) - elems[1]).abs() < 0.001);
3238 /// assert!((3.0f32.powf(5.0) - elems[2]).abs() < 0.001);
3239 /// assert!((4.0f32.powf(6.0) - elems[3]).abs() < 0.001);
3240 /// ```
3241 pub fn pow(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
3242 {
3243 if a.row_count != b.row_count || a.col_count != b.col_count {
3244 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3245 }
3246 if a.row_count != c.row_count || a.col_count != c.col_count {
3247 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3248 }
3249 if c.is_transposed {
3250 return Err(Error::ResTransposition);
3251 }
3252 match (a.is_transposed, b.is_transposed) {
3253 (false, false) => self.backend.pow_a_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3254 (true, false) => self.backend.pow_at_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3255 (false, true) => self.backend.pow_a_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3256 (true, true) => self.backend.pow_at_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3257 }
3258 }
3259
3260 /// Raises the `a` matrix elements to the power of the `b` scalar and then the result is in
3261 /// the `c` matrix
3262 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></msup></mrow></math>).
3263 ///
3264 /// # Examples
3265 ///
3266 /// ```
3267 /// # use unmtx_gpu::*;
3268 /// let a = matrix![
3269 /// [1.0, 2.0],
3270 /// [3.0, 4.0]
3271 /// ];
3272 /// let c = Matrix::new(2, 2);
3273 /// let frontend = Frontend::new().unwrap();
3274 /// frontend.pow_for_scalar(&a, 2.5, &c).unwrap();
3275 /// let elems = c.elems();
3276 /// assert!((1.0f32.powf(2.5) - elems[0]).abs() < 0.001);
3277 /// assert!((2.0f32.powf(2.5) - elems[1]).abs() < 0.001);
3278 /// assert!((3.0f32.powf(2.5) - elems[2]).abs() < 0.001);
3279 /// assert!((4.0f32.powf(2.5) - elems[3]).abs() < 0.001);
3280 /// ```
3281 pub fn pow_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
3282 {
3283 if a.row_count != c.row_count || a.col_count != c.col_count {
3284 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3285 }
3286 if c.is_transposed {
3287 return Err(Error::ResTransposition);
3288 }
3289 if !a.is_transposed {
3290 self.backend.pow_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3291 } else {
3292 self.backend.pow_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3293 }
3294 }
3295
3296 /// Raises the `b` scalar to the power of the `a` matrix elements and then the result is in
3297 /// the `c` matrix
3298 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
3299 ///
3300 /// # Examples
3301 ///
3302 /// ```
3303 /// # use unmtx_gpu::*;
3304 /// let a = matrix![
3305 /// [1.0, 2.0],
3306 /// [3.0, 4.0]
3307 /// ];
3308 /// let c = Matrix::new(2, 2);
3309 /// let frontend = Frontend::new().unwrap();
3310 /// frontend.rpow_for_scalar(&a, 10.5, &c).unwrap();
3311 /// let elems = c.elems();
3312 /// assert!((10.5f32.powf(1.0) - elems[0]).abs() < 0.001);
3313 /// assert!((10.5f32.powf(2.0) - elems[1]).abs() < 0.001);
3314 /// assert!((10.5f32.powf(3.0) - elems[2]).abs() < 0.001);
3315 /// assert!((10.5f32.powf(4.0) - elems[3]).abs() < 0.001);
3316 /// ```
3317 pub fn rpow_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
3318 {
3319 if a.row_count != c.row_count || a.col_count != c.col_count {
3320 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3321 }
3322 if c.is_transposed {
3323 return Err(Error::ResTransposition);
3324 }
3325 if !a.is_transposed {
3326 self.backend.rpow_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3327 } else {
3328 self.backend.rpow_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3329 }
3330 }
3331
3332 /// Calculates exponential function for the `a` matrix elements and then the result is in the
3333 /// `b` matrix
3334 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msup><mi>e</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></msup></mrow></math>).
3335 ///
3336 /// # Examples
3337 ///
3338 /// ```
3339 /// # use unmtx_gpu::*;
3340 /// let a = matrix![
3341 /// [1.0, 2.0],
3342 /// [3.0, 4.0]
3343 /// ];
3344 /// let b = Matrix::new(2, 2);
3345 /// let frontend = Frontend::new().unwrap();
3346 /// frontend.exp(&a, &b).unwrap();
3347 /// let elems = b.elems();
3348 /// assert!((1.0f32.exp() - elems[0]).abs() < 0.001);
3349 /// assert!((2.0f32.exp() - elems[1]).abs() < 0.001);
3350 /// assert!((3.0f32.exp() - elems[2]).abs() < 0.001);
3351 /// assert!((4.0f32.exp() - elems[3]).abs() < 0.001);
3352 /// ```
3353 pub fn exp(&self, a: &Matrix, b: &Matrix) -> Result<()>
3354 {
3355 if a.row_count != b.row_count || a.col_count != b.col_count {
3356 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3357 }
3358 if b.is_transposed {
3359 return Err(Error::ResTransposition);
3360 }
3361 if !a.is_transposed {
3362 self.backend.exp_a(&*a.array, &*b.array, a.row_count, a.col_count)
3363 } else {
3364 self.backend.exp_at(&*a.array, &*b.array, a.row_count, a.col_count)
3365 }
3366 }
3367
3368 /// Calculates natural logarithm of the `a` matrix elements and then the result is in the `b`
3369 /// matrix
3370 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>ln</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
3371 ///
3372 /// # Examples
3373 ///
3374 /// ```
3375 /// # use unmtx_gpu::*;
3376 /// let a = matrix![
3377 /// [1.0, 2.0],
3378 /// [3.0, 4.0]
3379 /// ];
3380 /// let b = Matrix::new(2, 2);
3381 /// let frontend = Frontend::new().unwrap();
3382 /// frontend.ln(&a, &b).unwrap();
3383 /// let elems = b.elems();
3384 /// assert!((1.0f32.ln() - elems[0]).abs() < 0.001);
3385 /// assert!((2.0f32.ln() - elems[1]).abs() < 0.001);
3386 /// assert!((3.0f32.ln() - elems[2]).abs() < 0.001);
3387 /// assert!((4.0f32.ln() - elems[3]).abs() < 0.001);
3388 /// ```
3389 pub fn ln(&self, a: &Matrix, b: &Matrix) -> Result<()>
3390 {
3391 if a.row_count != b.row_count || a.col_count != b.col_count {
3392 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3393 }
3394 if b.is_transposed {
3395 return Err(Error::ResTransposition);
3396 }
3397 if !a.is_transposed {
3398 self.backend.ln_a(&*a.array, &*b.array, a.row_count, a.col_count)
3399 } else {
3400 self.backend.ln_at(&*a.array, &*b.array, a.row_count, a.col_count)
3401 }
3402 }
3403
3404 /// Calculates base 2 logarithm of the `a` matrix elements and then the result is in the `b`
3405 /// matrix
3406 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>2</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
3407 ///
3408 /// # Examples
3409 ///
3410 /// ```
3411 /// # use unmtx_gpu::*;
3412 /// let a = matrix![
3413 /// [1.0, 2.0],
3414 /// [3.0, 4.0]
3415 /// ];
3416 /// let b = Matrix::new(2, 2);
3417 /// let frontend = Frontend::new().unwrap();
3418 /// frontend.log2(&a, &b).unwrap();
3419 /// let elems = b.elems();
3420 /// assert!((1.0f32.log2() - elems[0]).abs() < 0.001);
3421 /// assert!((2.0f32.log2() - elems[1]).abs() < 0.001);
3422 /// assert!((3.0f32.log2() - elems[2]).abs() < 0.001);
3423 /// assert!((4.0f32.log2() - elems[3]).abs() < 0.001);
3424 /// ```
3425 pub fn log2(&self, a: &Matrix, b: &Matrix) -> Result<()>
3426 {
3427 if a.row_count != b.row_count || a.col_count != b.col_count {
3428 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3429 }
3430 if b.is_transposed {
3431 return Err(Error::ResTransposition);
3432 }
3433 if !a.is_transposed {
3434 self.backend.log2_a(&*a.array, &*b.array, a.row_count, a.col_count)
3435 } else {
3436 self.backend.log2_at(&*a.array, &*b.array, a.row_count, a.col_count)
3437 }
3438 }
3439
3440 /// Calculates base 10 logarithm of the `a` matrix elements and then the result is in the `b`
3441 /// matrix
3442 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>log</mi><mn>10</mn></msub><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></math>).
3443 ///
3444 /// # Examples
3445 ///
3446 /// ```
3447 /// # use unmtx_gpu::*;
3448 /// let a = matrix![
3449 /// [1.0, 2.0],
3450 /// [3.0, 4.0]
3451 /// ];
3452 /// let b = Matrix::new(2, 2);
3453 /// let frontend = Frontend::new().unwrap();
3454 /// frontend.log10(&a, &b).unwrap();
3455 /// let elems = b.elems();
3456 /// assert!((1.0f32.log10() - elems[0]).abs() < 0.001);
3457 /// assert!((2.0f32.log10() - elems[1]).abs() < 0.001);
3458 /// assert!((3.0f32.log10() - elems[2]).abs() < 0.001);
3459 /// assert!((4.0f32.log10() - elems[3]).abs() < 0.001);
3460 /// ```
3461 pub fn log10(&self, a: &Matrix, b: &Matrix) -> Result<()>
3462 {
3463 if a.row_count != b.row_count || a.col_count != b.col_count {
3464 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3465 }
3466 if b.is_transposed {
3467 return Err(Error::ResTransposition);
3468 }
3469 if !a.is_transposed {
3470 self.backend.log10_a(&*a.array, &*b.array, a.row_count, a.col_count)
3471 } else {
3472 self.backend.log10_at(&*a.array, &*b.array, a.row_count, a.col_count)
3473 }
3474 }
3475
3476 /// Calculates sine function for the `a` matrix and then the result is in the `b` matrix
3477 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3478 ///
3479 /// # Examples
3480 ///
3481 /// ```
3482 /// # use unmtx_gpu::*;
3483 /// let a = matrix![
3484 /// [1.0, 2.0],
3485 /// [3.0, 4.0]
3486 /// ];
3487 /// let b = Matrix::new(2, 2);
3488 /// let frontend = Frontend::new().unwrap();
3489 /// frontend.sin(&a, &b).unwrap();
3490 /// let elems = b.elems();
3491 /// assert!((1.0f32.sin() - elems[0]).abs() < 0.001);
3492 /// assert!((2.0f32.sin() - elems[1]).abs() < 0.001);
3493 /// assert!((3.0f32.sin() - elems[2]).abs() < 0.001);
3494 /// assert!((4.0f32.sin() - elems[3]).abs() < 0.001);
3495 /// ```
3496 pub fn sin(&self, a: &Matrix, b: &Matrix) -> Result<()>
3497 {
3498 if a.row_count != b.row_count || a.col_count != b.col_count {
3499 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3500 }
3501 if b.is_transposed {
3502 return Err(Error::ResTransposition);
3503 }
3504 if !a.is_transposed {
3505 self.backend.sin_a(&*a.array, &*b.array, a.row_count, a.col_count)
3506 } else {
3507 self.backend.sin_at(&*a.array, &*b.array, a.row_count, a.col_count)
3508 }
3509 }
3510
3511 /// Calculates cosine function for the `a` matrix and then the result is in the `b` matrix
3512 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3513 ///
3514 /// # Examples
3515 ///
3516 /// ```
3517 /// # use unmtx_gpu::*;
3518 /// let a = matrix![
3519 /// [1.0, 2.0],
3520 /// [3.0, 4.0]
3521 /// ];
3522 /// let b = Matrix::new(2, 2);
3523 /// let frontend = Frontend::new().unwrap();
3524 /// frontend.cos(&a, &b).unwrap();
3525 /// let elems = b.elems();
3526 /// assert!((1.0f32.cos() - elems[0]).abs() < 0.001);
3527 /// assert!((2.0f32.cos() - elems[1]).abs() < 0.001);
3528 /// assert!((3.0f32.cos() - elems[2]).abs() < 0.001);
3529 /// assert!((4.0f32.cos() - elems[3]).abs() < 0.001);
3530 /// ```
3531 pub fn cos(&self, a: &Matrix, b: &Matrix) -> Result<()>
3532 {
3533 if a.row_count != b.row_count || a.col_count != b.col_count {
3534 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3535 }
3536 if b.is_transposed {
3537 return Err(Error::ResTransposition);
3538 }
3539 if !a.is_transposed {
3540 self.backend.cos_a(&*a.array, &*b.array, a.row_count, a.col_count)
3541 } else {
3542 self.backend.cos_at(&*a.array, &*b.array, a.row_count, a.col_count)
3543 }
3544 }
3545
3546 /// Calculates tangent function for the `a` matrix and then the result is in the `b` matrix
3547 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>tan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3548 ///
3549 /// # Examples
3550 ///
3551 /// ```
3552 /// # use unmtx_gpu::*;
3553 /// let a = matrix![
3554 /// [1.0, 2.0],
3555 /// [3.0, 4.0]
3556 /// ];
3557 /// let b = Matrix::new(2, 2);
3558 /// let frontend = Frontend::new().unwrap();
3559 /// frontend.tan(&a, &b).unwrap();
3560 /// let elems = b.elems();
3561 /// assert!((1.0f32.tan() - elems[0]).abs() < 0.001);
3562 /// assert!((2.0f32.tan() - elems[1]).abs() < 0.001);
3563 /// assert!((3.0f32.tan() - elems[2]).abs() < 0.001);
3564 /// assert!((4.0f32.tan() - elems[3]).abs() < 0.001);
3565 /// ```
3566 pub fn tan(&self, a: &Matrix, b: &Matrix) -> Result<()>
3567 {
3568 if a.row_count != b.row_count || a.col_count != b.col_count {
3569 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3570 }
3571 if b.is_transposed {
3572 return Err(Error::ResTransposition);
3573 }
3574 if !a.is_transposed {
3575 self.backend.tan_a(&*a.array, &*b.array, a.row_count, a.col_count)
3576 } else {
3577 self.backend.tan_at(&*a.array, &*b.array, a.row_count, a.col_count)
3578 }
3579 }
3580
3581 /// Calculates arcsine function for the `a` matrix and then the result is in the `b` matrix
3582 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcsin</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3583 ///
3584 /// # Examples
3585 ///
3586 /// ```
3587 /// # use unmtx_gpu::*;
3588 /// let a = matrix![
3589 /// [0.25, 0.5],
3590 /// [0.75, 1.0]
3591 /// ];
3592 /// let b = Matrix::new(2, 2);
3593 /// let frontend = Frontend::new().unwrap();
3594 /// frontend.asin(&a, &b).unwrap();
3595 /// let elems = b.elems();
3596 /// assert!((0.25f32.asin() - elems[0]).abs() < 0.001);
3597 /// assert!((0.5f32.asin() - elems[1]).abs() < 0.001);
3598 /// assert!((0.75f32.asin() - elems[2]).abs() < 0.001);
3599 /// assert!((1.0f32.asin() - elems[3]).abs() < 0.001);
3600 /// ```
3601 pub fn asin(&self, a: &Matrix, b: &Matrix) -> Result<()>
3602 {
3603 if a.row_count != b.row_count || a.col_count != b.col_count {
3604 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3605 }
3606 if b.is_transposed {
3607 return Err(Error::ResTransposition);
3608 }
3609 if !a.is_transposed {
3610 self.backend.asin_a(&*a.array, &*b.array, a.row_count, a.col_count)
3611 } else {
3612 self.backend.asin_at(&*a.array, &*b.array, a.row_count, a.col_count)
3613 }
3614 }
3615
3616 /// Calculates arccosine function for the `a` matrix and then the result is in the `b` matrix
3617 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arccos</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3618 ///
3619 /// # Examples
3620 ///
3621 /// ```
3622 /// # use unmtx_gpu::*;
3623 /// let a = matrix![
3624 /// [0.25, 0.5],
3625 /// [0.75, 1.0]
3626 /// ];
3627 /// let b = Matrix::new(2, 2);
3628 /// let frontend = Frontend::new().unwrap();
3629 /// frontend.acos(&a, &b).unwrap();
3630 /// let elems = b.elems();
3631 /// assert!((0.25f32.acos() - elems[0]).abs() < 0.001);
3632 /// assert!((0.5f32.acos() - elems[1]).abs() < 0.001);
3633 /// assert!((0.75f32.acos() - elems[2]).abs() < 0.001);
3634 /// assert!((1.0f32.acos() - elems[3]).abs() < 0.001);
3635 /// ```
3636 pub fn acos(&self, a: &Matrix, b: &Matrix) -> Result<()>
3637 {
3638 if a.row_count != b.row_count || a.col_count != b.col_count {
3639 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3640 }
3641 if b.is_transposed {
3642 return Err(Error::ResTransposition);
3643 }
3644 if !a.is_transposed {
3645 self.backend.acos_a(&*a.array, &*b.array, a.row_count, a.col_count)
3646 } else {
3647 self.backend.acos_at(&*a.array, &*b.array, a.row_count, a.col_count)
3648 }
3649 }
3650
3651 /// Calculates arctangent function for the `a` matrix and then the result is in the `b` matrix
3652 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3653 ///
3654 /// # Examples
3655 ///
3656 /// ```
3657 /// # use unmtx_gpu::*;
3658 /// let a = matrix![
3659 /// [1.0, 2.0],
3660 /// [3.0, 4.0]
3661 /// ];
3662 /// let b = Matrix::new(2, 2);
3663 /// let frontend = Frontend::new().unwrap();
3664 /// frontend.atan(&a, &b).unwrap();
3665 /// let elems = b.elems();
3666 /// assert!((1.0f32.atan() - elems[0]).abs() < 0.001);
3667 /// assert!((2.0f32.atan() - elems[1]).abs() < 0.001);
3668 /// assert!((3.0f32.atan() - elems[2]).abs() < 0.001);
3669 /// assert!((4.0f32.atan() - elems[3]).abs() < 0.001);
3670 /// ```
3671 pub fn atan(&self, a: &Matrix, b: &Matrix) -> Result<()>
3672 {
3673 if a.row_count != b.row_count || a.col_count != b.col_count {
3674 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3675 }
3676 if b.is_transposed {
3677 return Err(Error::ResTransposition);
3678 }
3679 if !a.is_transposed {
3680 self.backend.atan_a(&*a.array, &*b.array, a.row_count, a.col_count)
3681 } else {
3682 self.backend.atan_at(&*a.array, &*b.array, a.row_count, a.col_count)
3683 }
3684 }
3685
3686 /// Calculates arctangent function for the `a` matrix elements and the `b` matrix elements and
3687 /// then the result is in the `c` matrix
3688 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><msub><mi>b</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
3689 ///
3690 /// # Examples
3691 ///
3692 /// ```
3693 /// # use unmtx_gpu::*;
3694 /// let a = matrix![
3695 /// [1.0, 2.0],
3696 /// [3.0, 4.0]
3697 /// ];
3698 /// let b = matrix![
3699 /// [5.0, 6.0],
3700 /// [7.0, 8.0]
3701 /// ];
3702 /// let c = Matrix::new(2, 2);
3703 /// let frontend = Frontend::new().unwrap();
3704 /// frontend.atan2(&a, &b, &c).unwrap();
3705 /// let elems = c.elems();
3706 /// assert!((1.0f32.atan2(5.0) - elems[0]).abs() < 0.001);
3707 /// assert!((2.0f32.atan2(6.0) - elems[1]).abs() < 0.001);
3708 /// assert!((3.0f32.atan2(7.0) - elems[2]).abs() < 0.001);
3709 /// assert!((4.0f32.atan2(8.0) - elems[3]).abs() < 0.001);
3710 /// ```
3711 pub fn atan2(&self, a: &Matrix, b: &Matrix, c: &Matrix) -> Result<()>
3712 {
3713 if a.row_count != b.row_count || a.col_count != b.col_count {
3714 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3715 }
3716 if a.row_count != c.row_count || a.col_count != c.col_count {
3717 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3718 }
3719 if c.is_transposed {
3720 return Err(Error::ResTransposition);
3721 }
3722 match (a.is_transposed, b.is_transposed) {
3723 (false, false) => self.backend.atan2_a_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3724 (true, false) => self.backend.atan2_at_b(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3725 (false, true) => self.backend.atan2_a_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3726 (true, true) => self.backend.atan2_at_bt(&*a.array, &*b.array, &*c.array, a.row_count, a.col_count),
3727 }
3728 }
3729
3730 /// Calculates arctangent function for the `a` matrix elements and the `b` scalar and then the
3731 /// result is in the `c` matrix
3732 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>b</mi></mfrac><mo fence="true">)</mo></mrow></math>).
3733 ///
3734 /// # Examples
3735 ///
3736 /// ```
3737 /// # use unmtx_gpu::*;
3738 /// let a = matrix![
3739 /// [1.0, 2.0],
3740 /// [3.0, 4.0]
3741 /// ];
3742 /// let c = Matrix::new(2, 2);
3743 /// let frontend = Frontend::new().unwrap();
3744 /// frontend.atan2_for_scalar(&a, 10.5, &c).unwrap();
3745 /// let elems = c.elems();
3746 /// assert!((1.0f32.atan2(10.5) - elems[0]).abs() < 0.001);
3747 /// assert!((2.0f32.atan2(10.5) - elems[1]).abs() < 0.001);
3748 /// assert!((3.0f32.atan2(10.5) - elems[2]).abs() < 0.001);
3749 /// assert!((4.0f32.atan2(10.5) - elems[3]).abs() < 0.001);
3750 /// ```
3751 pub fn atan2_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
3752 {
3753 if a.row_count != c.row_count || a.col_count != c.col_count {
3754 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3755 }
3756 if c.is_transposed {
3757 return Err(Error::ResTransposition);
3758 }
3759 if !a.is_transposed {
3760 self.backend.atan2_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3761 } else {
3762 self.backend.atan2_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3763 }
3764 }
3765
3766 /// Calculates arctangent function for the `b` scalar and the `a` matrix elements and then the
3767 /// result is in the `c` matrix
3768 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><msub><mi>c</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><mi>arctan</mi><mo fence="true">(</mo><mfrac><mi>b</mi><msub><mi>a</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mfrac><mo fence="true">)</mo></mrow></math>).
3769 ///
3770 /// # Examples
3771 ///
3772 /// ```
3773 /// # use unmtx_gpu::*;
3774 /// let a = matrix![
3775 /// [1.0, 2.0],
3776 /// [3.0, 4.0]
3777 /// ];
3778 /// let c = Matrix::new(2, 2);
3779 /// let frontend = Frontend::new().unwrap();
3780 /// frontend.ratan2_for_scalar(&a, 10.5, &c).unwrap();
3781 /// let elems = c.elems();
3782 /// assert!((10.5f32.atan2(1.0) - elems[0]).abs() < 0.001);
3783 /// assert!((10.5f32.atan2(2.0) - elems[1]).abs() < 0.001);
3784 /// assert!((10.5f32.atan2(3.0) - elems[2]).abs() < 0.001);
3785 /// assert!((10.5f32.atan2(4.0) - elems[3]).abs() < 0.001);
3786 /// ```
3787 pub fn ratan2_for_scalar(&self, a: &Matrix, b: f32, c: &Matrix) -> Result<()>
3788 {
3789 if a.row_count != c.row_count || a.col_count != c.col_count {
3790 return Err(Error::OpSize(a.row_count, a.col_count, c.row_count, c.col_count));
3791 }
3792 if c.is_transposed {
3793 return Err(Error::ResTransposition);
3794 }
3795 if !a.is_transposed {
3796 self.backend.ratan2_a_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3797 } else {
3798 self.backend.ratan2_at_b_for_scalar(&*a.array, b, &*c.array, a.row_count, a.col_count)
3799 }
3800 }
3801
3802 /// Calculates hyperbolic sine function for the `a` matrix and then the result is in the `b`
3803 /// matrix
3804 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3805 ///
3806 /// # Examples
3807 ///
3808 /// ```
3809 /// # use unmtx_gpu::*;
3810 /// let a = matrix![
3811 /// [1.0, 2.0],
3812 /// [3.0, 4.0]
3813 /// ];
3814 /// let b = Matrix::new(2, 2);
3815 /// let frontend = Frontend::new().unwrap();
3816 /// frontend.sinh(&a, &b).unwrap();
3817 /// let elems = b.elems();
3818 /// assert!((1.0f32.sinh() - elems[0]).abs() < 0.001);
3819 /// assert!((2.0f32.sinh() - elems[1]).abs() < 0.001);
3820 /// assert!((3.0f32.sinh() - elems[2]).abs() < 0.001);
3821 /// assert!((4.0f32.sinh() - elems[3]).abs() < 0.001);
3822 /// ```
3823 pub fn sinh(&self, a: &Matrix, b: &Matrix) -> Result<()>
3824 {
3825 if a.row_count != b.row_count || a.col_count != b.col_count {
3826 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3827 }
3828 if b.is_transposed {
3829 return Err(Error::ResTransposition);
3830 }
3831 if !a.is_transposed {
3832 self.backend.sinh_a(&*a.array, &*b.array, a.row_count, a.col_count)
3833 } else {
3834 self.backend.sinh_at(&*a.array, &*b.array, a.row_count, a.col_count)
3835 }
3836 }
3837
3838 /// Calculates hyperbolic cosine function for the `a` matrix and then the result is in the `b`
3839 /// matrix
3840 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>cosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3841 ///
3842 /// # Examples
3843 ///
3844 /// ```
3845 /// # use unmtx_gpu::*;
3846 /// let a = matrix![
3847 /// [1.0, 2.0],
3848 /// [3.0, 4.0]
3849 /// ];
3850 /// let b = Matrix::new(2, 2);
3851 /// let frontend = Frontend::new().unwrap();
3852 /// frontend.cosh(&a, &b).unwrap();
3853 /// let elems = b.elems();
3854 /// assert!((1.0f32.cosh() - elems[0]).abs() < 0.001);
3855 /// assert!((2.0f32.cosh() - elems[1]).abs() < 0.001);
3856 /// assert!((3.0f32.cosh() - elems[2]).abs() < 0.001);
3857 /// assert!((4.0f32.cosh() - elems[3]).abs() < 0.001);
3858 /// ```
3859 pub fn cosh(&self, a: &Matrix, b: &Matrix) -> Result<()>
3860 {
3861 if a.row_count != b.row_count || a.col_count != b.col_count {
3862 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3863 }
3864 if b.is_transposed {
3865 return Err(Error::ResTransposition);
3866 }
3867 if !a.is_transposed {
3868 self.backend.cosh_a(&*a.array, &*b.array, a.row_count, a.col_count)
3869 } else {
3870 self.backend.cosh_at(&*a.array, &*b.array, a.row_count, a.col_count)
3871 }
3872 }
3873
3874 /// Calculates inverse hyperbolic sine function for the `a` matrix and then the result is in
3875 /// the `b` matrix
3876 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arsinh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3877 ///
3878 /// # Examples
3879 ///
3880 /// ```
3881 /// # use unmtx_gpu::*;
3882 /// let a = matrix![
3883 /// [1.0, 2.0],
3884 /// [3.0, 4.0]
3885 /// ];
3886 /// let b = Matrix::new(2, 2);
3887 /// let frontend = Frontend::new().unwrap();
3888 /// frontend.asinh(&a, &b).unwrap();
3889 /// let elems = b.elems();
3890 /// assert!((1.0f32.asinh() - elems[0]).abs() < 0.001);
3891 /// assert!((2.0f32.asinh() - elems[1]).abs() < 0.001);
3892 /// assert!((3.0f32.asinh() - elems[2]).abs() < 0.001);
3893 /// assert!((4.0f32.asinh() - elems[3]).abs() < 0.001);
3894 /// ```
3895 pub fn asinh(&self, a: &Matrix, b: &Matrix) -> Result<()>
3896 {
3897 if a.row_count != b.row_count || a.col_count != b.col_count {
3898 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3899 }
3900 if b.is_transposed {
3901 return Err(Error::ResTransposition);
3902 }
3903 if !a.is_transposed {
3904 self.backend.asinh_a(&*a.array, &*b.array, a.row_count, a.col_count)
3905 } else {
3906 self.backend.asinh_at(&*a.array, &*b.array, a.row_count, a.col_count)
3907 }
3908 }
3909
3910 /// Calculates inverse hyperbolic cosine function for the `a` matrix and then the result is in
3911 /// the `b` matrix
3912 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>arcosh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3913 ///
3914 /// # Examples
3915 ///
3916 /// ```
3917 /// # use unmtx_gpu::*;
3918 /// let a = matrix![
3919 /// [1.0, 2.0],
3920 /// [3.0, 4.0]
3921 /// ];
3922 /// let b = Matrix::new(2, 2);
3923 /// let frontend = Frontend::new().unwrap();
3924 /// frontend.acosh(&a, &b).unwrap();
3925 /// let elems = b.elems();
3926 /// assert!((1.0f32.acosh() - elems[0]).abs() < 0.001);
3927 /// assert!((2.0f32.acosh() - elems[1]).abs() < 0.001);
3928 /// assert!((3.0f32.acosh() - elems[2]).abs() < 0.001);
3929 /// assert!((4.0f32.acosh() - elems[3]).abs() < 0.001);
3930 /// ```
3931 pub fn acosh(&self, a: &Matrix, b: &Matrix) -> Result<()>
3932 {
3933 if a.row_count != b.row_count || a.col_count != b.col_count {
3934 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3935 }
3936 if b.is_transposed {
3937 return Err(Error::ResTransposition);
3938 }
3939 if !a.is_transposed {
3940 self.backend.acosh_a(&*a.array, &*b.array, a.row_count, a.col_count)
3941 } else {
3942 self.backend.acosh_at(&*a.array, &*b.array, a.row_count, a.col_count)
3943 }
3944 }
3945
3946 /// Calculates inverse hyperbolic tangent function for the `a` matrix and then the result is
3947 /// in the `b` matrix
3948 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>artanh</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3949 ///
3950 /// # Examples
3951 ///
3952 /// ```
3953 /// # use unmtx_gpu::*;
3954 /// let a = matrix![
3955 /// [0.25, 0.5],
3956 /// [0.75, 1.0]
3957 /// ];
3958 /// let b = Matrix::new(2, 2);
3959 /// let frontend = Frontend::new().unwrap();
3960 /// frontend.atanh(&a, &b).unwrap();
3961 /// let elems = b.elems();
3962 /// assert!((0.25f32.atanh() - elems[0]).abs() < 0.001);
3963 /// assert!((0.5f32.atanh() - elems[1]).abs() < 0.001);
3964 /// assert!((0.75f32.atanh() - elems[2]).abs() < 0.001);
3965 /// assert_eq!(f32::INFINITY, elems[3]);
3966 /// ```
3967 pub fn atanh(&self, a: &Matrix, b: &Matrix) -> Result<()>
3968 {
3969 if a.row_count != b.row_count || a.col_count != b.col_count {
3970 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
3971 }
3972 if b.is_transposed {
3973 return Err(Error::ResTransposition);
3974 }
3975 if !a.is_transposed {
3976 self.backend.atanh_a(&*a.array, &*b.array, a.row_count, a.col_count)
3977 } else {
3978 self.backend.atanh_at(&*a.array, &*b.array, a.row_count, a.col_count)
3979 }
3980 }
3981
3982 /// Calculates signum function for the `a` matrix and then the result is in the `b` matrix
3983 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>sgn</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
3984 ///
3985 /// # Examples
3986 ///
3987 /// ```
3988 /// # use unmtx_gpu::*;
3989 /// let a = matrix![
3990 /// [-2.0, -1.0],
3991 /// [1.0, 2.0]
3992 /// ];
3993 /// let b = Matrix::new(2, 2);
3994 /// let frontend = Frontend::new().unwrap();
3995 /// frontend.signum(&a, &b).unwrap();
3996 /// assert_eq!(vec![-1.0, -1.0, 1.0, 1.0], b.elems());
3997 /// ```
3998 pub fn signum(&self, a: &Matrix, b: &Matrix) -> Result<()>
3999 {
4000 if a.row_count != b.row_count || a.col_count != b.col_count {
4001 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
4002 }
4003 if b.is_transposed {
4004 return Err(Error::ResTransposition);
4005 }
4006 if !a.is_transposed {
4007 self.backend.signum_a(&*a.array, &*b.array, a.row_count, a.col_count)
4008 } else {
4009 self.backend.signum_at(&*a.array, &*b.array, a.row_count, a.col_count)
4010 }
4011 }
4012
4013 /// Calculates ceil function for the `a` matrix and then the result is in the `b` matrix
4014 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>ceil</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
4015 ///
4016 /// # Examples
4017 ///
4018 /// ```
4019 /// # use unmtx_gpu::*;
4020 /// let a = matrix![
4021 /// [-2.6, -1.3],
4022 /// [1.3, 2.6]
4023 /// ];
4024 /// let b = Matrix::new(2, 2);
4025 /// let frontend = Frontend::new().unwrap();
4026 /// frontend.ceil(&a, &b).unwrap();
4027 /// assert_eq!(vec![-2.0, -1.0, 2.0, 3.0], b.elems());
4028 /// ```
4029 pub fn ceil(&self, a: &Matrix, b: &Matrix) -> Result<()>
4030 {
4031 if a.row_count != b.row_count || a.col_count != b.col_count {
4032 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
4033 }
4034 if b.is_transposed {
4035 return Err(Error::ResTransposition);
4036 }
4037 if !a.is_transposed {
4038 self.backend.ceil_a(&*a.array, &*b.array, a.row_count, a.col_count)
4039 } else {
4040 self.backend.ceil_at(&*a.array, &*b.array, a.row_count, a.col_count)
4041 }
4042 }
4043
4044 /// Calculates floor function for the `a` matrix and then the result is in the `b` matrix
4045 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>floor</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
4046 ///
4047 /// # Examples
4048 ///
4049 /// ```
4050 /// # use unmtx_gpu::*;
4051 /// let a = matrix![
4052 /// [-2.6, -1.3],
4053 /// [1.3, 2.6]
4054 /// ];
4055 /// let b = Matrix::new(2, 2);
4056 /// let frontend = Frontend::new().unwrap();
4057 /// frontend.floor(&a, &b).unwrap();
4058 /// assert_eq!(vec![-3.0, -2.0, 1.0, 2.0], b.elems());
4059 /// ```
4060 pub fn floor(&self, a: &Matrix, b: &Matrix) -> Result<()>
4061 {
4062 if a.row_count != b.row_count || a.col_count != b.col_count {
4063 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
4064 }
4065 if b.is_transposed {
4066 return Err(Error::ResTransposition);
4067 }
4068 if !a.is_transposed {
4069 self.backend.floor_a(&*a.array, &*b.array, a.row_count, a.col_count)
4070 } else {
4071 self.backend.floor_at(&*a.array, &*b.array, a.row_count, a.col_count)
4072 }
4073 }
4074
4075 /// Calculates round function for the `a` matrix and then the result is in the `b` matrix
4076 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>round</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
4077 ///
4078 /// # Examples
4079 ///
4080 /// ```
4081 /// # use unmtx_gpu::*;
4082 /// let a = matrix![
4083 /// [-2.6, -1.3],
4084 /// [1.3, 2.6]
4085 /// ];
4086 /// let b = Matrix::new(2, 2);
4087 /// let frontend = Frontend::new().unwrap();
4088 /// frontend.round(&a, &b).unwrap();
4089 /// assert_eq!(vec![-3.0, -1.0, 1.0, 3.0], b.elems());
4090 /// ```
4091 pub fn round(&self, a: &Matrix, b: &Matrix) -> Result<()>
4092 {
4093 if a.row_count != b.row_count || a.col_count != b.col_count {
4094 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
4095 }
4096 if b.is_transposed {
4097 return Err(Error::ResTransposition);
4098 }
4099 if !a.is_transposed {
4100 self.backend.round_a(&*a.array, &*b.array, a.row_count, a.col_count)
4101 } else {
4102 self.backend.round_at(&*a.array, &*b.array, a.row_count, a.col_count)
4103 }
4104 }
4105
4106 /// Calculates trunc function for the `a` matrix and then the result is in the `b` matrix
4107 /// (<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mi mathvariant="bold">B</mi><mo>=</mo><mi>trunc</mi><mo fence="true">(</mo><mi mathvariant="bold">A</mi><mo fence="true">)</mo></mrow></math>).
4108 ///
4109 /// # Examples
4110 ///
4111 /// ```
4112 /// # use unmtx_gpu::*;
4113 /// let a = matrix![
4114 /// [-2.6, -1.3],
4115 /// [1.3, 2.6]
4116 /// ];
4117 /// let b = Matrix::new(2, 2);
4118 /// let frontend = Frontend::new().unwrap();
4119 /// frontend.trunc(&a, &b).unwrap();
4120 /// assert_eq!(vec![-2.0, -1.0, 1.0, 2.0], b.elems());
4121 /// ```
4122 pub fn trunc(&self, a: &Matrix, b: &Matrix) -> Result<()>
4123 {
4124 if a.row_count != b.row_count || a.col_count != b.col_count {
4125 return Err(Error::OpSize(a.row_count, a.col_count, b.row_count, b.col_count));
4126 }
4127 if b.is_transposed {
4128 return Err(Error::ResTransposition);
4129 }
4130 if !a.is_transposed {
4131 self.backend.trunc_a(&*a.array, &*b.array, a.row_count, a.col_count)
4132 } else {
4133 self.backend.trunc_at(&*a.array, &*b.array, a.row_count, a.col_count)
4134 }
4135 }
4136}
4137
4138#[cfg(test)]
4139mod test_helpers;
4140#[cfg(all(test, not(feature = "test_only_backend")))]
4141mod tests;