Eliminate the num-traits dependency (#761)
1//! Allocator-flexible data types
2
3// When std is enabled, prefer those types
4#[cfg(feature = "std")]
5pub(crate) use self::std::*;
6
7// When alloc but not std is enabled, use those types
8#[cfg(all(feature = "alloc", not(feature = "std")))]
9pub(crate) use self::alloc::*;
10
11// When neither alloc or std is enabled, use a heapless fallback
12#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
13pub(crate) use self::core::*;
14
15/// For when `std` is enabled
16#[cfg(feature = "std")]
17mod std {
18 /// An allocation-backend agnostic vector type
19 pub(crate) type Vec<A> = std::vec::Vec<A>;
20 /// A vector of child nodes
21 pub(crate) type ChildrenVec<A> = std::vec::Vec<A>;
22 #[cfg(feature = "grid")]
23 /// A vector of grid tracks
24 pub(crate) type GridTrackVec<A> = std::vec::Vec<A>;
25
26 /// Creates a new vector with the capacity for the specified number of items before it must be resized
27 #[must_use]
28 pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
29 Vec::with_capacity(capacity)
30 }
31
32 /// Rounds to the nearest whole number
33 #[must_use]
34 #[inline(always)]
35 pub(crate) fn round(value: f32) -> f32 {
36 value.round()
37 }
38
39 /// Computes the absolute value
40 #[must_use]
41 #[inline(always)]
42 pub(crate) fn abs(value: f32) -> f32 {
43 value.abs()
44 }
45
46 /// Returns the largest of two f32 values
47 #[inline(always)]
48 pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
49 a.max(b)
50 }
51
52 /// Returns the smallest of two f32 values
53 #[inline(always)]
54 pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
55 a.min(b)
56 }
57}
58
59/// For when `alloc` but not `std` is enabled
60#[cfg(all(feature = "alloc", not(feature = "std")))]
61mod alloc {
62 extern crate alloc;
63 use core::cmp::Ordering;
64
65 /// An allocation-backend agnostic vector type
66 pub(crate) type Vec<A> = alloc::vec::Vec<A>;
67 /// A vector of child nodes
68 pub(crate) type ChildrenVec<A> = alloc::vec::Vec<A>;
69 #[cfg(feature = "grid")]
70 /// A vector of grid tracks
71 pub(crate) type GridTrackVec<A> = alloc::vec::Vec<A>;
72
73 /// Creates a new vector with the capacity for the specified number of items before it must be resized
74 #[must_use]
75 pub(crate) fn new_vec_with_capacity<A>(capacity: usize) -> Vec<A> {
76 Vec::with_capacity(capacity)
77 }
78
79 /// Rounds to the nearest whole number
80 pub(crate) use super::polyfill::round;
81
82 /// Computes the absolute value
83 pub(crate) use super::polyfill::abs;
84
85 /// Returns the largest of two f32 values
86 #[inline(always)]
87 pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
88 a.max(b)
89 }
90
91 /// Returns the smallest of two f32 values
92 #[inline(always)]
93 pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
94 a.min(b)
95 }
96}
97
98/// For when neither `alloc` nor `std` is enabled
99#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
100mod core {
101 use core::cmp::Ordering;
102
103 /// The maximum number of nodes in the tree
104 pub const MAX_NODE_COUNT: usize = 256;
105 /// The maximum number of children of any given node
106 pub const MAX_CHILD_COUNT: usize = 16;
107 #[cfg(feature = "grid")]
108 /// The maximum number of children of any given node
109 pub const MAX_GRID_TRACKS: usize = 16;
110
111 /// An allocation-backend agnostic vector type
112 pub(crate) type Vec<A> = arrayvec::ArrayVec<A, MAX_NODE_COUNT>;
113 /// A vector of child nodes, whose length cannot exceed [`MAX_CHILD_COUNT`]
114 pub(crate) type ChildrenVec<A> = arrayvec::ArrayVec<A, MAX_CHILD_COUNT>;
115 #[cfg(feature = "grid")]
116 /// A vector of grid tracks
117 pub(crate) type GridTrackVec<A> = arrayvec::ArrayVec<A, MAX_GRID_TRACKS>;
118
119 /// Creates a new map with the capacity for the specified number of items before it must be resized
120 ///
121 /// This vector cannot be resized.
122 #[must_use]
123 pub(crate) fn new_vec_with_capacity<A, const CAP: usize>(_capacity: usize) -> arrayvec::ArrayVec<A, CAP> {
124 arrayvec::ArrayVec::new()
125 }
126
127 /// Rounds to the nearest whole number
128 pub(crate) use super::polyfill::round;
129
130 /// Computes the absolute value
131 pub(crate) use super::polyfill::abs;
132
133 /// Returns the largest of two f32 values
134 #[inline(always)]
135 pub(crate) fn f32_max(a: f32, b: f32) -> f32 {
136 a.max(b)
137 }
138
139 /// Returns the smallest of two f32 values
140 #[inline(always)]
141 pub(crate) fn f32_min(a: f32, b: f32) -> f32 {
142 a.min(b)
143 }
144}
145
146/// Implementations of float functions for no_std and alloc builds
147/// Copied from `num-traits` crate
148mod polyfill {
149 #[inline(always)]
150 #[cfg(not(feature = "std"))]
151 fn fract(value: f32) -> f32 {
152 if value == 0.0 {
153 0.0
154 } else {
155 value % 1.0
156 }
157 }
158
159 #[must_use]
160 #[inline(always)]
161 #[cfg(not(feature = "std"))]
162 pub(crate) fn round(value: f32) -> f32 {
163 let f = fract(value);
164 if f.is_nan() || f == 0.0 {
165 value
166 } else if value > 0.0 {
167 if f < 0.5 {
168 value - f
169 } else {
170 value - f + 1.0
171 }
172 } else if -f < 0.5 {
173 value - f
174 } else {
175 value - f - 1.0
176 }
177 }
178
179 /// Computes the absolute value
180 #[must_use]
181 #[inline(always)]
182 #[cfg(not(feature = "std"))]
183 pub(crate) fn abs(value: f32) -> f32 {
184 if value.is_sign_positive() {
185 return value;
186 } else if value.is_sign_negative() {
187 return -value;
188 } else {
189 f32::NAN
190 }
191 }
192}