1use crate::error::IntegerError;
2
3use musli::Context;
4
5use crate::parser::Parser;
6
7use self::traits::FromUnsigned;
8pub(crate) use self::traits::{Float, Signed, Unsigned};
9
10#[non_exhaustive]
12#[derive(Clone, Copy)]
13pub(crate) struct SignedPartsBase<T>
14where
15 T: Signed,
16{
17 pub(crate) is_negative: bool,
19 pub(crate) unsigned: T::Unsigned,
21}
22
23impl<T> SignedPartsBase<T>
24where
25 T: Signed,
26{
27 pub(crate) fn compute(self) -> Result<T, IntegerError> {
28 let Self {
29 is_negative,
30 unsigned,
31 } = self;
32
33 match if is_negative {
34 unsigned.negate()
35 } else {
36 unsigned.signed()
37 } {
38 Some(value) => Ok(value),
39 None => Err(IntegerError::IntegerOverflow),
40 }
41 }
42}
43
44#[non_exhaustive]
46#[derive(Clone, Copy)]
47pub(crate) struct SignedPartsFull<T>
48where
49 T: Signed,
50{
51 pub(crate) is_negative: bool,
53 pub(crate) unsigned: Parts<T::Unsigned>,
55}
56
57impl<T> SignedPartsFull<T>
58where
59 T: Signed,
60{
61 #[inline(always)]
62 pub(crate) fn compute(self) -> Result<T, IntegerError> {
63 let Self {
64 is_negative,
65 unsigned: parts,
66 } = self;
67
68 let value = parts.compute()?;
69
70 match if is_negative {
71 value.negate()
72 } else {
73 value.signed()
74 } {
75 Some(value) => Ok(value),
76 None => Err(IntegerError::IntegerOverflow),
77 }
78 }
79
80 #[inline(always)]
81 pub(crate) fn compute_float<F>(self) -> F
82 where
83 F: Float,
84 F: FromUnsigned<T::Unsigned>,
85 {
86 let Self {
87 is_negative,
88 unsigned: parts,
89 } = self;
90 let value = parts.compute_float::<F>();
91
92 if is_negative {
93 value.negate()
94 } else {
95 value
96 }
97 }
98}
99
100#[derive(Clone, Copy)]
102pub(crate) struct Mantissa<T> {
103 value: T,
105 exp: i32,
107}
108
109impl<T> Mantissa<T>
110where
111 T: Unsigned,
112{
113 fn into_float<F>(self) -> Mantissa<F>
114 where
115 F: FromUnsigned<T>,
116 {
117 Mantissa {
118 value: self.value.into_float::<F>(),
119 exp: self.exp,
120 }
121 }
122}
123
124impl<F> Mantissa<F>
125where
126 F: Float,
127{
128 #[inline]
130 fn compute_float(self, e: i32) -> F {
131 self.value.pow10(e - self.exp)
132 }
133}
134
135impl<T> Default for Mantissa<T>
136where
137 T: Unsigned,
138{
139 fn default() -> Self {
140 Self {
141 value: T::ZERO,
142 exp: 0i32,
143 }
144 }
145}
146
147#[non_exhaustive]
149#[derive(Clone, Copy)]
150pub(crate) struct Parts<T> {
151 pub(crate) base: T,
153 pub(crate) m: Mantissa<T>,
155 pub(crate) e: i32,
157}
158
159impl<T> Parts<T>
160where
161 T: Unsigned,
162{
163 #[inline(always)]
164 pub(crate) fn compute(self) -> Result<T, IntegerError> {
165 macro_rules! check {
166 ($expr:expr, $kind:ident) => {
167 match $expr {
168 Some(value) => value,
169 None => return Err(IntegerError::$kind),
170 }
171 };
172 }
173
174 let Self { mut base, m, e } = self;
175
176 if e == 0 {
177 if !m.value.is_zero() {
178 return Err(IntegerError::Decimal);
179 }
180
181 return Ok(base);
182 }
183
184 if e >= 0 {
185 let mantissa_exp = check!(e.checked_sub(m.exp).filter(|n| *n >= 0), Decimal) as u32;
187
188 if !base.is_zero() {
189 base = check!(base.checked_pow10(e as u32), IntegerOverflow);
190 }
191
192 let base = check! {
193 m.value
194 .checked_pow10(mantissa_exp)
195 .and_then(|m| base.checked_add(m)),
196 IntegerOverflow
197 };
198
199 Ok(base)
200 } else if !m.value.is_zero() {
201 Err(IntegerError::Decimal)
202 } else {
203 Ok(check!(base.checked_neg_pow10(-e as u32), Decimal))
204 }
205 }
206
207 #[inline(always)]
208 pub(crate) fn compute_float<F>(self) -> F
209 where
210 F: Float,
211 F: FromUnsigned<T>,
212 {
213 let Self { base, m, e } = self;
214 base.into_float::<F>().pow10(e) + m.into_float::<F>().compute_float(e)
215 }
216}
217
218pub(crate) fn skip_number<'de, P, C>(cx: &C, mut p: P) -> Result<(), C::Error>
220where
221 P: Parser<'de>,
222 C: ?Sized + Context,
223{
224 p.skip_whitespace(cx)?;
225
226 let start = cx.mark();
227
228 if p.peek_byte(cx)? == Some(b'-') {
229 p.skip(cx, 1)?;
230 }
231
232 match p.read_byte(cx)? {
233 b'0' => (),
234 b if is_digit_nonzero(b) => {
235 p.consume_while(cx, is_digit)?;
236 }
237 _ => {
238 return Err(cx.marked_message(start, IntegerError::InvalidNumeric));
239 }
240 }
241
242 if p.peek_byte(cx)? == Some(b'.') {
243 p.skip(cx, 1)?;
244 p.consume_while(cx, is_digit)?;
245 }
246
247 if matches!(p.peek_byte(cx)?, Some(b'e') | Some(b'E')) {
248 p.skip(cx, 1)?;
249
250 match p.peek_byte(cx)? {
251 Some(b'-') => {
252 p.skip(cx, 1)?;
253 }
254 Some(b'+') => {
255 p.skip(cx, 1)?;
256 }
257 _ => (),
258 };
259
260 p.consume_while(cx, is_digit)?;
261 }
262
263 Ok(())
264}
265
266#[cfg_attr(feature = "parse-full", allow(unused))]
268#[inline(never)]
269pub(crate) fn parse_unsigned_base<'de, T, C, P>(cx: &C, mut p: P) -> Result<T, C::Error>
270where
271 T: Unsigned,
272 P: Parser<'de>,
273 C: ?Sized + Context,
274{
275 p.skip_whitespace(cx)?;
276
277 let start = cx.mark();
278 decode_unsigned_base::<T, _, _>(cx, p, start)
279}
280
281#[cfg_attr(not(feature = "parse-full"), allow(unused))]
283#[inline(never)]
284pub(crate) fn parse_unsigned_full<'de, T, C, P>(cx: &C, mut p: P) -> Result<T, C::Error>
285where
286 T: Unsigned,
287 P: Parser<'de>,
288 C: ?Sized + Context,
289{
290 p.skip_whitespace(cx)?;
291
292 let start = cx.mark();
293
294 match decode_unsigned_full(cx, p, start)?.compute() {
295 Ok(value) => Ok(value),
296 Err(error) => Err(cx.marked_message(start, error)),
297 }
298}
299
300#[inline(always)]
302fn decode_signed_base<'de, T, C, P>(cx: &C, mut p: P) -> Result<SignedPartsBase<T>, C::Error>
303where
304 C: ?Sized + Context,
305 T: Signed,
306 P: Parser<'de>,
307{
308 let start = cx.mark();
309
310 let is_negative = if p.peek_byte(cx)? == Some(b'-') {
311 p.skip(cx, 1)?;
312 true
313 } else {
314 false
315 };
316
317 let unsigned = decode_unsigned_base::<T::Unsigned, _, _>(cx, p, start)?;
318
319 Ok(SignedPartsBase {
320 is_negative,
321 unsigned,
322 })
323}
324
325pub(crate) fn decode_signed_full<'de, T, C, P>(
327 cx: &C,
328 p: &mut P,
329) -> Result<SignedPartsFull<T>, C::Error>
330where
331 C: ?Sized + Context,
332 T: Signed,
333 P: ?Sized + Parser<'de>,
334{
335 p.skip_whitespace(cx)?;
336
337 decode_signed_full_inner(cx, p)
338}
339
340#[inline(always)]
342fn decode_signed_full_inner<'de, T, C, P>(cx: &C, mut p: P) -> Result<SignedPartsFull<T>, C::Error>
343where
344 C: ?Sized + Context,
345 T: Signed,
346 P: Parser<'de>,
347{
348 let start = cx.mark();
349
350 let is_negative = if p.peek_byte(cx)? == Some(b'-') {
351 p.skip(cx, 1)?;
352 true
353 } else {
354 false
355 };
356
357 let parts = decode_unsigned_full::<T::Unsigned, _, _>(cx, p, start)?;
358
359 Ok(SignedPartsFull {
360 is_negative,
361 unsigned: parts,
362 })
363}
364
365#[cfg_attr(feature = "parse-full", allow(unused))]
367#[inline(never)]
368pub(crate) fn parse_signed_base<'de, T, C, P>(cx: &C, mut p: P) -> Result<T, C::Error>
369where
370 T: Signed,
371 P: Parser<'de>,
372 C: ?Sized + Context,
373{
374 p.skip_whitespace(cx)?;
375
376 let start = cx.mark();
377
378 match decode_signed_base(cx, p)?.compute() {
379 Ok(value) => Ok(value),
380 Err(error) => Err(cx.marked_message(start, error)),
381 }
382}
383
384#[cfg_attr(not(feature = "parse-full"), allow(unused))]
386#[inline(never)]
387pub(crate) fn parse_signed_full<'de, T, C, P>(cx: &C, mut p: P) -> Result<T, C::Error>
388where
389 T: Signed,
390 P: Parser<'de>,
391 C: ?Sized + Context,
392{
393 p.skip_whitespace(cx)?;
394
395 let start = cx.mark();
396
397 match decode_signed_full_inner(cx, p)?.compute() {
398 Ok(value) => Ok(value),
399 Err(error) => Err(cx.marked_message(start, error)),
400 }
401}
402
403#[inline(always)]
406fn decode_unsigned_base<'de, T, C, P>(cx: &C, mut p: P, start: C::Mark) -> Result<T, C::Error>
407where
408 T: Unsigned,
409 P: Parser<'de>,
410 C: ?Sized + Context,
411{
412 let base = match p.read_byte(cx)? {
413 b'0' => T::ZERO,
414 b if is_digit_nonzero(b) => {
415 let mut base = T::from_byte(b - b'0');
416
417 while let Some(true) = p.peek_byte(cx)?.map(is_digit) {
418 base = digit(cx, base, p.borrow_mut(), start)?;
419 }
420
421 base
422 }
423 _ => {
424 return Err(cx.marked_message(start, IntegerError::InvalidNumeric));
425 }
426 };
427
428 Ok(base)
429}
430
431#[inline(always)]
434fn decode_unsigned_full<'de, T, C, P>(
435 cx: &C,
436 mut p: P,
437 start: C::Mark,
438) -> Result<Parts<T>, C::Error>
439where
440 T: Unsigned,
441 P: Parser<'de>,
442 C: ?Sized + Context,
443{
444 let base = decode_unsigned_base(cx, p.borrow_mut(), start)?;
445
446 let mut m = Mantissa::<T>::default();
447
448 if let Some(b'.') = p.peek_byte(cx)? {
449 p.skip(cx, 1)?;
450
451 m.exp = m.exp.wrapping_add(decode_zeros(cx, p.borrow_mut())?);
454
455 let mut zeros = 0;
458
459 while let Some(true) = p.peek_byte(cx)?.map(is_digit) {
460 if zeros > 0 {
462 m.exp += zeros;
463 m.value = match m.value.checked_pow10(zeros as u32) {
464 Some(mantissa) => mantissa,
465 None => {
466 return Err(cx.marked_message(start, IntegerError::IntegerOverflow));
467 }
468 };
469 }
470
471 m.exp += 1;
472 m.value = digit(cx, m.value, p.borrow_mut(), start)?;
473 zeros = decode_zeros(cx, p.borrow_mut())?;
474 }
475 }
476
477 let e = if matches!(p.peek_byte(cx)?, Some(b'e' | b'E')) {
478 p.skip(cx, 1)?;
479 decode_exponent(cx, p, start)?
480 } else {
481 0
482 };
483
484 Ok(Parts { base, m, e })
485}
486
487#[inline(always)]
489fn decode_exponent<'de, P, C>(cx: &C, mut p: P, start: C::Mark) -> Result<i32, C::Error>
490where
491 P: Parser<'de>,
492 C: ?Sized + Context,
493{
494 let mut is_negative = false;
495 let mut e = 0u32;
496
497 match p.peek_byte(cx)? {
498 Some(b'-') => {
499 p.skip(cx, 1)?;
500 is_negative = true
501 }
502 Some(b'+') => {
503 p.skip(cx, 1)?;
504 }
505 _ => (),
506 };
507
508 while let Some(true) = p.peek_byte(cx)?.map(is_digit) {
509 e = digit(cx, e, p.borrow_mut(), start)?;
510 }
511
512 match if is_negative { e.negate() } else { e.signed() } {
513 Some(value) => Ok(value),
514 None => Err(cx.marked_message(start, IntegerError::IntegerOverflow)),
515 }
516}
517
518#[inline(always)]
520fn digit<'de, T, C, P>(cx: &C, out: T, mut p: P, start: C::Mark) -> Result<T, C::Error>
521where
522 T: Unsigned,
523 P: Parser<'de>,
524 C: ?Sized + Context,
525{
526 let Some(out) = out.checked_mul10() else {
527 return Err(cx.marked_message(start, IntegerError::IntegerOverflow));
528 };
529
530 Ok(out + T::from_byte(p.read_byte(cx)? - b'0'))
531}
532
533#[inline(always)]
535fn decode_zeros<'de, P, C>(cx: &C, mut p: P) -> Result<i32, C::Error>
536where
537 P: Parser<'de>,
538 C: ?Sized + Context,
539{
540 let mut count = 0i32;
541
542 while let Some(b'0') = p.peek_byte(cx)? {
543 count = count.wrapping_add(1);
544 p.skip(cx, 1)?;
545 }
546
547 Ok(count)
548}
549
550#[inline]
552fn is_digit(b: u8) -> bool {
553 b.is_ascii_digit()
554}
555
556#[inline(always)]
558fn is_digit_nonzero(b: u8) -> bool {
559 (b'1'..=b'9').contains(&b)
560}
561
562mod traits {
563 use core::fmt;
564 use core::ops::{Add, Not};
565
566 pub(crate) trait Unsigned: Sized + fmt::Debug + Add<Self, Output = Self> {
567 type Signed: Signed<Unsigned = Self>;
568
569 const ZERO: Self;
570
571 fn from_byte(b: u8) -> Self;
572
573 fn is_zero(&self) -> bool;
574
575 fn checked_pow10(self, exp: u32) -> Option<Self>;
577
578 fn checked_neg_pow10(self, e: u32) -> Option<Self>;
580
581 fn checked_mul10(self) -> Option<Self>;
582
583 fn checked_add(self, other: Self) -> Option<Self>;
584
585 fn checked_pow(self, exp: u32) -> Option<Self>;
586
587 fn negate(self) -> Option<Self::Signed>;
588
589 fn signed(self) -> Option<Self::Signed>;
590
591 fn into_float<F>(self) -> F
592 where
593 F: FromUnsigned<Self>;
594 }
595
596 pub(crate) trait Signed: Sized + fmt::Debug {
597 type Unsigned: Unsigned<Signed = Self>;
598 }
599
600 pub(crate) trait FromUnsigned<T> {
601 fn from_unsigned(value: T) -> Self;
602 }
603
604 pub(crate) trait Float: Sized + Add<Self, Output = Self> {
605 fn negate(self) -> Self;
606
607 fn pow10(self, e: i32) -> Self;
608 }
609
610 macro_rules! count {
611 (()) => { 0 };
612 ((_)) => { 1 };
613 ((_ _)) => { 2 };
614 ((_ _ _)) => { 3 };
615 ((_ _ _ _)) => { 4 };
616 ((_ _ _ _ _)) => { 5 };
617 ((_ _ _ _ _ _)) => { 6 };
618 ((_ _ _ _ _ _ _)) => { 7 };
619 ((_ _ _ _ _ _ _ _)) => { 8 };
620 ((_ _ _ _ _ _ _ _ _)) => { 9 };
621 ((_ _ _ _ _ _ _ _ _ _)) => { 10 };
622 ((_ _ _ _ _ _ _ _ _ _ _)) => { 11 };
623 ((_ _ _ _ _ _ _ _ _ _ _ _)) => { 12 };
624 ((_ _ _ _ _ _ _ _ _ _ _ _ _)) => { 13 };
625 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 14 };
626 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 15 };
627 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 16 };
628 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 17 };
629 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 18 };
630 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 19 };
631 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 20 };
632 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 21 };
633 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 22 };
634 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 23 };
635 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 24 };
636 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 25 };
637 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 26 };
638 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 27 };
639 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 28 };
640 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 29 };
641 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 30 };
642 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 31 };
643 ((_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)) => { 32 };
644
645 (($($s:tt)*) $first:tt $($tt:tt)*) => {
646 count!(($($s)* _) $($tt)*)
647 };
648 }
649
650 macro_rules! unsigned {
651 ($unsigned:ty, $signed:ty, [$($pows:literal),* $(,)?]) => {
652 impl Unsigned for $unsigned {
653 type Signed = $signed;
654
655 const ZERO: Self = 0;
656
657 #[inline(always)]
658 fn from_byte(b: u8) -> Self {
659 b as $unsigned
660 }
661
662 #[inline(always)]
663 fn is_zero(&self) -> bool {
664 *self == 0
665 }
666
667 #[inline(always)]
668 fn checked_pow10(self, e: u32) -> Option<Self> {
669 static POWS: [$unsigned; count!(() $($pows)*)] = [
670 $($pows),*
671 ];
672
673 let n = if let Some(e) = POWS.get(e as usize) {
674 *e
675 } else {
676 10.checked_pow(e)?
677 };
678
679 self.checked_mul(n)
680 }
681
682 #[inline(always)]
683 fn checked_neg_pow10(self, e: u32) -> Option<Self> {
684 const ONE: $unsigned = 1;
685 let div = ONE.checked_pow10(e)?;
686
687 if self % div != 0 {
688 None
689 } else {
690 Some(self / div)
691 }
692 }
693
694 #[inline(always)]
695 fn checked_mul10(self) -> Option<Self> {
696 self.checked_mul(10)
697 }
698
699 #[inline(always)]
700 fn checked_add(self, other: Self) -> Option<Self> {
701 <$unsigned>::checked_add(self, other)
702 }
703
704 #[inline(always)]
705 fn checked_pow(self, exp: u32) -> Option<Self> {
706 <$unsigned>::checked_pow(self, exp)
707 }
708
709 #[inline(always)]
710 fn negate(self) -> Option<Self::Signed> {
711 if self > (<$unsigned>::MAX >> 1) + 1 {
712 None
713 } else {
714 Some(self.not().wrapping_add(1) as $signed)
715 }
716 }
717
718 #[inline(always)]
719 fn signed(self) -> Option<Self::Signed> {
720 if self > <$unsigned>::MAX >> 1 {
721 None
722 } else {
723 Some(self as $signed)
724 }
725 }
726
727 #[inline(always)]
728 fn into_float<F>(self) -> F where F: FromUnsigned<Self> {
729 F::from_unsigned(self)
730 }
731 }
732
733 impl Signed for $signed {
734 type Unsigned = $unsigned;
735 }
736 };
737 }
738
739 unsigned!(u8, i8, [1, 10, 100,]);
740
741 unsigned!(u16, i16, [1, 10, 100, 1000, 10000,]);
742
743 unsigned!(
744 u32,
745 i32,
746 [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,]
747 );
748
749 unsigned!(
750 u64,
751 i64,
752 [
753 1,
754 10,
755 100,
756 1000,
757 10000,
758 100000,
759 1000000,
760 10000000,
761 100000000,
762 1000000000,
763 10000000000,
764 100000000000,
765 1000000000000,
766 10000000000000,
767 100000000000000,
768 1000000000000000,
769 10000000000000000,
770 100000000000000000,
771 1000000000000000000,
772 10000000000000000000,
773 ]
774 );
775
776 unsigned!(
777 u128,
778 i128,
779 [
780 1,
781 10,
782 100,
783 1000,
784 10000,
785 100000,
786 1000000,
787 10000000,
788 100000000,
789 1000000000,
790 10000000000,
791 100000000000,
792 1000000000000,
793 10000000000000,
794 100000000000000,
795 1000000000000000,
796 10000000000000000,
797 100000000000000000,
798 1000000000000000000,
799 10000000000000000000,
800 100000000000000000000,
801 1000000000000000000000,
802 10000000000000000000000,
803 100000000000000000000000,
804 1000000000000000000000000,
805 10000000000000000000000000,
806 100000000000000000000000000,
807 1000000000000000000000000000,
808 10000000000000000000000000000,
809 100000000000000000000000000000,
810 1000000000000000000000000000000,
811 10000000000000000000000000000000,
812 ]
813 );
814
815 #[cfg(target_pointer_width = "32")]
816 unsigned!(
817 usize,
818 isize,
819 [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,]
820 );
821
822 #[cfg(target_pointer_width = "64")]
823 unsigned!(
824 usize,
825 isize,
826 [
827 1,
828 10,
829 100,
830 1000,
831 10000,
832 100000,
833 1000000,
834 10000000,
835 100000000,
836 1000000000,
837 10000000000,
838 100000000000,
839 1000000000000,
840 10000000000000,
841 100000000000000,
842 1000000000000000,
843 10000000000000000,
844 100000000000000000,
845 1000000000000000000,
846 10000000000000000000,
847 ]
848 );
849
850 macro_rules! float {
851 ($float:ty, $fallback:path) => {
852 impl Float for $float {
853 #[inline]
854 fn negate(self) -> Self {
855 -self
856 }
857
858 #[inline]
859 #[cfg(feature = "std")]
860 fn pow10(self, e: i32) -> Self {
861 self * <$float>::powi(10.0, e)
862 }
863
864 #[inline]
865 #[cfg(not(feature = "std"))]
866 fn pow10(self, e: i32) -> Self {
867 self * $fallback(10.0, e)
868 }
869 }
870
871 impl FromUnsigned<u8> for $float {
872 fn from_unsigned(value: u8) -> Self {
873 value as $float
874 }
875 }
876
877 impl FromUnsigned<u16> for $float {
878 fn from_unsigned(value: u16) -> Self {
879 value as $float
880 }
881 }
882
883 impl FromUnsigned<u32> for $float {
884 fn from_unsigned(value: u32) -> Self {
885 value as $float
886 }
887 }
888
889 impl FromUnsigned<u64> for $float {
890 fn from_unsigned(value: u64) -> Self {
891 value as $float
892 }
893 }
894
895 impl FromUnsigned<u128> for $float {
896 fn from_unsigned(value: u128) -> Self {
897 value as $float
898 }
899 }
900 };
901 }
902
903 float!(f32, self::no_std::powf32);
904 float!(f64, self::no_std::powf64);
905
906 #[cfg(not(feature = "std"))]
907 mod no_std {
908 macro_rules! powf {
909 ($ty:ty, $name:ident) => {
910 #[inline(never)]
911 pub(crate) fn $name(mut base: $ty, mut exp: i32) -> $ty {
912 if exp == 0 {
913 return 1.0;
914 }
915
916 while exp & 1 == 0 {
917 base = base * base;
918 exp >>= 1;
919 }
920
921 if exp == 1 {
922 return base;
923 }
924
925 let mut acc = base;
926
927 while exp > 1 {
928 exp >>= 1;
929 base = base * base;
930
931 if exp & 1 == 1 {
932 acc = acc * base;
933 }
934 }
935
936 acc
937 }
938 };
939 }
940
941 powf!(f32, powf32);
942 powf!(f64, powf64);
943 }
944}