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