Skip to main content

unlab_gpu/
utils.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//! A module of utilities.
9use std::sync::mpsc::Receiver;
10use std::sync::Mutex;
11use std::sync::MutexGuard;
12use std::sync::RwLock;
13use std::sync::RwLockReadGuard;
14use std::sync::RwLockWriteGuard;
15use crate::matrix;
16use crate::matrix::Frontend;
17use crate::matrix::Matrix;
18use crate::error::*;
19use crate::value::*;
20
21/// A structure of pushback iterator.
22///
23/// The pushback iterator allows to push back an item. If the item is pushed back, the item can
24/// be again returned by the `next` method.
25#[derive(Clone)]
26pub struct PushbackIter<T: Iterator>
27{
28    iter: T,
29    pushed_items: Vec<T::Item>,
30}
31
32impl<T: Iterator> PushbackIter<T>
33{
34    /// Creates a pushback iterator.
35    pub fn new(iter: T) -> Self
36    { PushbackIter { iter, pushed_items: Vec::new(), } }
37
38    /// Returns an immutable iterator.
39    pub fn iter(&self) -> &T
40    { &self.iter }
41    
42    /// Returns a mutable iterator.
43    pub fn iter_mut(&mut self) -> &mut T
44    { &mut self.iter }
45
46    /// Pushes back the item to the pushback iterator.
47    pub fn undo(&mut self, item: T::Item)
48    { self.pushed_items.push(item); }
49}
50
51impl<T: Iterator> Iterator for PushbackIter<T>
52{
53    type Item = T::Item;
54    
55    fn next(&mut self) -> Option<Self::Item>
56    {
57        match self.pushed_items.pop() {
58            Some(item) => Some(item),
59            None => self.iter.next(),
60        }
61    }
62}
63
64/// Returns the string slice without the LF character and the CRLF character sequence.
65pub fn str_without_crlf(s: &str) -> &str
66{
67    if s.ends_with('\n') {
68        let s2 = &s[0..(s.len() - 1)];
69        if s2.ends_with('\r') {
70            &s2[0..(s2.len() - 1)]
71        } else {
72            s2
73        }
74    } else {
75        s
76    }
77}
78
79/// Locks the mutex.
80pub fn mutex_lock<T>(mutex: &Mutex<T>) -> Result<MutexGuard<'_, T>>
81{
82    match mutex.lock() {
83        Ok(guard) => Ok(guard),
84        Err(_) => Err(Error::Mutex),
85    }
86}
87
88/// Locks the reader-writer lock with shared read access.
89pub fn rw_lock_read<T>(rw_lock: &RwLock<T>) -> Result<RwLockReadGuard<'_, T>>
90{
91    match rw_lock.read() {
92        Ok(guard) => Ok(guard),
93        Err(_) => Err(Error::RwLockRead),
94    }
95}
96
97/// Locks the reader-writer lock with exclusive write access.
98pub fn rw_lock_write<T>(rw_lock: &RwLock<T>) -> Result<RwLockWriteGuard<'_, T>>
99{
100    match rw_lock.write() {
101        Ok(guard) => Ok(guard),
102        Err(_) => Err(Error::RwLockRead),
103    }
104}
105
106/// Receives an object from the receiver.
107pub fn receiver_recv<T>(receiver: &Receiver<T>) -> Result<T>
108{
109    match receiver.recv() {
110        Ok(object) => Ok(object),
111        Err(_) => Err(Error::Recv),
112    }
113}
114
115fn matrix_res_backend_name() -> matrix::Result<&'static str>
116{
117    let frontend = Frontend::new()?;
118    Ok(frontend.backend().name())
119}
120
121/// Returns the backend name.
122pub fn matrix_backend_name() -> Result<&'static str>
123{
124    match matrix_res_backend_name() {
125        Ok(s) => Ok(s),
126        Err(err) => Err(Error::Matrix(err)),
127    }
128}
129
130fn matrix_res_create_and_set_zeros(row_count: usize, col_count: usize) -> matrix::Result<Matrix>
131{
132    let frontend = Frontend::new()?;
133    Ok(frontend.create_matrix_and_set_zeros(row_count, col_count)?)
134}
135
136/// Creates a matrix and sets the matrix elements on zeros.
137pub fn matrix_create_and_set_zeros(row_count: usize, col_count: usize) -> Result<Matrix>
138{
139    match matrix_res_create_and_set_zeros(row_count, col_count) {
140        Ok(c) => Ok(c),
141        Err(err) => Err(Error::Matrix(err)),
142    }
143}
144
145fn matrix_res_create_and_set_elems(row_count: usize, col_count: usize, elems: &[f32]) -> matrix::Result<Matrix>
146{
147    let frontend = Frontend::new()?;
148    Ok(frontend.create_matrix_and_set_elems(row_count, col_count, elems)?)
149}
150
151/// Creates a matrix and sets the matrix elements.
152pub fn matrix_create_and_set_elems(row_count: usize, col_count: usize, elems: &[f32]) -> Result<Matrix>
153{
154    match matrix_res_create_and_set_elems(row_count, col_count, elems) {
155        Ok(c) => Ok(c),
156        Err(err) => Err(Error::Matrix(err)),
157    }
158}
159
160fn matrix_res_elems_and_transpose_flag(a: &Matrix) -> matrix::Result<(Vec<f32>, bool)>
161{
162    let frontend = Frontend::new()?;
163    Ok(frontend.elems_and_transpose_flag(a)?)
164}
165
166/// Returns the elements and the transpose flag of matrix.
167pub fn matrix_elems_and_transpose_flag(a: &Matrix) -> Result<(Vec<f32>, bool)>
168{
169    match matrix_res_elems_and_transpose_flag(a) {
170        Ok(pair) => Ok(pair),
171        Err(err) => Err(Error::Matrix(err)),
172    }
173}
174
175fn matrix_res_add(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
176{
177    let frontend = Frontend::new()?;
178    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
179    frontend.add(a, b, &c)?;
180    Ok(c)
181}
182
183/// Adds the `b` matrix to the `a` matrix.
184pub fn matrix_add(a: &Matrix, b: &Matrix) -> Result<Matrix>
185{
186    match matrix_res_add(a, b) {
187        Ok(c) => Ok(c),
188        Err(err) => Err(Error::Matrix(err)),
189    }
190}
191
192fn matrix_res_sub(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
193{
194    let frontend = Frontend::new()?;
195    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
196    frontend.sub(a, b, &c)?;
197    Ok(c)
198}
199
200/// Subtracts the `b` matrix from the `a` matrix.
201pub fn matrix_sub(a: &Matrix, b: &Matrix) -> Result<Matrix>
202{
203    match matrix_res_sub(a, b) {
204        Ok(c) => Ok(c),
205        Err(err) => Err(Error::Matrix(err)),
206    }
207}
208
209fn matrix_res_mul(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
210{
211    let frontend = Frontend::new()?;
212    let c = if  frontend.backend().has_cublas() {
213        frontend.create_matrix_and_set_zeros(a.row_count(), b.col_count())?
214    } else {
215        unsafe { frontend.create_matrix(a.row_count(), b.col_count())? }
216    };
217    frontend.mul(a, b, &c)?;
218    Ok(c)
219}
220
221/// Multiplies the `a` matrix by the `b` matrix.
222pub fn matrix_mul(a: &Matrix, b: &Matrix) -> Result<Matrix>
223{
224    match matrix_res_mul(a, b) {
225        Ok(c) => Ok(c),
226        Err(err) => Err(Error::Matrix(err)),
227    }
228}
229
230fn matrix_res_mul_elems(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
231{
232    let frontend = Frontend::new()?;
233    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
234    frontend.mul_elems(a, b, &c)?;
235    Ok(c)
236}
237
238/// Multiplies the `a` matrix elements by the `b` matrix.
239pub fn matrix_mul_elems(a: &Matrix, b: &Matrix) -> Result<Matrix>
240{
241    match matrix_res_mul_elems(a, b) {
242        Ok(c) => Ok(c),
243        Err(err) => Err(Error::Matrix(err)),
244    }
245}
246
247fn matrix_res_div_elems(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
248{
249    let frontend = Frontend::new()?;
250    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
251    frontend.div_elems(a, b, &c)?;
252    Ok(c)
253}
254
255/// Divides the `a` matrix elements by the `b` matrix.
256pub fn matrix_div_elems(a: &Matrix, b: &Matrix) -> Result<Matrix>
257{
258    match matrix_res_div_elems(a, b) {
259        Ok(c) => Ok(c),
260        Err(err) => Err(Error::Matrix(err)),
261    }
262}
263
264fn matrix_res_add_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
265{
266    let frontend = Frontend::new()?;
267    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
268    frontend.add_for_scalar(a, b, &c)?;
269    Ok(c)
270}
271
272/// Adds the `b` scalar to the `a` matrix.
273pub fn matrix_add_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
274{
275    match matrix_res_add_for_scalar(a, b) {
276        Ok(c) => Ok(c),
277        Err(err) => Err(Error::Matrix(err)),
278    }
279}
280
281fn matrix_res_sub_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
282{
283    let frontend = Frontend::new()?;
284    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
285    frontend.sub_for_scalar(a, b, &c)?;
286    Ok(c)
287}
288
289/// Subtracts the `b` scalar from the `a` matrix.
290pub fn matrix_sub_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
291{
292    match matrix_res_sub_for_scalar(a, b) {
293        Ok(c) => Ok(c),
294        Err(err) => Err(Error::Matrix(err)),
295    }
296}
297
298fn matrix_res_rsub_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
299{
300    let frontend = Frontend::new()?;
301    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
302    frontend.rsub_for_scalar(a, b, &c)?;
303    Ok(c)
304}
305
306/// Subtracts the `a` matrix from the `b` scalar.
307pub fn matrix_rsub_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
308{
309    match matrix_res_rsub_for_scalar(a, b) {
310        Ok(c) => Ok(c),
311        Err(err) => Err(Error::Matrix(err)),
312    }
313}
314
315fn matrix_res_mul_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
316{
317    let frontend = Frontend::new()?;
318    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
319    frontend.mul_for_scalar(a, b, &c)?;
320    Ok(c)
321}
322
323/// Multiplies the `a` matrix by the `b` scalar.
324pub fn matrix_mul_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
325{
326    match matrix_res_mul_for_scalar(a, b) {
327        Ok(c) => Ok(c),
328        Err(err) => Err(Error::Matrix(err)),
329    }
330}
331
332fn matrix_res_div_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
333{
334    let frontend = Frontend::new()?;
335    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
336    frontend.div_for_scalar(a, b, &c)?;
337    Ok(c)
338}
339
340/// Divides the `a` matrix by the `b` scalar.
341pub fn matrix_div_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
342{
343    match matrix_res_div_for_scalar(a, b) {
344        Ok(c) => Ok(c),
345        Err(err) => Err(Error::Matrix(err)),
346    }
347}
348
349fn matrix_res_rdiv_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
350{
351    let frontend = Frontend::new()?;
352    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
353    frontend.rdiv_for_scalar(a, b, &c)?;
354    Ok(c)
355}
356
357/// Divides the `b` scalar by the `a` matrix elements.
358pub fn matrix_rdiv_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
359{
360    match matrix_res_rdiv_for_scalar(a, b) {
361        Ok(c) => Ok(c),
362        Err(err) => Err(Error::Matrix(err)),
363    }
364}
365
366fn matrix_res_sigmoid(a: &Matrix) -> matrix::Result<Matrix>
367{
368    let frontend = Frontend::new()?;
369    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
370    frontend.sigmoid(a, &b)?;
371    Ok(b)
372}
373
374/// Calculates sigmoid function for the `a` matrix.
375pub fn matrix_sigmoid(a: &Matrix) -> Result<Matrix>
376{
377    match matrix_res_sigmoid(a) {
378        Ok(b) => Ok(b),
379        Err(err) => Err(Error::Matrix(err)),
380    }
381}
382
383fn matrix_res_tanh(a: &Matrix) -> matrix::Result<Matrix>
384{
385    let frontend = Frontend::new()?;
386    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
387    frontend.tanh(a, &b)?;
388    Ok(b)
389}
390
391/// Calculates hyperbolic tangent function for the `a` matrix.
392pub fn matrix_tanh(a: &Matrix) -> Result<Matrix>
393{
394    match matrix_res_tanh(a) {
395        Ok(b) => Ok(b),
396        Err(err) => Err(Error::Matrix(err)),
397    }
398}
399
400fn matrix_res_swish(a: &Matrix) -> matrix::Result<Matrix>
401{
402    let frontend = Frontend::new()?;
403    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
404    frontend.swish(a, &b)?;
405    Ok(b)
406}
407
408/// Calculates swish function for the `a` matrix.
409pub fn matrix_swish(a: &Matrix) -> Result<Matrix>
410{
411    match matrix_res_swish(a) {
412        Ok(b) => Ok(b),
413        Err(err) => Err(Error::Matrix(err)),
414    }
415}
416
417fn matrix_res_softmax(a: &Matrix) -> matrix::Result<Matrix>
418{
419    let frontend = Frontend::new()?;
420    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
421    frontend.softmax(a, &b)?;
422    Ok(b)
423}
424
425/// Calculates softmax function for the `a` matrix.
426pub fn matrix_softmax(a: &Matrix) -> Result<Matrix>
427{
428    match matrix_res_softmax(a) {
429        Ok(b) => Ok(b),
430        Err(err) => Err(Error::Matrix(err)),
431    }
432}
433
434fn matrix_res_sqrt(a: &Matrix) -> matrix::Result<Matrix>
435{
436    let frontend = Frontend::new()?;
437    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
438    frontend.sqrt(a, &b)?;
439    Ok(b)
440}
441
442/// Calculates square roots of the `a` matrix elements.
443pub fn matrix_sqrt(a: &Matrix) -> Result<Matrix>
444{
445    match matrix_res_sqrt(a) {
446        Ok(b) => Ok(b),
447        Err(err) => Err(Error::Matrix(err)),
448    }
449}
450
451fn matrix_res_really_transpose(a: &Matrix) -> matrix::Result<Matrix>
452{
453    let frontend = Frontend::new()?;
454    let b = unsafe { frontend.create_matrix(a.col_count(), a.row_count())? };
455    frontend.really_transpose(a, &b)?;
456    Ok(b)
457}
458
459/// Indeed transposes the `a` matrix.
460pub fn matrix_really_transpose(a: &Matrix) -> Result<Matrix>
461{
462    match matrix_res_really_transpose(a) {
463        Ok(b) => Ok(b),
464        Err(err) => Err(Error::Matrix(err)),
465    }
466}
467
468fn matrix_res_repeat(a: &Matrix, n: usize) -> matrix::Result<Option<Matrix>>
469{
470    if a.col_count() != 1 && a.row_count() != 1 {
471        return Ok(None);
472    }
473    let frontend = Frontend::new()?;
474    let b = if a.col_count() == 1 {
475        unsafe { frontend.create_matrix(a.row_count(), n)? }
476    } else {
477        unsafe { frontend.create_matrix(n, a.col_count())? }
478    };
479    frontend.repeat(a, &b)?;
480    Ok(Some(b))
481}
482
483/// Repeats the `a` vector as column or a row.
484pub fn matrix_repeat(a: &Matrix, n: usize) -> Result<Option<Matrix>>
485{
486    match matrix_res_repeat(a, n) {
487        Ok(b) => Ok(b),
488        Err(err) => Err(Error::Matrix(err)),
489    }
490}
491
492fn matrix_res_to_matrix_array(a: &Matrix) -> matrix::Result<Object>
493{
494    let frontend = Frontend::new()?;
495    let xs = frontend.elems_and_transpose_flag(a)?.0;
496    let transpose_flag = if a.is_transposed() {
497        TransposeFlag::Transpose
498    } else {
499        TransposeFlag::NoTranspose
500    };
501    Ok(Object::MatrixArray(a.row_count(), a.col_count(), transpose_flag, xs))
502}
503
504/// Converts the `a` matrix to the matrix array.
505pub fn matrix_to_matrix_array(a: &Matrix) -> Result<Object>
506{
507    match matrix_res_to_matrix_array(a) {
508        Ok(object) => Ok(object),
509        Err(err) => Err(Error::Matrix(err)),
510    }
511}
512
513fn matrix_res_abs(a: &Matrix) -> matrix::Result<Matrix>
514{
515    let frontend = Frontend::new()?;
516    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
517    frontend.abs(a, &b)?;
518    Ok(b)
519}
520
521/// Calculates absolute values of the `a` matrix elements.
522pub fn matrix_abs(a: &Matrix) -> Result<Matrix>
523{
524    match matrix_res_abs(a) {
525        Ok(b) => Ok(b),
526        Err(err) => Err(Error::Matrix(err)),
527    }
528}
529
530fn matrix_res_pow(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
531{
532    let frontend = Frontend::new()?;
533    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
534    frontend.pow(a, b, &c)?;
535    Ok(c)
536}
537
538/// Raises the `a` matrix elements to the power of the `b` matrix elements.
539pub fn matrix_pow(a: &Matrix, b: &Matrix) -> Result<Matrix>
540{
541    match matrix_res_pow(a, b) {
542        Ok(c) => Ok(c),
543        Err(err) => Err(Error::Matrix(err)),
544    }
545}
546
547fn matrix_res_pow_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
548{
549    let frontend = Frontend::new()?;
550    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
551    frontend.pow_for_scalar(a, b, &c)?;
552    Ok(c)
553}
554
555/// Raises the `a` matrix elements to the power of the `b` scalar.
556pub fn matrix_pow_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
557{
558    match matrix_res_pow_for_scalar(a, b) {
559        Ok(c) => Ok(c),
560        Err(err) => Err(Error::Matrix(err)),
561    }
562}
563
564fn matrix_res_rpow_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
565{
566    let frontend = Frontend::new()?;
567    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
568    frontend.rpow_for_scalar(a, b, &c)?;
569    Ok(c)
570}
571
572/// Raises the `b` scalar to the power of the `a` matrix elements.
573pub fn matrix_rpow_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
574{
575    match matrix_res_rpow_for_scalar(a, b) {
576        Ok(c) => Ok(c),
577        Err(err) => Err(Error::Matrix(err)),
578    }
579}
580
581fn matrix_res_exp(a: &Matrix) -> matrix::Result<Matrix>
582{
583    let frontend = Frontend::new()?;
584    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
585    frontend.exp(a, &b)?;
586    Ok(b)
587}
588
589/// Calculates exponential function for the `a` matrix elements.
590pub fn matrix_exp(a: &Matrix) -> Result<Matrix>
591{
592    match matrix_res_exp(a) {
593        Ok(b) => Ok(b),
594        Err(err) => Err(Error::Matrix(err)),
595    }
596}
597
598fn matrix_res_ln(a: &Matrix) -> matrix::Result<Matrix>
599{
600    let frontend = Frontend::new()?;
601    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
602    frontend.ln(a, &b)?;
603    Ok(b)
604}
605
606/// Calculates natural logarithm of the `a` matrix elements.
607pub fn matrix_ln(a: &Matrix) -> Result<Matrix>
608{
609    match matrix_res_ln(a) {
610        Ok(b) => Ok(b),
611        Err(err) => Err(Error::Matrix(err)),
612    }
613}
614
615fn matrix_res_log2(a: &Matrix) -> matrix::Result<Matrix>
616{
617    let frontend = Frontend::new()?;
618    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
619    frontend.log2(a, &b)?;
620    Ok(b)
621}
622
623/// Calculates base 2 logarithm of the `a` matrix elements.
624pub fn matrix_log2(a: &Matrix) -> Result<Matrix>
625{
626    match matrix_res_log2(a) {
627        Ok(b) => Ok(b),
628        Err(err) => Err(Error::Matrix(err)),
629    }
630}
631
632fn matrix_res_log10(a: &Matrix) -> matrix::Result<Matrix>
633{
634    let frontend = Frontend::new()?;
635    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
636    frontend.log10(a, &b)?;
637    Ok(b)
638}
639
640/// Calculates base 10 logarithm of the `a` matrix elements.
641pub fn matrix_log10(a: &Matrix) -> Result<Matrix>
642{
643    match matrix_res_log10(a) {
644        Ok(b) => Ok(b),
645        Err(err) => Err(Error::Matrix(err)),
646    }
647}
648
649fn matrix_res_sin(a: &Matrix) -> matrix::Result<Matrix>
650{
651    let frontend = Frontend::new()?;
652    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
653    frontend.sin(a, &b)?;
654    Ok(b)
655}
656
657/// Calculates sine function for the `a` matrix.
658pub fn matrix_sin(a: &Matrix) -> Result<Matrix>
659{
660    match matrix_res_sin(a) {
661        Ok(b) => Ok(b),
662        Err(err) => Err(Error::Matrix(err)),
663    }
664}
665
666fn matrix_res_cos(a: &Matrix) -> matrix::Result<Matrix>
667{
668    let frontend = Frontend::new()?;
669    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
670    frontend.cos(a, &b)?;
671    Ok(b)
672}
673
674/// Calculates cosine function for the `a` matrix.
675pub fn matrix_cos(a: &Matrix) -> Result<Matrix>
676{
677    match matrix_res_cos(a) {
678        Ok(b) => Ok(b),
679        Err(err) => Err(Error::Matrix(err)),
680    }
681}
682
683fn matrix_res_tan(a: &Matrix) -> matrix::Result<Matrix>
684{
685    let frontend = Frontend::new()?;
686    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
687    frontend.tan(a, &b)?;
688    Ok(b)
689}
690
691/// Calculates tangent function for the `a` matrix.
692pub fn matrix_tan(a: &Matrix) -> Result<Matrix>
693{
694    match matrix_res_tan(a) {
695        Ok(b) => Ok(b),
696        Err(err) => Err(Error::Matrix(err)),
697    }
698}
699
700fn matrix_res_asin(a: &Matrix) -> matrix::Result<Matrix>
701{
702    let frontend = Frontend::new()?;
703    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
704    frontend.asin(a, &b)?;
705    Ok(b)
706}
707
708/// Calculates arcsine function for the `a` matrix.
709pub fn matrix_asin(a: &Matrix) -> Result<Matrix>
710{
711    match matrix_res_asin(a) {
712        Ok(b) => Ok(b),
713        Err(err) => Err(Error::Matrix(err)),
714    }
715}
716
717fn matrix_res_acos(a: &Matrix) -> matrix::Result<Matrix>
718{
719    let frontend = Frontend::new()?;
720    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
721    frontend.acos(a, &b)?;
722    Ok(b)
723}
724
725/// Calculates arccosine function for the `a` matrix.
726pub fn matrix_acos(a: &Matrix) -> Result<Matrix>
727{
728    match matrix_res_acos(a) {
729        Ok(b) => Ok(b),
730        Err(err) => Err(Error::Matrix(err)),
731    }
732}
733
734fn matrix_res_atan(a: &Matrix) -> matrix::Result<Matrix>
735{
736    let frontend = Frontend::new()?;
737    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
738    frontend.atan(a, &b)?;
739    Ok(b)
740}
741
742/// Calculates arctangent function for the `a` matrix.
743pub fn matrix_atan(a: &Matrix) -> Result<Matrix>
744{
745    match matrix_res_atan(a) {
746        Ok(b) => Ok(b),
747        Err(err) => Err(Error::Matrix(err)),
748    }
749}
750
751fn matrix_res_atan2(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
752{
753    let frontend = Frontend::new()?;
754    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
755    frontend.atan2(a, b, &c)?;
756    Ok(c)
757}
758
759/// Calculates arctangent function for the `a` matrix elements and the `b` matrix elements.
760pub fn matrix_atan2(a: &Matrix, b: &Matrix) -> Result<Matrix>
761{
762    match matrix_res_atan2(a, b) {
763        Ok(c) => Ok(c),
764        Err(err) => Err(Error::Matrix(err)),
765    }
766}
767
768fn matrix_res_atan2_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
769{
770    let frontend = Frontend::new()?;
771    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
772    frontend.atan2_for_scalar(a, b, &c)?;
773    Ok(c)
774}
775
776/// Calculates arctangent function for the `a` matrix elements and the `b` scalar.
777pub fn matrix_atan2_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
778{
779    match matrix_res_atan2_for_scalar(a, b) {
780        Ok(c) => Ok(c),
781        Err(err) => Err(Error::Matrix(err)),
782    }
783}
784
785fn matrix_res_ratan2_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
786{
787    let frontend = Frontend::new()?;
788    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
789    frontend.ratan2_for_scalar(a, b, &c)?;
790    Ok(c)
791}
792
793/// Calculates arctangent function for the `b` scalar and the `a` matrix elements.
794pub fn matrix_ratan2_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
795{
796    match matrix_res_ratan2_for_scalar(a, b) {
797        Ok(c) => Ok(c),
798        Err(err) => Err(Error::Matrix(err)),
799    }
800}
801
802fn matrix_res_sinh(a: &Matrix) -> matrix::Result<Matrix>
803{
804    let frontend = Frontend::new()?;
805    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
806    frontend.sinh(a, &b)?;
807    Ok(b)
808}
809
810/// Calculates hyperbolic sine function for the `a` matrix.
811pub fn matrix_sinh(a: &Matrix) -> Result<Matrix>
812{
813    match matrix_res_sinh(a) {
814        Ok(b) => Ok(b),
815        Err(err) => Err(Error::Matrix(err)),
816    }
817}
818
819fn matrix_res_cosh(a: &Matrix) -> matrix::Result<Matrix>
820{
821    let frontend = Frontend::new()?;
822    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
823    frontend.cosh(a, &b)?;
824    Ok(b)
825}
826
827/// Calculates hyperbolic cosine function for the `a` matrix.
828pub fn matrix_cosh(a: &Matrix) -> Result<Matrix>
829{
830    match matrix_res_cosh(a) {
831        Ok(b) => Ok(b),
832        Err(err) => Err(Error::Matrix(err)),
833    }
834}
835
836fn matrix_res_asinh(a: &Matrix) -> matrix::Result<Matrix>
837{
838    let frontend = Frontend::new()?;
839    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
840    frontend.asinh(a, &b)?;
841    Ok(b)
842}
843
844/// Calculates inverse hyperbolic sine function for the `a` matrix.
845pub fn matrix_asinh(a: &Matrix) -> Result<Matrix>
846{
847    match matrix_res_asinh(a) {
848        Ok(b) => Ok(b),
849        Err(err) => Err(Error::Matrix(err)),
850    }
851}
852
853fn matrix_res_acosh(a: &Matrix) -> matrix::Result<Matrix>
854{
855    let frontend = Frontend::new()?;
856    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
857    frontend.acosh(a, &b)?;
858    Ok(b)
859}
860
861/// Calculates inverse hyperbolic cosine function for the `a` matrix.
862pub fn matrix_acosh(a: &Matrix) -> Result<Matrix>
863{
864    match matrix_res_acosh(a) {
865        Ok(b) => Ok(b),
866        Err(err) => Err(Error::Matrix(err)),
867    }
868}
869
870fn matrix_res_atanh(a: &Matrix) -> matrix::Result<Matrix>
871{
872    let frontend = Frontend::new()?;
873    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
874    frontend.atanh(a, &b)?;
875    Ok(b)
876}
877
878/// Calculates inverse hyperbolic tangent function for the `a` matrix.
879pub fn matrix_atanh(a: &Matrix) -> Result<Matrix>
880{
881    match matrix_res_atanh(a) {
882        Ok(b) => Ok(b),
883        Err(err) => Err(Error::Matrix(err)),
884    }
885}
886
887fn matrix_res_signum(a: &Matrix) -> matrix::Result<Matrix>
888{
889    let frontend = Frontend::new()?;
890    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
891    frontend.signum(a, &b)?;
892    Ok(b)
893}
894
895/// Calculates signum function for the `a` matrix.
896pub fn matrix_signum(a: &Matrix) -> Result<Matrix>
897{
898    match matrix_res_signum(a) {
899        Ok(b) => Ok(b),
900        Err(err) => Err(Error::Matrix(err)),
901    }
902}
903
904fn matrix_res_ceil(a: &Matrix) -> matrix::Result<Matrix>
905{
906    let frontend = Frontend::new()?;
907    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
908    frontend.ceil(a, &b)?;
909    Ok(b)
910}
911
912/// Calculates ceil function for the `a` matrix.
913pub fn matrix_ceil(a: &Matrix) -> Result<Matrix>
914{
915    match matrix_res_ceil(a) {
916        Ok(b) => Ok(b),
917        Err(err) => Err(Error::Matrix(err)),
918    }
919}
920
921fn matrix_res_floor(a: &Matrix) -> matrix::Result<Matrix>
922{
923    let frontend = Frontend::new()?;
924    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
925    frontend.floor(a, &b)?;
926    Ok(b)
927}
928
929/// Calculates floor function for the `a` matrix.
930pub fn matrix_floor(a: &Matrix) -> Result<Matrix>
931{
932    match matrix_res_floor(a) {
933        Ok(b) => Ok(b),
934        Err(err) => Err(Error::Matrix(err)),
935    }
936}
937
938fn matrix_res_round(a: &Matrix) -> matrix::Result<Matrix>
939{
940    let frontend = Frontend::new()?;
941    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
942    frontend.round(a, &b)?;
943    Ok(b)
944}
945
946/// Calculates round function for the `a` matrix.
947pub fn matrix_round(a: &Matrix) -> Result<Matrix>
948{
949    match matrix_res_round(a) {
950        Ok(b) => Ok(b),
951        Err(err) => Err(Error::Matrix(err)),
952    }
953}
954
955fn matrix_res_trunc(a: &Matrix) -> matrix::Result<Matrix>
956{
957    let frontend = Frontend::new()?;
958    let b = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
959    frontend.trunc(a, &b)?;
960    Ok(b)
961}
962
963/// Calculates trunc function for the `a` matrix.
964pub fn matrix_trunc(a: &Matrix) -> Result<Matrix>
965{
966    match matrix_res_trunc(a) {
967        Ok(b) => Ok(b),
968        Err(err) => Err(Error::Matrix(err)),
969    }
970}
971
972fn matrix_res_max(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
973{
974    let frontend = Frontend::new()?;
975    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
976    frontend.max(a, b, &c)?;
977    Ok(c)
978}
979
980/// Finds maximum values between the `a` matrix elements and the `b` matrix elements.
981pub fn matrix_max(a: &Matrix, b: &Matrix) -> Result<Matrix>
982{
983    match matrix_res_max(a, b) {
984        Ok(c) => Ok(c),
985        Err(err) => Err(Error::Matrix(err)),
986    }
987}
988
989fn matrix_res_max_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
990{
991    let frontend = Frontend::new()?;
992    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
993    frontend.max_for_scalar(a, b, &c)?;
994    Ok(c)
995}
996
997/// Finds maximum values between the `a` matrix elements and the `b` scalar.
998pub fn matrix_max_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
999{
1000    match matrix_res_max_for_scalar(a, b) {
1001        Ok(c) => Ok(c),
1002        Err(err) => Err(Error::Matrix(err)),
1003    }
1004}
1005
1006fn matrix_res_min(a: &Matrix, b: &Matrix) -> matrix::Result<Matrix>
1007{
1008    let frontend = Frontend::new()?;
1009    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
1010    frontend.min(a, b, &c)?;
1011    Ok(c)
1012}
1013
1014/// Finds minimum values between the `a` matrix elements and the `b` matrix elements.
1015pub fn matrix_min(a: &Matrix, b: &Matrix) -> Result<Matrix>
1016{
1017    match matrix_res_min(a, b) {
1018        Ok(c) => Ok(c),
1019        Err(err) => Err(Error::Matrix(err)),
1020    }
1021}
1022
1023fn matrix_res_min_for_scalar(a: &Matrix, b: f32) -> matrix::Result<Matrix>
1024{
1025    let frontend = Frontend::new()?;
1026    let c = unsafe { frontend.create_matrix(a.row_count(), a.col_count())? };
1027    frontend.min_for_scalar(a, b, &c)?;
1028    Ok(c)
1029}
1030
1031/// Finds minimum values between the `a` matrix elements and the `b` scalar.
1032pub fn matrix_min_for_scalar(a: &Matrix, b: f32) -> Result<Matrix>
1033{
1034    match matrix_res_min_for_scalar(a, b) {
1035        Ok(c) => Ok(c),
1036        Err(err) => Err(Error::Matrix(err)),
1037    }
1038}
1039
1040/// Converts the string slice to an URL name.
1041///
1042/// The character of string slice is escaped if the character of string slice isn't an URL
1043/// unreserved character. If the path flag is set, slash character isn't escaped.
1044pub fn str_to_url_name(s: &str, is_path: bool) -> String
1045{
1046    let mut url_name = String::new();
1047    for b in s.as_bytes() {
1048        match b {
1049            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'.' | b'_' | b'~' => url_name.push(*b as char),
1050            b'/' if is_path => url_name.push(*b as char),
1051            _ => url_name.push_str(format!("%{:02X}", b).as_str()),
1052        }
1053    }
1054    url_name
1055}
1056
1057/// Converts the string slice to an identifier.
1058///
1059/// If the character of string slice isn't identifier character, the character of string slice is
1060/// replaced by a `_` character.
1061pub fn str_to_ident(s: &str) -> String
1062{
1063    let mut ident = String::new();
1064    let mut is_first = true;
1065    for c in s.chars() {
1066        if is_first {
1067            if c.is_alphabetic() || c == '_' {
1068                ident.push(c);
1069            } else if c.is_numeric() {
1070                ident.push('_');
1071                ident.push(c);
1072            } else {
1073                ident.push('_');
1074            }
1075        } else {
1076            if c.is_alphanumeric() || c == '_' {
1077                ident.push(c);
1078            } else {
1079                ident.push('_');
1080            }
1081        }
1082        is_first = false;
1083    }
1084    ident
1085}
1086
1087/// Prints the error to the standard error.
1088pub fn eprint_error(err: &Error)
1089{ eprintln!("{}", err); }
1090
1091/// Prints the error with the stac trace to the standard error.
1092pub fn eprint_error_with_stack_trace(err: &Error, stack_trace: &[(Option<Value>, Pos)])
1093{
1094    eprintln!("{}", err);
1095    for (fun_value, pos) in stack_trace {
1096        match fun_value {
1097            Some(fun_value) => eprintln!("    at {} ({}: {}.{})", fun_value, pos.path, pos.line, pos.column),
1098            None => eprintln!("    at {}: {}.{}", pos.path, pos.line, pos.column),
1099        }
1100    }
1101}