@@ -634,6 +634,194 @@ macro_rules! uint_impl {
634634 }
635635 }
636636
637+ /// Returns the logarithm of the number with respect to an arbitrary base.
638+ ///
639+ /// This method may not be optimized owing to implementation details;
640+ /// `log2` can produce results more efficiently for base 2, and `log10`
641+ /// can produce results more efficiently for base 10.
642+ ///
643+ /// # Panics
644+ ///
645+ /// When the number is negative, zero, or if the base is not at least 2;
646+ /// it panics in debug mode and the return value is wrapped to 0 in
647+ /// release mode (the only situation in which the method can return 0).
648+ ///
649+ /// # Examples
650+ ///
651+ /// ```
652+ /// #![feature(int_log)]
653+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".log(5), 1);" ) ]
654+ /// ```
655+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
656+ #[ must_use = "this returns the result of the operation, \
657+ without modifying the original"]
658+ #[ inline]
659+ #[ track_caller]
660+ #[ rustc_inherit_overflow_checks]
661+ #[ allow( arithmetic_overflow) ]
662+ pub const fn log( self , base: Self ) -> Self {
663+ match self . checked_log( base) {
664+ Some ( n) => n,
665+ None => {
666+ // In debug builds, trigger a panic on None.
667+ // This should optimize completely out in release builds.
668+ let _ = Self :: MAX + 1 ;
669+
670+ 0
671+ } ,
672+ }
673+ }
674+
675+ /// Returns the base 2 logarithm of the number.
676+ ///
677+ /// # Panics
678+ ///
679+ /// When the number is negative or zero it panics in debug mode and
680+ /// the return value is wrapped to 0 in release mode (the only situation in
681+ /// which the method can return 0).
682+ ///
683+ /// # Examples
684+ ///
685+ /// ```
686+ /// #![feature(int_log)]
687+ #[ doc = concat!( "assert_eq!(2" , stringify!( $SelfT) , ".log2(), 1);" ) ]
688+ /// ```
689+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
690+ #[ must_use = "this returns the result of the operation, \
691+ without modifying the original"]
692+ #[ inline]
693+ #[ track_caller]
694+ #[ rustc_inherit_overflow_checks]
695+ #[ allow( arithmetic_overflow) ]
696+ pub const fn log2( self ) -> Self {
697+ match self . checked_log2( ) {
698+ Some ( n) => n,
699+ None => {
700+ // In debug builds, trigger a panic on None.
701+ // This should optimize completely out in release builds.
702+ let _ = Self :: MAX + 1 ;
703+
704+ 0
705+ } ,
706+ }
707+ }
708+
709+ /// Returns the base 10 logarithm of the number.
710+ ///
711+ /// # Panics
712+ ///
713+ /// When the number is negative or zero it panics in debug mode and the
714+ /// return value is wrapped to 0 in release mode (the only situation in
715+ /// which the method can return 0).
716+ ///
717+ /// # Example
718+ ///
719+ /// ```
720+ /// #![feature(int_log)]
721+ #[ doc = concat!( "assert_eq!(10" , stringify!( $SelfT) , ".log10(), 1);" ) ]
722+ /// ```
723+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
724+ #[ must_use = "this returns the result of the operation, \
725+ without modifying the original"]
726+ #[ inline]
727+ #[ track_caller]
728+ #[ rustc_inherit_overflow_checks]
729+ #[ allow( arithmetic_overflow) ]
730+ pub const fn log10( self ) -> Self {
731+ match self . checked_log10( ) {
732+ Some ( n) => n,
733+ None => {
734+ // In debug builds, trigger a panic on None.
735+ // This should optimize completely out in release builds.
736+ let _ = Self :: MAX + 1 ;
737+
738+ 0
739+ } ,
740+ }
741+ }
742+
743+ /// Returns the logarithm of the number with respect to an arbitrary base.
744+ ///
745+ /// Returns `None` if the number is zero, or if the base is not at least 2.
746+ ///
747+ /// This method may not be optimized owing to implementation details;
748+ /// `checked_log2` can produce results more efficiently for base 2, and
749+ /// `checked_log10` can produce results more efficiently for base 10.
750+ ///
751+ /// # Examples
752+ ///
753+ /// ```
754+ /// #![feature(int_log)]
755+ #[ doc = concat!( "assert_eq!(5" , stringify!( $SelfT) , ".checked_log(5), Some(1));" ) ]
756+ /// ```
757+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
758+ #[ must_use = "this returns the result of the operation, \
759+ without modifying the original"]
760+ #[ inline]
761+ pub const fn checked_log( self , base: Self ) -> Option <Self > {
762+ if self <= 0 || base <= 1 {
763+ None
764+ } else {
765+ let mut n = 0 ;
766+ let mut r = self ;
767+
768+ // Optimization for 128 bit wide integers.
769+ if Self :: BITS == 128 {
770+ let b = Self :: log2( self ) / ( Self :: log2( base) + 1 ) ;
771+ n += b;
772+ r /= base. pow( b as u32 ) ;
773+ }
774+
775+ while r >= base {
776+ r /= base;
777+ n += 1 ;
778+ }
779+ Some ( n)
780+ }
781+ }
782+
783+ /// Returns the base 2 logarithm of the number.
784+ ///
785+ /// Returns `None` if the number is zero.
786+ ///
787+ /// # Examples
788+ ///
789+ /// ```
790+ /// #![feature(int_log)]
791+ #[ doc = concat!( "assert_eq!(2" , stringify!( $SelfT) , ".checked_log2(), Some(1));" ) ]
792+ /// ```
793+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
794+ #[ must_use = "this returns the result of the operation, \
795+ without modifying the original"]
796+ #[ inline]
797+ pub const fn checked_log2( self ) -> Option <Self > {
798+ if self <= 0 {
799+ None
800+ } else {
801+ // SAFETY: We just checked that this number is positive
802+ let log = ( Self :: BITS - 1 ) as Self - unsafe { intrinsics:: ctlz_nonzero( self ) } ;
803+ Some ( log)
804+ }
805+ }
806+
807+ /// Returns the base 10 logarithm of the number.
808+ ///
809+ /// Returns `None` if the number is zero.
810+ ///
811+ /// # Examples
812+ ///
813+ /// ```
814+ /// #![feature(int_log)]
815+ #[ doc = concat!( "assert_eq!(10" , stringify!( $SelfT) , ".checked_log10(), Some(1));" ) ]
816+ /// ```
817+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
818+ #[ must_use = "this returns the result of the operation, \
819+ without modifying the original"]
820+ #[ inline]
821+ pub const fn checked_log10( self ) -> Option <Self > {
822+ self . checked_log( 10 )
823+ }
824+
637825 /// Checked negation. Computes `-self`, returning `None` unless `self ==
638826 /// 0`.
639827 ///
0 commit comments