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