Skip to main content

bixverse_core/utils/
traits.rs

1//! Various traits in bixverse
2
3use faer::traits::{ComplexField, RealField};
4use num_traits::float::TotalOrder;
5use num_traits::{Float, FromPrimitive, ToPrimitive};
6
7use std::fmt::Display;
8
9use std::ops::{AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
10
11///////////////////
12// Numeric trait //
13///////////////////
14
15/// Trait for floating-point types used in Bixverse. Has all of the common
16/// floating-point operations and traits.
17pub trait BixverseFloat:
18    Float
19    + FromPrimitive
20    + ToPrimitive
21    + ComplexField
22    + Copy
23    + 'static
24    + RealField
25    + AddAssign
26    + DivAssign
27    + SubAssign
28    + MulAssign
29    + Div
30    + Display
31    + Sub
32    + Mul
33    + Div
34    + TotalOrder
35    + Clone
36{
37}
38
39impl<T> BixverseFloat for T where
40    T: Float
41        + FromPrimitive
42        + ToPrimitive
43        + ComplexField
44        + Copy
45        + 'static
46        + RealField
47        + AddAssign
48        + DivAssign
49        + SubAssign
50        + MulAssign
51        + Div
52        + Display
53        + Sub
54        + Mul
55        + Div
56        + TotalOrder
57        + Clone
58{
59}
60
61pub use bixverse_sparse::traits::{BixverseNumeric, VecIndexCast};
62
63////////////////////
64// R vector stuff //
65////////////////////
66
67/// Converts vectors between integer types for R compatibility.
68pub trait VecConvert<U> {
69    /// Converts usize vectors into i32 for fast R transfer
70    fn r_int_convert(self) -> Vec<U>;
71
72    /// Converts vectors from usize to i32, while adding one (shifting from
73    /// 0-indexed data to 1-indexed data) or vice versa from i32 to usize while
74    /// subtracting 1 (shifting from 1-indexed data to 0-indexed data).
75    fn r_int_convert_shift(self) -> Vec<U>;
76}
77
78impl VecConvert<i32> for Vec<usize> {
79    fn r_int_convert(self) -> Vec<i32> {
80        self.into_iter().map(|x| x as i32).collect()
81    }
82    fn r_int_convert_shift(self) -> Vec<i32> {
83        self.into_iter().map(|x| (x as i32) + 1).collect()
84    }
85}
86
87impl VecConvert<i32> for &[&usize] {
88    fn r_int_convert(self) -> Vec<i32> {
89        self.iter().map(|&&x| x as i32).collect()
90    }
91    fn r_int_convert_shift(self) -> Vec<i32> {
92        self.iter().map(|&&x| (x as i32) + 1).collect()
93    }
94}
95
96impl VecConvert<i32> for Vec<u32> {
97    fn r_int_convert(self) -> Vec<i32> {
98        self.into_iter().map(|x| x as i32).collect()
99    }
100    fn r_int_convert_shift(self) -> Vec<i32> {
101        self.into_iter().map(|x| (x as i32) + 1).collect()
102    }
103}
104
105impl VecConvert<usize> for Vec<i32> {
106    fn r_int_convert(self) -> Vec<usize> {
107        self.into_iter().map(|x| x as usize).collect()
108    }
109    fn r_int_convert_shift(self) -> Vec<usize> {
110        self.into_iter().map(|x| (x - 1) as usize).collect()
111    }
112}
113
114impl VecConvert<i32> for &[usize] {
115    fn r_int_convert(self) -> Vec<i32> {
116        self.iter().map(|&x| x as i32).collect()
117    }
118    fn r_int_convert_shift(self) -> Vec<i32> {
119        self.iter().map(|&x| (x as i32) + 1).collect()
120    }
121}
122
123impl VecConvert<usize> for &[i32] {
124    fn r_int_convert(self) -> Vec<usize> {
125        self.iter().map(|&x| x as usize).collect()
126    }
127    fn r_int_convert_shift(self) -> Vec<usize> {
128        self.iter().map(|&x| (x - 1) as usize).collect()
129    }
130}
131
132/// Converts vectors between floating-point types for R compatibility.
133pub trait VecFloatConvert<U> {
134    /// Converts the R double vectors from/to f64 to f32
135    fn r_float_convert(self) -> Vec<U>;
136}
137
138impl VecFloatConvert<f32> for Vec<f64> {
139    fn r_float_convert(self) -> Vec<f32> {
140        self.into_iter().map(|x| x as f32).collect()
141    }
142}
143
144impl VecFloatConvert<f64> for Vec<f32> {
145    fn r_float_convert(self) -> Vec<f64> {
146        self.into_iter().map(|x| x as f64).collect()
147    }
148}
149
150impl VecFloatConvert<f64> for &[f32] {
151    fn r_float_convert(self) -> Vec<f64> {
152        self.iter().map(|x| *x as f64).collect()
153    }
154}
155
156impl VecFloatConvert<f32> for &[f64] {
157    fn r_float_convert(self) -> Vec<f32> {
158        self.iter().map(|&x| x as f32).collect()
159    }
160}