authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-07 16:27:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-07 16:28:23-04:00
log2cd5e555818583e77e5601d43d55339e8c4017b0
treee71b274b17d219b8264b8d8cb2f1ad8353da8725
parent8fcf21fefce56695820b5ec31161589822df8762
signature Commit is signed but in an unrecognized format.

std.math.min: return a more restrictive type sometimes


1 files changed, 59 insertions(+), 2 deletions(-)

std/math.zig+59-2
......@@ -242,12 +242,69 @@ pub fn floatExponentBits(comptime T: type) comptime_int {
242242 };
243243}
244244
245pub fn min(x: var, y: var) @typeOf(x + y) {
246 return if (x < y) x else y;
245/// Given two types, returns the smallest one which is capable of holding the
246/// full range of the minimum value.
247pub fn Min(comptime A: type, comptime B: type) type {
248 return switch (@typeInfo(A)) {
249 .Int => |a_info| switch (@typeInfo(B)) {
250 .Int => |b_info| blk: {
251 if (a_info.is_signed == b_info.is_signed) {
252 break :blk if (a_info.bits < b_info.bits) A else B;
253 } else if (a_info.is_signed) {
254 break :blk A;
255 } else {
256 break :blk B;
257 }
258 },
259 .ComptimeInt => A,
260 else => @compileError("unsupported type: " ++ @typeName(B)),
261 },
262 .Float => |a_info| if (a_info.bits < @typeInfo(B).Float.bits) A else B,
263 .ComptimeInt => B,
264 .ComptimeFloat => B,
265 else => @compileError("unsupported type: " ++ @typeName(A)),
266 };
267}
268
269/// Returns the smaller number. When one of the parameter's type's full range fits in the other,
270/// the return type is the smaller type.
271pub fn min(x: var, y: var) Min(@typeOf(x), @typeOf(y)) {
272 const Result = Min(@typeOf(x), @typeOf(y));
273 if (x < y) {
274 // TODO Zig should allow this as an implicit cast because x is immutable and in this
275 // scope it is known to fit in the return type.
276 switch (@typeInfo(Result)) {
277 .Int => return @intCast(Result, x),
278 .Float => return @floatCast(Result, x),
279 else => return x,
280 }
281 } else {
282 // TODO Zig should allow this as an implicit cast because y is immutable and in this
283 // scope it is known to fit in the return type.
284 switch (@typeInfo(Result)) {
285 .Int => return @intCast(Result, y),
286 .Float => return @floatCast(Result, y),
287 else => return y,
288 }
289 }
247290}
248291
249292test "math.min" {
250293 testing.expect(min(i32(-1), i32(2)) == -1);
294 {
295 var a: u16 = 999;
296 var b: u32 = 10;
297 var result = min(a, b);
298 testing.expect(@typeOf(result) == u16);
299 testing.expect(result == 10);
300 }
301 {
302 var a: f64 = 10.34;
303 var b: f32 = 999.12;
304 var result = min(a, b);
305 testing.expect(@typeOf(result) == f32);
306 testing.expect(result == 10.34);
307 }
251308}
252309
253310pub fn max(x: var, y: var) @typeOf(x + y) {