blas_array2/blas1/
iamax.rs

1use crate::ffi::{self, blas_int};
2use crate::util::*;
3use derive_builder::Builder;
4use ndarray::prelude::*;
5
6/* #region BLAS func */
7
8pub trait IAMAXNum: BLASFloat {
9    unsafe fn iamax(n: *const blas_int, x: *const Self, incx: *const blas_int) -> blas_int;
10}
11
12macro_rules! impl_func {
13    ($type: ty, $func: ident) => {
14        impl IAMAXNum for $type
15        where
16            $type: BLASFloat,
17        {
18            unsafe fn iamax(n: *const blas_int, x: *const Self, incx: *const blas_int) -> blas_int {
19                ffi::$func(n, x, incx)
20            }
21        }
22    };
23}
24
25impl_func!(f32, isamax_);
26impl_func!(f64, idamax_);
27impl_func!(c32, icamax_);
28impl_func!(c64, izamax_);
29
30/* #endregion */
31
32/* #region BLAS driver */
33
34pub struct IAMAX_Driver<'x, F>
35where
36    F: IAMAXNum,
37{
38    n: blas_int,
39    x: ArrayView1<'x, F>,
40    incx: blas_int,
41}
42
43impl<'x, F> IAMAX_Driver<'x, F>
44where
45    F: IAMAXNum,
46{
47    pub fn run_blas(self) -> Result<usize, BLASError> {
48        let Self { n, x, incx } = self;
49        let x_ptr = x.as_ptr();
50        if n == 0 {
51            return Ok(0);
52        } else {
53            // 0-index for C/Rust v.s. 1-index for Fortran
54            return unsafe { Ok((F::iamax(&n, x_ptr, &incx) - 1).try_into()?) };
55        }
56    }
57}
58
59/* #endregion */
60
61/* #region BLAS builder */
62
63#[derive(Builder)]
64#[builder(pattern = "owned", build_fn(error = "BLASError"), no_std)]
65pub struct IAMAX_<'x, F>
66where
67    F: IAMAXNum,
68{
69    pub x: ArrayView1<'x, F>,
70}
71
72impl<'x, F> IAMAX_<'x, F>
73where
74    F: IAMAXNum,
75{
76    pub fn driver(self) -> Result<IAMAX_Driver<'x, F>, BLASError> {
77        let Self { x } = self;
78        let incx = x.stride_of(Axis(0));
79        let n = x.len_of(Axis(0));
80        let driver = IAMAX_Driver { n: n.try_into()?, x, incx: incx.try_into()? };
81        return Ok(driver);
82    }
83}
84
85/* #region BLAS wrapper */
86
87pub type IAMAX<'x, F> = IAMAX_Builder<'x, F>;
88pub type ISAMAX<'x> = IAMAX<'x, f32>;
89pub type IDAMAX<'x> = IAMAX<'x, f64>;
90pub type ICAMAX<'x> = IAMAX<'x, c32>;
91pub type IZAMAX<'x> = IAMAX<'x, c64>;
92
93impl<'x, F> IAMAX<'x, F>
94where
95    F: IAMAXNum,
96{
97    pub fn run(self) -> Result<usize, BLASError> {
98        self.build()?.driver()?.run_blas()
99    }
100}
101
102/* #endregion */