@@ -2160,6 +2160,117 @@ assert_eq!((-a).rem_euclid(-b), 1);
21602160 }
21612161 }
21622162
2163+ doc_comment! {
2164+ concat!( "Returns the logarithm of the number with respect to an arbitrary base.
2165+
2166+ Returns `None` if the number is zero, or if the base is zero or one.
2167+
2168+ This method may not be optimized owing to implementation details;
2169+ `self.checked_log2()` can produce results more efficiently for base 2, and
2170+ `self.checked_log10()` can produce results more efficiently for base 10.
2171+
2172+ # Examples
2173+
2174+ ```
2175+ #![feature(int_log)]
2176+
2177+ let five = 5" , stringify!( $SelfT) , ";
2178+
2179+ // log5(5) == 1
2180+ let result = five.checked_log(5);
2181+
2182+ assert_eq!(result, Some(1));
2183+ ```" ) ,
2184+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
2185+ #[ must_use = "this returns the result of the operation, \
2186+ without modifying the original"]
2187+ #[ inline]
2188+ pub fn checked_log( self , base: Self ) -> Option <Self > {
2189+ // SAFETY: We check the input to this is always positive
2190+ let logb2 = |x: Self | unsafe { intrinsics:: ctlz_nonzero( 1 as Self ) - intrinsics:: ctlz_nonzero( x) } ;
2191+
2192+ if self <= 0 || base <= 1 {
2193+ None
2194+ } else {
2195+ let mut n = 0 ;
2196+ let mut r = self ;
2197+
2198+ // Optimization for 128 bit wide integers.
2199+ if mem:: size_of:: <Self >( ) * 8 == 128 {
2200+ let b = logb2( self ) / ( logb2( base) + 1 ) ;
2201+ n += b;
2202+ r /= base. pow( b as u32 ) ;
2203+ }
2204+
2205+ while r >= base {
2206+ r /= base;
2207+ n += 1 ;
2208+ }
2209+ Some ( n)
2210+ }
2211+ }
2212+ }
2213+
2214+ doc_comment! {
2215+ concat!( "Returns the base 2 logarithm of the number.
2216+
2217+ Returns `None` if the number is lower than 1.
2218+
2219+ # Examples
2220+
2221+ ```
2222+ #![feature(int_log)]
2223+
2224+ let two = 2" , stringify!( $SelfT) , ";
2225+
2226+ // checked_log2(2) == 1
2227+ let result = two.checked_log2();
2228+
2229+ assert_eq!(result, Some(1));
2230+ ```" ) ,
2231+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
2232+ #[ must_use = "this returns the result of the operation, \
2233+ without modifying the original"]
2234+ #[ inline]
2235+ pub fn checked_log2( self ) -> Option <Self > {
2236+ if self <= 0 {
2237+ None
2238+ } else {
2239+ // SAFETY: We just checked that this number is positive
2240+ let log = unsafe { intrinsics:: ctlz_nonzero( 1 as Self ) - intrinsics:: ctlz_nonzero( self ) } ;
2241+ Some ( log)
2242+ }
2243+ }
2244+ }
2245+
2246+ doc_comment! {
2247+ concat!( "Returns the base 10 logarithm of the number.
2248+
2249+ Returns `None` if the number is lower than 1.
2250+
2251+ # Examples
2252+
2253+ ```
2254+ #![feature(int_log)]
2255+
2256+ let ten = 10" , stringify!( $SelfT) , ";
2257+
2258+ // checked_log10(10) == 1
2259+ let result = ten.checked_log10();
2260+
2261+ assert_eq!(result, Some(1));
2262+ ```" ) ,
2263+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
2264+ #[ must_use = "this returns the result of the operation, \
2265+ without modifying the original"]
2266+ #[ inline]
2267+ pub fn checked_log10( self ) -> Option <Self > {
2268+ self . checked_log( 10 )
2269+ }
2270+ }
2271+
2272+
2273+
21632274 doc_comment! {
21642275 concat!( "Computes the absolute value of `self`.
21652276
@@ -4169,6 +4280,115 @@ assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer
41694280 }
41704281 }
41714282
4283+ doc_comment! {
4284+ concat!( "Returns the logarithm of the number with respect to an arbitrary base.
4285+
4286+ Returns `None` if the number is negative or zero, or if the base is negative, zero, or one.
4287+
4288+ This method may not be optimized owing to implementation details;
4289+ `self.checked_log2()` can produce results more efficiently for base 2, and
4290+ `self.checked_log10()` can produce results more efficiently for base 10.
4291+
4292+ # Examples
4293+
4294+ ```
4295+ #![feature(int_log)]
4296+
4297+ let five = 5" , stringify!( $SelfT) , ";
4298+
4299+ // log5(5) == 1
4300+ let result = five.checked_log(5);
4301+
4302+ assert_eq!(result, Some(1));
4303+ ```" ) ,
4304+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
4305+ #[ must_use = "this returns the result of the operation, \
4306+ without modifying the original"]
4307+ #[ inline]
4308+ pub fn checked_log( self , base: Self ) -> Option <Self > {
4309+ // SAFETY: We check the input to this is always positive.
4310+ let logb2 = |x: Self | unsafe { intrinsics:: ctlz_nonzero( 1 as Self ) - intrinsics:: ctlz_nonzero( x) } ;
4311+
4312+ if self <= 0 || base <= 1 {
4313+ None
4314+ } else {
4315+ let mut n = 0 ;
4316+ let mut r = self ;
4317+
4318+ // Optimization for 128 bit wide integers.
4319+ if mem:: size_of:: <Self >( ) * 8 == 128 {
4320+ let b = logb2( self ) / ( logb2( base) + 1 ) ;
4321+ n += b;
4322+ r /= base. pow( b as u32 ) ;
4323+ }
4324+
4325+ while r >= base {
4326+ r /= base;
4327+ n += 1 ;
4328+ }
4329+ Some ( n)
4330+ }
4331+ }
4332+ }
4333+
4334+ doc_comment! {
4335+ concat!( "Returns the base 2 logarithm of the number.
4336+
4337+ Returns `None` if the number is lower than 1.
4338+
4339+ # Examples
4340+
4341+ ```
4342+ #![feature(int_log)]
4343+
4344+ let two = 2" , stringify!( $SelfT) , ";
4345+
4346+ // checked_log2(2) == 1
4347+ let result = two.checked_log2();
4348+
4349+ assert_eq!(result, Some(1));
4350+ ```" ) ,
4351+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
4352+ #[ must_use = "this returns the result of the operation, \
4353+ without modifying the original"]
4354+ #[ inline]
4355+ pub fn checked_log2( self ) -> Option <Self > {
4356+ if self <= 0 {
4357+ None
4358+ } else {
4359+ // SAFETY: We just checked that this number is positive
4360+ let log = unsafe { intrinsics:: ctlz_nonzero( 1 as Self ) - intrinsics:: ctlz_nonzero( self ) } ;
4361+ Some ( log)
4362+ }
4363+ }
4364+ }
4365+
4366+ doc_comment! {
4367+ concat!( "Returns the base 10 logarithm of the number.
4368+
4369+ Returns `None` if the number is lower than 1.
4370+
4371+ # Examples
4372+
4373+ ```
4374+ #![feature(int_log)]
4375+
4376+ let ten = 10" , stringify!( $SelfT) , ";
4377+
4378+ // checked_log10(10) == 1
4379+ let result = ten.checked_log10();
4380+
4381+ assert_eq!(result, Some(1));
4382+ ```" ) ,
4383+ #[ unstable( feature = "int_log" , issue = "70887" ) ]
4384+ #[ must_use = "this returns the result of the operation, \
4385+ without modifying the original"]
4386+ #[ inline]
4387+ pub fn checked_log10( self ) -> Option <Self > {
4388+ self . checked_log( 10 )
4389+ }
4390+ }
4391+
41724392 doc_comment! {
41734393 concat!( "Returns `true` if and only if `self == 2^k` for some `k`.
41744394
0 commit comments