unmtx_gpu/
lib.rs

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