| ... | ... | @@ -277,6 +277,8 @@ test { |
| 277 | 277 | std.testing.refAllDecls(@This()); |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | /// Returns the number of bits in the mantissa of floating point type |
| 281 | /// T. |
| 280 | 282 | pub fn floatMantissaBits(comptime T: type) comptime_int { |
| 281 | 283 | assert(@typeInfo(T) == .Float); |
| 282 | 284 | |
| ... | ... | @@ -290,6 +292,8 @@ pub fn floatMantissaBits(comptime T: type) comptime_int { |
| 290 | 292 | }; |
| 291 | 293 | } |
| 292 | 294 | |
| 295 | /// Returns the number of bits in the exponent of floating point type |
| 296 | /// T. |
| 293 | 297 | pub fn floatExponentBits(comptime T: type) comptime_int { |
| 294 | 298 | assert(@typeInfo(T) == .Float); |
| 295 | 299 | |
| ... | ... | @@ -322,20 +326,22 @@ pub fn Min(comptime A: type, comptime B: type) type { |
| 322 | 326 | return @TypeOf(@as(A, 0) + @as(B, 0)); |
| 323 | 327 | } |
| 324 | 328 | |
| 325 | | /// Returns the smaller number. When one of the parameter's type's full range fits in the other, |
| 326 | | /// the return type is the smaller type. |
| 329 | /// Returns the smaller number. When one parameter's type's full range |
| 330 | /// fits in the other, the return type is the smaller type. |
| 327 | 331 | pub fn min(x: anytype, y: anytype) Min(@TypeOf(x), @TypeOf(y)) { |
| 328 | 332 | const Result = Min(@TypeOf(x), @TypeOf(y)); |
| 329 | 333 | if (x < y) { |
| 330 | | // TODO Zig should allow this as an implicit cast because x is immutable and in this |
| 331 | | // scope it is known to fit in the return type. |
| 334 | // TODO Zig should allow this as an implicit cast because x is |
| 335 | // immutable and in this scope it is known to fit in the |
| 336 | // return type. |
| 332 | 337 | switch (@typeInfo(Result)) { |
| 333 | 338 | .Int => return @intCast(Result, x), |
| 334 | 339 | else => return x, |
| 335 | 340 | } |
| 336 | 341 | } else { |
| 337 | | // TODO Zig should allow this as an implicit cast because y is immutable and in this |
| 338 | | // scope it is known to fit in the return type. |
| 342 | // TODO Zig should allow this as an implicit cast because y is |
| 343 | // immutable and in this scope it is known to fit in the |
| 344 | // return type. |
| 339 | 345 | switch (@typeInfo(Result)) { |
| 340 | 346 | .Int => return @intCast(Result, y), |
| 341 | 347 | else => return y, |
| ... | ... | @@ -375,7 +381,7 @@ test "math.min" { |
| 375 | 381 | } |
| 376 | 382 | } |
| 377 | 383 | |
| 378 | | /// Finds the min of three numbers |
| 384 | /// Finds the minimum of three numbers. |
| 379 | 385 | pub fn min3(x: anytype, y: anytype, z: anytype) @TypeOf(x, y, z) { |
| 380 | 386 | return min(x, min(y, z)); |
| 381 | 387 | } |
| ... | ... | @@ -389,6 +395,8 @@ test "math.min3" { |
| 389 | 395 | try testing.expect(min3(@as(i32, 2), @as(i32, 1), @as(i32, 0)) == 0); |
| 390 | 396 | } |
| 391 | 397 | |
| 398 | /// Returns the maximum of two numbers. Return type is the one with the |
| 399 | /// larger range. |
| 392 | 400 | pub fn max(x: anytype, y: anytype) @TypeOf(x, y) { |
| 393 | 401 | return if (x > y) x else y; |
| 394 | 402 | } |
| ... | ... | @@ -398,7 +406,7 @@ test "math.max" { |
| 398 | 406 | try testing.expect(max(@as(i32, 2), @as(i32, -1)) == 2); |
| 399 | 407 | } |
| 400 | 408 | |
| 401 | | /// Finds the max of three numbers |
| 409 | /// Finds the maximum of three numbers. |
| 402 | 410 | pub fn max3(x: anytype, y: anytype, z: anytype) @TypeOf(x, y, z) { |
| 403 | 411 | return max(x, max(y, z)); |
| 404 | 412 | } |
| ... | ... | @@ -412,6 +420,7 @@ test "math.max3" { |
| 412 | 420 | try testing.expect(max3(@as(i32, 2), @as(i32, 1), @as(i32, 0)) == 2); |
| 413 | 421 | } |
| 414 | 422 | |
| 423 | /// Limit val to the inclusive range [lower, upper]. |
| 415 | 424 | pub fn clamp(val: anytype, lower: anytype, upper: anytype) @TypeOf(val, lower, upper) { |
| 416 | 425 | assert(lower <= upper); |
| 417 | 426 | return max(lower, min(val, upper)); |
| ... | ... | @@ -433,17 +442,20 @@ test "math.clamp" { |
| 433 | 442 | try testing.expect(std.math.clamp(i, 0, 1) == 1); |
| 434 | 443 | } |
| 435 | 444 | |
| 445 | /// Returns the product of a and b. Returns an error on overflow. |
| 436 | 446 | pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) { |
| 437 | 447 | var answer: T = undefined; |
| 438 | 448 | return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| 439 | 449 | } |
| 440 | 450 | |
| 451 | /// Returns the sum of a and b. Returns an error on overflow. |
| 441 | 452 | pub fn add(comptime T: type, a: T, b: T) (error{Overflow}!T) { |
| 442 | 453 | if (T == comptime_int) return a + b; |
| 443 | 454 | var answer: T = undefined; |
| 444 | 455 | return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| 445 | 456 | } |
| 446 | 457 | |
| 458 | /// Returns a - b, or an error on overflow. |
| 447 | 459 | pub fn sub(comptime T: type, a: T, b: T) (error{Overflow}!T) { |
| 448 | 460 | var answer: T = undefined; |
| 449 | 461 | return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| ... | ... | @@ -453,6 +465,8 @@ pub fn negate(x: anytype) !@TypeOf(x) { |
| 453 | 465 | return sub(@TypeOf(x), 0, x); |
| 454 | 466 | } |
| 455 | 467 | |
| 468 | /// Shifts a left by shift_amt. Returns an error on overflow. shift_amt |
| 469 | /// is unsigned. |
| 456 | 470 | pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T { |
| 457 | 471 | var answer: T = undefined; |
| 458 | 472 | return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer; |
| ... | ... | @@ -538,8 +552,8 @@ test "math.shr" { |
| 538 | 552 | try testing.expect(shr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){42}, 33)[0] == 0); |
| 539 | 553 | } |
| 540 | 554 | |
| 541 | | /// Rotates right. Only unsigned values can be rotated. |
| 542 | | /// Negative shift values results in shift modulo the bit count. |
| 555 | /// Rotates right. Only unsigned values can be rotated. Negative shift |
| 556 | /// values result in shift modulo the bit count. |
| 543 | 557 | pub fn rotr(comptime T: type, x: T, r: anytype) T { |
| 544 | 558 | if (@typeInfo(T) == .Vector) { |
| 545 | 559 | const C = @typeInfo(T).Vector.child; |
| ... | ... | @@ -566,8 +580,8 @@ test "math.rotr" { |
| 566 | 580 | try testing.expect(rotr(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1}, @as(isize, -1))[0] == @as(u32, 1) << 1); |
| 567 | 581 | } |
| 568 | 582 | |
| 569 | | /// Rotates left. Only unsigned values can be rotated. |
| 570 | | /// Negative shift values results in shift modulo the bit count. |
| 583 | /// Rotates left. Only unsigned values can be rotated. Negative shift |
| 584 | /// values result in shift modulo the bit count. |
| 571 | 585 | pub fn rotl(comptime T: type, x: T, r: anytype) T { |
| 572 | 586 | if (@typeInfo(T) == .Vector) { |
| 573 | 587 | const C = @typeInfo(T).Vector.child; |
| ... | ... | @@ -594,6 +608,8 @@ test "math.rotl" { |
| 594 | 608 | try testing.expect(rotl(std.meta.Vector(1, u32), std.meta.Vector(1, u32){1 << 31}, @as(isize, -1))[0] == @as(u32, 1) << 30); |
| 595 | 609 | } |
| 596 | 610 | |
| 611 | /// Returns an unsigned int type that can hold the number of bits in T |
| 612 | /// - 1. Suitable for 0-based bit indices of T. |
| 597 | 613 | pub fn Log2Int(comptime T: type) type { |
| 598 | 614 | // comptime ceil log2 |
| 599 | 615 | comptime var count = 0; |
| ... | ... | @@ -605,6 +621,7 @@ pub fn Log2Int(comptime T: type) type { |
| 605 | 621 | return std.meta.Int(.unsigned, count); |
| 606 | 622 | } |
| 607 | 623 | |
| 624 | /// Returns an unsigned int type that can hold the number of bits in T. |
| 608 | 625 | pub fn Log2IntCeil(comptime T: type) type { |
| 609 | 626 | // comptime ceil log2 |
| 610 | 627 | comptime var count = 0; |
| ... | ... | @@ -616,6 +633,7 @@ pub fn Log2IntCeil(comptime T: type) type { |
| 616 | 633 | return std.meta.Int(.unsigned, count); |
| 617 | 634 | } |
| 618 | 635 | |
| 636 | /// Returns the smallest integer type that can hold both from and to. |
| 619 | 637 | pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type { |
| 620 | 638 | assert(from <= to); |
| 621 | 639 | if (from == 0 and to == 0) { |
| ... | ... | @@ -691,6 +709,8 @@ fn testOverflow() !void { |
| 691 | 709 | try testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); |
| 692 | 710 | } |
| 693 | 711 | |
| 712 | /// Returns the absolute value of x, where x is a value of an integer |
| 713 | /// type. |
| 694 | 714 | pub fn absInt(x: anytype) !@TypeOf(x) { |
| 695 | 715 | const T = @TypeOf(x); |
| 696 | 716 | comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt |
| ... | ... | @@ -724,6 +744,8 @@ fn testAbsFloat() !void { |
| 724 | 744 | try testing.expect(absFloat(@as(f32, 10.05)) == 10.05); |
| 725 | 745 | } |
| 726 | 746 | |
| 747 | /// Divide numerator by denominator, rounding toward zero. Returns an |
| 748 | /// error on overflow or when denominator is zero. |
| 727 | 749 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { |
| 728 | 750 | @setRuntimeSafety(false); |
| 729 | 751 | if (denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -745,6 +767,9 @@ fn testDivTrunc() !void { |
| 745 | 767 | try testing.expect((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0); |
| 746 | 768 | } |
| 747 | 769 | |
| 770 | /// Divide numerator by denominator, rounding toward negative |
| 771 | /// infinity. Returns an error on overflow or when denominator is |
| 772 | /// zero. |
| 748 | 773 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { |
| 749 | 774 | @setRuntimeSafety(false); |
| 750 | 775 | if (denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -766,6 +791,9 @@ fn testDivFloor() !void { |
| 766 | 791 | try testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0); |
| 767 | 792 | } |
| 768 | 793 | |
| 794 | /// Divide numerator by denominator, rounding toward positive |
| 795 | /// infinity. Returns an error on overflow or when denominator is |
| 796 | /// zero. |
| 769 | 797 | pub fn divCeil(comptime T: type, numerator: T, denominator: T) !T { |
| 770 | 798 | @setRuntimeSafety(false); |
| 771 | 799 | if (comptime std.meta.trait.isNumber(T) and denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -819,6 +847,8 @@ fn testDivCeil() !void { |
| 819 | 847 | try testing.expectError(error.DivisionByZero, divCeil(comptime_float, 23.0, 0.0)); |
| 820 | 848 | } |
| 821 | 849 | |
| 850 | /// Divide numerator by denominator. Return an error if quotient is |
| 851 | /// not an integer, denominator is zero, or on overflow. |
| 822 | 852 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { |
| 823 | 853 | @setRuntimeSafety(false); |
| 824 | 854 | if (denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -844,6 +874,9 @@ fn testDivExact() !void { |
| 844 | 874 | try testing.expectError(error.UnexpectedRemainder, divExact(f32, 5.0, 2.0)); |
| 845 | 875 | } |
| 846 | 876 | |
| 877 | /// Returns numerator modulo denominator, or an error if denominator is |
| 878 | /// zero or negative. Negative numerators never result in negative |
| 879 | /// return values. |
| 847 | 880 | pub fn mod(comptime T: type, numerator: T, denominator: T) !T { |
| 848 | 881 | @setRuntimeSafety(false); |
| 849 | 882 | if (denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -867,6 +900,9 @@ fn testMod() !void { |
| 867 | 900 | try testing.expectError(error.DivisionByZero, mod(f32, 10, 0)); |
| 868 | 901 | } |
| 869 | 902 | |
| 903 | /// Returns the remainder when numerator is divided by denominator, or |
| 904 | /// an error if denominator is zero or negative. Negative numerators |
| 905 | /// can give negative results. |
| 870 | 906 | pub fn rem(comptime T: type, numerator: T, denominator: T) !T { |
| 871 | 907 | @setRuntimeSafety(false); |
| 872 | 908 | if (denominator == 0) return error.DivisionByZero; |
| ... | ... | @@ -989,6 +1025,8 @@ pub fn isPowerOfTwo(v: anytype) bool { |
| 989 | 1025 | return (v & (v - 1)) == 0; |
| 990 | 1026 | } |
| 991 | 1027 | |
| 1028 | /// Returns the nearest power of two less than or equal to value, or |
| 1029 | /// zero if value is less than or equal to zero. |
| 992 | 1030 | pub fn floorPowerOfTwo(comptime T: type, value: T) T { |
| 993 | 1031 | var x = value; |
| 994 | 1032 | |
| ... | ... | @@ -1042,6 +1080,9 @@ pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) { |
| 1042 | 1080 | return @intCast(T, x); |
| 1043 | 1081 | } |
| 1044 | 1082 | |
| 1083 | /// Returns the next power of two (if the value is not already a power |
| 1084 | /// of two). Only unsigned integers can be used. Zero is not an |
| 1085 | /// allowed input. Asserts that the value fits. |
| 1045 | 1086 | pub fn ceilPowerOfTwoAssert(comptime T: type, value: T) T { |
| 1046 | 1087 | return ceilPowerOfTwo(T, value) catch unreachable; |
| 1047 | 1088 | } |
| ... | ... | @@ -1080,6 +1121,8 @@ fn testCeilPowerOfTwo() !void { |
| 1080 | 1121 | try testing.expectError(error.Overflow, ceilPowerOfTwo(u4, 9)); |
| 1081 | 1122 | } |
| 1082 | 1123 | |
| 1124 | /// Return the log base 2 of integer value x, rounding down to the |
| 1125 | /// nearest integer. |
| 1083 | 1126 | pub fn log2_int(comptime T: type, x: T) Log2Int(T) { |
| 1084 | 1127 | if (@typeInfo(T) != .Int or @typeInfo(T).Int.signedness != .unsigned) |
| 1085 | 1128 | @compileError("log2_int requires an unsigned integer, found " ++ @typeName(T)); |
| ... | ... | @@ -1087,6 +1130,8 @@ pub fn log2_int(comptime T: type, x: T) Log2Int(T) { |
| 1087 | 1130 | return @intCast(Log2Int(T), @typeInfo(T).Int.bits - 1 - @clz(T, x)); |
| 1088 | 1131 | } |
| 1089 | 1132 | |
| 1133 | /// Return the log base 2 of integer value x, rounding up to the |
| 1134 | /// nearest integer. |
| 1090 | 1135 | pub fn log2_int_ceil(comptime T: type, x: T) Log2IntCeil(T) { |
| 1091 | 1136 | if (@typeInfo(T) != .Int or @typeInfo(T).Int.signedness != .unsigned) |
| 1092 | 1137 | @compileError("log2_int_ceil requires an unsigned integer, found " ++ @typeName(T)); |
| ... | ... | @@ -1109,8 +1154,9 @@ test "std.math.log2_int_ceil" { |
| 1109 | 1154 | try testing.expect(log2_int_ceil(u32, 10) == 4); |
| 1110 | 1155 | } |
| 1111 | 1156 | |
| 1112 | | ///Cast a value to a different type. If the value doesn't fit in, or can't be perfectly represented by, |
| 1113 | | ///the new type, it will be converted to the closest possible representation. |
| 1157 | /// Cast a value to a different type. If the value doesn't fit in, or |
| 1158 | /// can't be perfectly represented by, the new type, it will be |
| 1159 | /// converted to the closest possible representation. |
| 1114 | 1160 | pub fn lossyCast(comptime T: type, value: anytype) T { |
| 1115 | 1161 | switch (@typeInfo(T)) { |
| 1116 | 1162 | .Float => { |
| ... | ... | @@ -1161,6 +1207,7 @@ test "math.f64_min" { |
| 1161 | 1207 | try testing.expect(@bitCast(u64, fmin) == f64_min_u64); |
| 1162 | 1208 | } |
| 1163 | 1209 | |
| 1210 | /// Returns the maximum value of integer type T. |
| 1164 | 1211 | pub fn maxInt(comptime T: type) comptime_int { |
| 1165 | 1212 | const info = @typeInfo(T); |
| 1166 | 1213 | const bit_count = info.Int.bits; |
| ... | ... | @@ -1168,6 +1215,7 @@ pub fn maxInt(comptime T: type) comptime_int { |
| 1168 | 1215 | return (1 << (bit_count - @boolToInt(info.Int.signedness == .signed))) - 1; |
| 1169 | 1216 | } |
| 1170 | 1217 | |
| 1218 | /// Returns the minimum value of integer type T. |
| 1171 | 1219 | pub fn minInt(comptime T: type) comptime_int { |
| 1172 | 1220 | const info = @typeInfo(T); |
| 1173 | 1221 | const bit_count = info.Int.bits; |
| ... | ... | @@ -1218,8 +1266,16 @@ test "max value type" { |
| 1218 | 1266 | try testing.expect(x == 2147483647); |
| 1219 | 1267 | } |
| 1220 | 1268 | |
| 1221 | | pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits * 2) { |
| 1222 | | const ResultInt = std.meta.Int(@typeInfo(T).Int.signedness, @typeInfo(T).Int.bits * 2); |
| 1269 | /// Multiply a and b. Return type is wide enough to guarantee no |
| 1270 | /// overflow. |
| 1271 | pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int( |
| 1272 | @typeInfo(T).Int.signedness, |
| 1273 | @typeInfo(T).Int.bits * 2, |
| 1274 | ) { |
| 1275 | const ResultInt = std.meta.Int( |
| 1276 | @typeInfo(T).Int.signedness, |
| 1277 | @typeInfo(T).Int.bits * 2, |
| 1278 | ); |
| 1223 | 1279 | return @as(ResultInt, a) * @as(ResultInt, b); |
| 1224 | 1280 | } |
| 1225 | 1281 | |