Skip to main content

unmtx_gpu/
lib.rs

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