unmtx_gpu/
lib.rs

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