| ... | ... | @@ -242,12 +242,69 @@ pub fn floatExponentBits(comptime T: type) comptime_int { |
| 242 | 242 | }; |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | | pub 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. |
| 247 | pub 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. |
| 271 | pub 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 | } |
| 247 | 290 | } |
| 248 | 291 | |
| 249 | 292 | test "math.min" { |
| 250 | 293 | 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 | } |
| 251 | 308 | } |
| 252 | 309 | |
| 253 | 310 | pub fn max(x: var, y: var) @typeOf(x + y) { |