| ... | @@ -365,6 +365,69 @@ pub fn Log2Int(comptime T: type) type { | ... | @@ -365,6 +365,69 @@ pub fn Log2Int(comptime T: type) type { |
| 365 | return @IntType(false, count); | 365 | return @IntType(false, count); |
| 366 | } | 366 | } |
| 367 | | 367 | |
| | 368 | pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { |
| | 369 | assert(from <= to); |
| | 370 | if (from == 0 and to == 0) { |
| | 371 | return u0; |
| | 372 | } |
| | 373 | const is_signed = from < 0; |
| | 374 | const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement |
| | 375 | const base = log2(largest_positive_integer); |
| | 376 | const upper = (1 << base) - 1; |
| | 377 | var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1; |
| | 378 | if (is_signed) { |
| | 379 | magnitude_bits += 1; |
| | 380 | } |
| | 381 | return @IntType(is_signed, magnitude_bits); |
| | 382 | } |
| | 383 | |
| | 384 | test "math.IntFittingRange" { |
| | 385 | assert(IntFittingRange(0, 0) == u0); |
| | 386 | assert(IntFittingRange(0, 1) == u1); |
| | 387 | assert(IntFittingRange(0, 2) == u2); |
| | 388 | assert(IntFittingRange(0, 3) == u2); |
| | 389 | assert(IntFittingRange(0, 4) == u3); |
| | 390 | assert(IntFittingRange(0, 7) == u3); |
| | 391 | assert(IntFittingRange(0, 8) == u4); |
| | 392 | assert(IntFittingRange(0, 9) == u4); |
| | 393 | assert(IntFittingRange(0, 15) == u4); |
| | 394 | assert(IntFittingRange(0, 16) == u5); |
| | 395 | assert(IntFittingRange(0, 17) == u5); |
| | 396 | assert(IntFittingRange(0, 4095) == u12); |
| | 397 | assert(IntFittingRange(2000, 4095) == u12); |
| | 398 | assert(IntFittingRange(0, 4096) == u13); |
| | 399 | assert(IntFittingRange(2000, 4096) == u13); |
| | 400 | assert(IntFittingRange(0, 4097) == u13); |
| | 401 | assert(IntFittingRange(2000, 4097) == u13); |
| | 402 | assert(IntFittingRange(0, 123456789123456798123456789) == u87); |
| | 403 | assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177); |
| | 404 | |
| | 405 | assert(IntFittingRange(-1, -1) == i1); |
| | 406 | assert(IntFittingRange(-1, 0) == i1); |
| | 407 | assert(IntFittingRange(-1, 1) == i2); |
| | 408 | assert(IntFittingRange(-2, -2) == i2); |
| | 409 | assert(IntFittingRange(-2, -1) == i2); |
| | 410 | assert(IntFittingRange(-2, 0) == i2); |
| | 411 | assert(IntFittingRange(-2, 1) == i2); |
| | 412 | assert(IntFittingRange(-2, 2) == i3); |
| | 413 | assert(IntFittingRange(-1, 2) == i3); |
| | 414 | assert(IntFittingRange(-1, 3) == i3); |
| | 415 | assert(IntFittingRange(-1, 4) == i4); |
| | 416 | assert(IntFittingRange(-1, 7) == i4); |
| | 417 | assert(IntFittingRange(-1, 8) == i5); |
| | 418 | assert(IntFittingRange(-1, 9) == i5); |
| | 419 | assert(IntFittingRange(-1, 15) == i5); |
| | 420 | assert(IntFittingRange(-1, 16) == i6); |
| | 421 | assert(IntFittingRange(-1, 17) == i6); |
| | 422 | assert(IntFittingRange(-1, 4095) == i13); |
| | 423 | assert(IntFittingRange(-4096, 4095) == i13); |
| | 424 | assert(IntFittingRange(-1, 4096) == i14); |
| | 425 | assert(IntFittingRange(-4097, 4095) == i14); |
| | 426 | assert(IntFittingRange(-1, 4097) == i14); |
| | 427 | assert(IntFittingRange(-1, 123456789123456798123456789) == i88); |
| | 428 | assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178); |
| | 429 | } |
| | 430 | |
| 368 | test "math overflow functions" { | 431 | test "math overflow functions" { |
| 369 | testOverflow(); | 432 | testOverflow(); |
| 370 | comptime testOverflow(); | 433 | comptime testOverflow(); |