deki_core/
lib.rs

1pub use maflow::*;
2pub use type_cell::*;
3pub use derive_more;
4pub use buns;
5
6
7// Renames \\
8
9    pub use std::marker::PhantomData as Ghost;
10    pub use derive_new::new as Constructor;
11    pub use extension_traits::extension as ext;
12    pub use derive_more as drv;
13    pub use buns::sandwich;
14    pub type Str = &'static str;
15
16// Traits \\
17
18    /// 'Short form' for: 'static+Send+Sync
19    pub trait Syncable:'static+Send+Sync {}
20    impl <T:'static+Send+Sync> Syncable for T {}
21
22    pub trait DefaultClear: Default {
23        fn clear(&mut self){*self = Self::default();}
24    }
25    impl <A:Default> DefaultClear for A {}
26
27
28// Extensions  \\
29use std::{iter::{zip, Zip}, ops::{Add, Range, RangeInclusive, Rem, Sub}, slice::Iter, vec::IntoIter};
30
31    #[ext(pub trait RangeOffset)]
32    impl <Idx:Clone+Add<Output=Idx>> RangeInclusive<Idx> {
33        fn offset(&self,rhs:Idx) -> Self {
34            self.start().clone()+rhs.clone()
35            ..=self.end().clone()+rhs.clone()
36        }
37    }
38
39    impl <Idx:Clone+Add<Output=Idx>> RangeOffset<Idx> for Range<Idx> {
40        fn offset(&self,rhs:Idx) -> Self {
41            self.start.clone()+rhs.clone()..self.end.clone()+rhs.clone()
42        }
43    }
44
45
46// Stack Map \\
47
48    /// Keys keep the order they're added in.
49    #[derive(Constructor)]
50    pub struct StackMap<K:PartialEq,V> {
51        #[new(default)] pub keys: Vec<K>,
52        #[new(default)] pub value: Vec<V>
53    }
54
55    impl <K:PartialEq,V:Default> StackMap<K,V> {
56        /// - get a mutable reference to the value of a key
57        /// - not in map? insert default value before returning
58        pub fn entry(&mut self,key:K) -> &mut V {
59            match self.key_idx(&key){
60                None => {
61                    self.keys.push(key);
62                    self.value.push(V::default());
63                    self.value.last_mut().unwrap()
64                }
65                Some(id) => &mut self.value[id]
66            }
67        }
68    }
69
70    impl <K:PartialEq,V> StackMap<K,V> {
71        /// - Some(idx): index of requested key
72        /// - None: not part of the map
73        pub fn key_idx(&self,key:&K) -> Option<usize> {
74            self.keys.iter().enumerate().find_map(|(id,k)|if key==k {Some(id)} else {None})
75        }
76        /// read-only reference iterator
77        pub fn iter(&self) -> Zip<Iter<K>,Iter<V>> {
78            zip(self.keys.iter(),self.value.iter())
79        }
80        /// consuming iterator
81        pub fn into_iter(self) -> Zip<IntoIter<K>,IntoIter<V>> {
82            zip(self.keys.into_iter(),self.value.into_iter())
83        }
84        /// true if empty
85        pub fn is_empty(&self) -> bool {self.keys.is_empty()}
86    }
87
88    impl <K:PartialEq,V:Default> Default for StackMap<K,V> {
89        fn default() -> Self {Self::new()}
90    }
91
92
93// Cycling Addition \\
94
95    buns::sandwich!{paste!{
96        #[inline]
97        pub fn [<quick_cycle_ ^0>]<A>(cur:A,rhs:A,min:A,max:A) -> A 
98        where A: Clone
99            + Add<Output=A>
100            + Sub<Output=A>
101            + Rem<Output=A>
102        {
103            let len = max.sub(min.clone());
104            let bas = cur.sub(min.clone()).add(len.clone());
105            let unc = bas.^0(rhs.rem(len.clone()));
106            min.add(unc.rem(len))
107        }
108    } #sub #add }
109
110    pub trait CycleMath {
111        /// quick cycling addition within a exclusive range, which assumes:
112        /// - current value is within the range
113        /// - range length < _::MAX/3
114        fn add_qucy(self,rhs:Self,min:Self,max:Self) -> Self;
115        /// quick cycling subtraction within a exclusive range, which assumes:
116        /// - current value is within the range
117        /// - range length < _::MAX/3
118        fn sub_qucy(self,rhs:Self,min:Self,max:Self) -> Self;
119    }
120    
121    buns::sandwich!{
122        impl CycleMath for ^0 {
123            #[inline]
124            fn add_qucy(self,rhs:Self,min:Self,max:Self) -> Self {
125                quick_cycle_add(self,rhs,min,max)
126            }
127            #[inline]
128            fn sub_qucy(self,rhs:Self,min:Self,max:Self) -> Self {
129                quick_cycle_sub(self,rhs,min,max)
130            }
131        }
132        #f32 #f64
133        #i8 #i16 #i32 #i64 #i128 #isize
134        #u8 #u16 #u32 #u64 #u128 #usize
135    }
136
137
138// Combined f32 Multiplication \\
139
140    #[ext(pub trait MulF32)]
141    impl f32 {
142        #[inline]
143        /// wonky float multiplication, mainly meant for integers
144        fn mul_f32(self,rhs:f32) -> Self {self * rhs}
145    }
146
147    impl MulF32 for f64 {
148        #[inline]
149        fn mul_f32(self,rhs:f32) -> Self {self * rhs as f64}
150    }
151
152    buns::sandwich!{
153        impl MulF32 for ^0 {
154            #[inline]
155            fn mul_f32(self,rhs:f32) -> Self {
156                (self as f32 * rhs).round() as ^0 
157            }
158        }
159        #i8 #i16 #i32 #i64 #i128 #isize
160    }
161
162
163// Randomness \\
164
165    /// quick and easy randomness
166    #[cfg(feature="random")]
167    pub mod random {
168        use std::ops::Range;
169        pub use fastrand::*;
170
171        /// random f32 within a range (including)
172        #[inline]
173        pub fn f32r(range:Range<f32>) -> f32 {
174            range.start + f32() * (range.end - range.start)
175        }    
176
177    }
178
179    #[cfg(feature="random")]
180    #[ext(pub trait DekiExtVecRng)]
181    impl <T> Vec<T> {
182        /// get a random entry of this vec
183        #[inline]
184        fn random(&self) -> &T {
185            exit!{>if (self.len()==1) &self[0]}
186            &self[random::usize(0..self.len())]
187        }
188    }
189
190
191// Approx Math \\
192
193    #[cfg(feature="approx")]
194    #[ext(pub trait DekiExtApprox)]
195    impl f32 {
196        /// approx sine, faster but inaccurate
197        #[inline]
198        fn sin_ca(self) -> f32 {approx::sin(self)}
199
200        /// approx cosine, faster but inaccurate
201        #[inline]
202        fn cos_ca(self) -> f32 {approx::cos(self)}
203
204        /// approx tangent, faster but inaccurate
205        #[inline]
206        fn tan_ca(self) -> f32 {approx::tan(self)}
207        
208        /// approx exponential, faster but inaccurate
209        #[inline]
210        fn exp_ca(self) -> f32 {approx::exp(self)}
211
212        /// approx logarithm, faster but inaccurate
213        #[inline]
214        fn log_ca(self,b:f32) -> f32 {approx::log(self,b)}
215
216        /// approx square, faster but inaccurate
217        #[inline]
218        fn sqrt_ca(self) -> f32 {approx::sqrt(self)}
219
220        /// approx power by, faster but inaccurate
221        #[inline]
222        fn pow_ca(self,b:f32) -> f32 {approx::pow(self,b)}
223
224    }
225
226    /// cheaper but inaccurate math implementations
227    #[cfg(feature="approx")]
228    pub mod approx {
229        use std::f32::consts::PI;
230        use fastapprox::faster as approx;
231
232        #[inline]
233        pub fn sin(a:f32) -> f32 {approx::sin(pi_clamp(a))}
234        #[inline]
235        pub fn cos(a:f32) -> f32 {approx::cos(pi_clamp(a))}
236        #[inline]
237        pub fn tan(a:f32) -> f32 {approx::tan(pih_clamp(a))}
238        #[inline]
239        pub fn exp(a:f32) -> f32 {approx::exp(a)}
240        #[inline]
241        pub fn log(a:f32,b:f32) -> f32 { 
242            if b==2. {approx::log2(a)} 
243            else if b==2.72 {approx::ln(a)} 
244            else {a.log(b)}
245        }
246        #[inline]
247        pub fn sqrt(a:f32) -> f32 {approx::pow(a,0.5)}
248        #[inline]
249        pub fn pow(a:f32,b:f32) -> f32 {approx::pow(a,b)}
250        
251        const PI2: f32 = PI*2.;
252        fn pi_clamp(i:f32) -> f32 {sym_clamp(i,PI,PI2)}
253
254        const PI2H: f32 = PI/2.;
255        fn pih_clamp(i:f32) -> f32 {sym_clamp(i,PI2H,PI)}
256
257        fn sym_clamp(i:f32,limit:f32,limit2:f32) -> f32 {
258            let mut a = i % limit2;
259            if a > limit && a < limit2 
260                {a = -limit2 + a;} 
261            a
262        }
263
264    }
265
266
267// Quick Constant \\
268
269    /// create a constant struct and name it after itself
270    #[macro_export]
271    macro_rules! qonst {
272        ($ty:ty: $($tt:tt)*) => {paste!{
273            pub const [<$ty:snake:upper>]: $ty = $ty {
274                $($tt)*
275            };
276        }};
277        ($ty:ident::$($tt:tt)*) => {paste!{
278            pub const [<$ty:snake:upper>]: $ty = $ty::$($tt)*;
279        }};
280    }
281
282
283// EOF \\