@@ -122,34 +122,46 @@ fn digit_log2<T: UnsignedInteger>(x: T) -> usize {
122
122
123
123
/// Highly-optimized digit count for base4 values.
124
124
///
125
- /// This is very similar to base 2, except we shift right by
126
- /// 1 and adjust by 1. For example, `fast_log2(3) == 1`, so
127
- /// `fast_log2(3) >> 1 == 0`, which then gives us our result.
125
+ /// This is very similar to base 2, except we divide by 2
126
+ /// and adjust by 1. For example, `fast_log2(3) == 1`, so
127
+ /// `fast_log2(3) / 2 == 0`, which then gives us our result.
128
+ ///
129
+ /// This works because `log2(x) / 2 == log4(x)`. Flooring is
130
+ /// the correct approach since `log2(15) == 3`, which should be
131
+ /// 2 digits (so `3 / 2 + 1`).
128
132
#[ inline( always) ]
129
133
fn digit_log4 < T : UnsignedInteger > ( x : T ) -> usize {
130
- // NOTE: This cannot be `fast_log2(fast_log2())`
131
- ( fast_log2 ( x | T :: ONE ) >> 1 ) + 1
134
+ ( fast_log2 ( x) / 2 ) + 1
132
135
}
133
136
134
- /// Specialized digit count for base8 values.
137
+ /// Highly-optimized digit count for base8 values.
138
+ ///
139
+ /// This works because `log2(x) / 3 == log8(x)`. Flooring is
140
+ /// the correct approach since `log2(63) == 5`, which should be
141
+ /// 2 digits (so `5 / 3 + 1`).
135
142
#[ inline( always) ]
136
143
fn digit_log8 < T : UnsignedInteger > ( x : T ) -> usize {
137
- // FIXME: Optimize
138
- digit_count ! ( @naive T , 8 , x)
144
+ ( fast_log2 ( x) / 3 ) + 1
139
145
}
140
146
141
- /// Specialized digit count for base16 values.
147
+ /// Highly-optimized digit count for base16 values.
148
+ ///
149
+ /// This works because `log2(x) / 4 == log16(x)`. Flooring is
150
+ /// the correct approach since `log2(255) == 7`, which should be
151
+ /// 2 digits (so `7 / 4 + 1`).
142
152
#[ inline( always) ]
143
153
fn digit_log16 < T : UnsignedInteger > ( x : T ) -> usize {
144
- // FIXME: Optimize
145
- digit_count ! ( @naive T , 16 , x)
154
+ ( fast_log2 ( x) / 4 ) + 1
146
155
}
147
156
148
- /// Specialized digit count for base32 values.
157
+ /// Highly-optimized digit count for base32 values.
158
+ ///
159
+ /// This works because `log2(x) / 5 == log32(x)`. Flooring is
160
+ /// the correct approach since `log2(1023) == 9`, which should be
161
+ /// 2 digits (so `9 / 5 + 1`).
149
162
#[ inline( always) ]
150
163
fn digit_log32 < T : UnsignedInteger > ( x : T ) -> usize {
151
- // FIXME: Optimize
152
- digit_count ! ( @naive T , 32 , x)
164
+ ( fast_log2 ( x) / 5 ) + 1
153
165
}
154
166
155
167
/// Quickly calculate the number of digits in a type.
@@ -183,6 +195,14 @@ pub unsafe trait DigitCount: UnsignedInteger + DecimalCount {
183
195
_ => digit_count ! ( @naive Self , radix, self ) ,
184
196
}
185
197
}
198
+
199
+ /// Get the number of digits in a value, always using the slow algorithm.
200
+ ///
201
+ /// This is exposed for testing purposes.
202
+ #[ inline( always) ]
203
+ fn slow_digit_count ( self , radix : u32 ) -> usize {
204
+ digit_count ! ( @naive Self , radix, self )
205
+ }
186
206
}
187
207
188
208
// Implement digit counts for all types.
0 commit comments