@@ -1082,7 +1082,19 @@ fn render_memory_layout(
10821082
10831083 if config. niches {
10841084 if let Some ( niches) = layout. niches ( ) {
1085- format_to ! ( label, "niches = {niches}, " ) ;
1085+ if niches > 1024 {
1086+ if niches. is_power_of_two ( ) {
1087+ format_to ! ( label, "niches = 2{}, " , pwr2_to_exponent( niches) ) ;
1088+ } else if is_pwr2plus1 ( niches) {
1089+ format_to ! ( label, "niches = 2{} + 1, " , pwr2_to_exponent( niches - 1 ) ) ;
1090+ } else if is_pwr2minus1 ( niches) {
1091+ format_to ! ( label, "niches = 2{} - 1, " , pwr2_to_exponent( niches + 1 ) ) ;
1092+ } else {
1093+ format_to ! ( label, "niches = a lot, " ) ;
1094+ }
1095+ } else {
1096+ format_to ! ( label, "niches = {niches}, " ) ;
1097+ }
10861098 }
10871099 }
10881100 label. pop ( ) ; // ' '
@@ -1210,3 +1222,74 @@ fn render_dyn_compatibility(
12101222 }
12111223 }
12121224}
1225+
1226+ fn is_pwr2minus1 ( val : u128 ) -> bool {
1227+ val == u128:: MAX || ( val + 1 ) . is_power_of_two ( )
1228+ }
1229+
1230+ fn is_pwr2plus1 ( val : u128 ) -> bool {
1231+ val != 0 && ( val - 1 ) . is_power_of_two ( )
1232+ }
1233+
1234+ /// Formats a power of two as an exponent of two, i.e. 16 => ⁴. Note that `num` MUST be a power
1235+ /// of 2, or this function will panic.
1236+ fn pwr2_to_exponent ( num : u128 ) -> String {
1237+ const DIGITS : [ char ; 10 ] = [ '⁰' , '¹' , '²' , '³' , '⁴' , '⁵' , '⁶' , '⁷' , '⁸' , '⁹' ] ;
1238+ assert_eq ! ( num. count_ones( ) , 1 ) ;
1239+ num. trailing_zeros ( )
1240+ . to_string ( )
1241+ . chars ( )
1242+ . map ( |c| c. to_digit ( 10 ) . unwrap ( ) as usize )
1243+ . map ( |idx| DIGITS [ idx] )
1244+ . collect :: < String > ( )
1245+ }
1246+
1247+ #[ cfg( test) ]
1248+ mod tests {
1249+ use super :: * ;
1250+
1251+ const TESTERS : [ u128 ; 10 ] = [ 0 , 1 , 2 , 3 , 4 , 255 , 256 , 257 , u128:: MAX - 1 , u128:: MAX ] ;
1252+
1253+ #[ test]
1254+ fn test_is_pwr2minus1 ( ) {
1255+ const OUTCOMES : [ bool ; 10 ] =
1256+ [ true , true , false , true , false , true , false , false , false , true ] ;
1257+ for ( test, expected) in TESTERS . iter ( ) . zip ( OUTCOMES ) {
1258+ let actual = is_pwr2minus1 ( * test) ;
1259+ assert_eq ! ( actual, expected, "is_pwr2minu1({test}) gave {actual}, expected {expected}" ) ;
1260+ }
1261+ }
1262+
1263+ #[ test]
1264+ fn test_is_pwr2plus1 ( ) {
1265+ const OUTCOMES : [ bool ; 10 ] =
1266+ [ false , false , true , true , false , false , false , true , false , false ] ;
1267+ for ( test, expected) in TESTERS . iter ( ) . zip ( OUTCOMES ) {
1268+ let actual = is_pwr2plus1 ( * test) ;
1269+ assert_eq ! ( actual, expected, "is_pwr2plus1({test}) gave {actual}, expected {expected}" ) ;
1270+ }
1271+ }
1272+
1273+ #[ test]
1274+ fn test_pwr2_to_exponent ( ) {
1275+ const TESTERS : [ u128 ; 9 ] = [
1276+ 1 ,
1277+ 2 ,
1278+ 4 ,
1279+ 8 ,
1280+ 16 ,
1281+ 9223372036854775808 ,
1282+ 18446744073709551616 ,
1283+ 36893488147419103232 ,
1284+ 170141183460469231731687303715884105728 ,
1285+ ] ;
1286+ const OUTCOMES : [ & str ; 9 ] = [ "⁰" , "¹" , "²" , "³" , "⁴" , "⁶³" , "⁶⁴" , "⁶⁵" , "¹²⁷" ] ;
1287+ for ( test, expected) in TESTERS . iter ( ) . zip ( OUTCOMES ) {
1288+ let actual = pwr2_to_exponent ( * test) ;
1289+ assert_eq ! (
1290+ actual, expected,
1291+ "pwr2_to_exponent({test}) returned {actual}, expected {expected}" ,
1292+ ) ;
1293+ }
1294+ }
1295+ }
0 commit comments