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