Compare commits
2 Commits
1f6b794ab6
...
7b038dd2a5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b038dd2a5 | ||
|
|
998404d82a |
@ -33,24 +33,24 @@ pub const Dimension = enum {
|
|||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
data: std.EnumArray(Dimension, i8),
|
data: std.EnumArray(Dimension, comptime_int),
|
||||||
|
|
||||||
pub fn init(comptime init_val: anytype) Self {
|
pub fn init(comptime init_val: anytype) Self {
|
||||||
var s = Self{ .data = std.EnumArray(Dimension, i8).initFill(0) };
|
var s = Self{ .data = std.EnumArray(Dimension, comptime_int).initFill(0) };
|
||||||
inline for (std.meta.fields(@TypeOf(init_val))) |f|
|
inline for (std.meta.fields(@TypeOf(init_val))) |f|
|
||||||
s.data.set(@field(Dimension, f.name), @field(init_val, f.name));
|
s.data.set(@field(Dimension, f.name), @field(init_val, f.name));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initFill(val: i8) Self {
|
pub fn initFill(comptime val: comptime_int) Self {
|
||||||
return .{ .data = std.EnumArray(Dimension, i8).initFill(val) };
|
return .{ .data = std.EnumArray(Dimension, comptime_int).initFill(val) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: Self, key: Dimension) i8 {
|
pub fn get(comptime self: Self, comptime key: Dimension) comptime_int {
|
||||||
return self.data.get(key);
|
return self.data.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: *Self, key: Dimension, val: i8) void {
|
pub fn set(comptime self: *Self, comptime key: Dimension, comptime val: i8) void {
|
||||||
self.data.set(key, val);
|
self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +64,13 @@ pub fn add(comptime a: Self, comptime b: Self) Self {
|
|||||||
pub fn sub(comptime a: Self, comptime b: Self) Self {
|
pub fn sub(comptime a: Self, comptime b: Self) Self {
|
||||||
@setEvalBranchQuota(10_000);
|
@setEvalBranchQuota(10_000);
|
||||||
var result = Self.initFill(0);
|
var result = Self.initFill(0);
|
||||||
for (std.enums.values(Dimension)) |d|
|
inline for (std.enums.values(Dimension)) |d|
|
||||||
result.set(d, a.get(d) - b.get(d));
|
result.set(d, a.get(d) - b.get(d));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eql(comptime a: Self, comptime b: Self) bool {
|
pub fn eql(comptime a: Self, comptime b: Self) bool {
|
||||||
for (std.enums.values(Dimension)) |d|
|
inline for (std.enums.values(Dimension)) |d|
|
||||||
if (a.get(d) != b.get(d)) return false;
|
if (a.get(d) != b.get(d)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const UnitScale = Scales.UnitScale;
|
|||||||
const Dimensions = @import("Dimensions.zig");
|
const Dimensions = @import("Dimensions.zig");
|
||||||
const Dimension = Dimensions.Dimension;
|
const Dimension = Dimensions.Dimension;
|
||||||
|
|
||||||
pub fn Quantity(T: type, d: Dimensions, s: Scales) type {
|
pub fn Quantity(comptime T: type, comptime d: Dimensions, comptime s: Scales) type {
|
||||||
return struct {
|
return struct {
|
||||||
value: T,
|
value: T,
|
||||||
|
|
||||||
@ -84,13 +84,13 @@ pub fn Quantity(T: type, d: Dimensions, s: Scales) type {
|
|||||||
|
|
||||||
// Fast-path: Native pure-integer exact conversions
|
// Fast-path: Native pure-integer exact conversions
|
||||||
if (comptime @typeInfo(T) == .int and @typeInfo(DestT) == .int) {
|
if (comptime @typeInfo(T) == .int and @typeInfo(DestT) == .int) {
|
||||||
if (ratio >= 1.0 and @round(ratio) == ratio) {
|
if (comptime ratio >= 1.0 and @round(ratio) == ratio) {
|
||||||
const mult: DestT = @intFromFloat(ratio);
|
const mult: DestT = comptime @intFromFloat(ratio);
|
||||||
return .{ .value = @as(DestT, @intCast(self.value)) * mult };
|
return .{ .value = @as(DestT, @intCast(self.value)) * mult };
|
||||||
} else if (ratio < 1.0 and @round(1.0 / ratio) == 1.0 / ratio) {
|
} else if (comptime ratio < 1.0 and @round(1.0 / ratio) == 1.0 / ratio) {
|
||||||
const div: DestT = @intFromFloat(1.0 / ratio);
|
const div: DestT = comptime @intFromFloat(1.0 / ratio);
|
||||||
const val = @as(DestT, @intCast(self.value));
|
const val = @as(DestT, @intCast(self.value));
|
||||||
const half = div / 2;
|
const half = comptime div / 2;
|
||||||
// Native round-to-nearest
|
// Native round-to-nearest
|
||||||
const rounded = if (val >= 0) @divTrunc(val + half, div) else @divTrunc(val - half, div);
|
const rounded = if (val >= 0) @divTrunc(val + half, div) else @divTrunc(val - half, div);
|
||||||
return .{ .value = rounded };
|
return .{ .value = rounded };
|
||||||
@ -100,21 +100,22 @@ pub fn Quantity(T: type, d: Dimensions, s: Scales) type {
|
|||||||
// Fallback preserving native Float types (e.g., f128 shouldn't downcast to f64)
|
// Fallback preserving native Float types (e.g., f128 shouldn't downcast to f64)
|
||||||
if (comptime @typeInfo(DestT) == .float) {
|
if (comptime @typeInfo(DestT) == .float) {
|
||||||
const val_f = switch (@typeInfo(T)) {
|
const val_f = switch (@typeInfo(T)) {
|
||||||
.int => @as(DestT, @floatFromInt(self.value)),
|
inline .int => @as(DestT, @floatFromInt(self.value)),
|
||||||
.float => @as(DestT, @floatCast(self.value)),
|
inline .float => @as(DestT, @floatCast(self.value)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
return .{ .value = val_f * @as(DestT, @floatCast(ratio)) };
|
return .{ .value = val_f * @as(DestT, @floatCast(ratio)) };
|
||||||
} else {
|
} else {
|
||||||
const val_f = switch (@typeInfo(T)) {
|
const val_f = switch (@typeInfo(T)) {
|
||||||
.int => @as(f64, @floatFromInt(self.value)),
|
inline .int => @as(f64, @floatFromInt(self.value)),
|
||||||
.float => @as(f64, @floatCast(self.value)),
|
inline .float => @as(f64, @floatCast(self.value)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
return .{ .value = @intFromFloat(@round(val_f * ratio)) };
|
return .{ .value = @intFromFloat(@round(val_f * ratio)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn Vec(self: Self, comptime len: usize) QuantityVec(len, Self) {
|
|
||||||
|
pub fn Vec(self: Self, comptime len: comptime_int) QuantityVec(len, Self) {
|
||||||
return QuantityVec(len, Self).initDefault(self.value);
|
return QuantityVec(len, Self).initDefault(self.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +128,10 @@ pub fn Quantity(T: type, d: Dimensions, s: Scales) type {
|
|||||||
writer: *std.Io.Writer,
|
writer: *std.Io.Writer,
|
||||||
) !void {
|
) !void {
|
||||||
try writer.print("{d}", .{self.value});
|
try writer.print("{d}", .{self.value});
|
||||||
var iter = std.EnumSet(Dimension).initFull().iterator();
|
|
||||||
var first = true;
|
var first = true;
|
||||||
while (iter.next()) |bu| {
|
inline for (std.enums.values(Dimension)) |bu| {
|
||||||
const v = dims.get(bu);
|
const v = dims.get(bu);
|
||||||
if (v == 0) continue;
|
if (comptime v == 0) continue;
|
||||||
if (!first)
|
if (!first)
|
||||||
try writer.writeAll(".");
|
try writer.writeAll(".");
|
||||||
|
|
||||||
@ -592,8 +592,7 @@ test "Overhead Analysis: Quantity vs Native" {
|
|||||||
a + b
|
a + b
|
||||||
else if (comptime std.mem.eql(u8, op_name, "mulBy"))
|
else if (comptime std.mem.eql(u8, op_name, "mulBy"))
|
||||||
a * b
|
a * b
|
||||||
else
|
else if (comptime @typeInfo(T) == .int) @divTrunc(a, b) else a / b;
|
||||||
if (comptime @typeInfo(T) == .int) @divTrunc(a, b) else a / b;
|
|
||||||
|
|
||||||
if (comptime @typeInfo(T) == .float) n_sink += r else n_sink ^= r;
|
if (comptime @typeInfo(T) == .float) n_sink += r else n_sink ^= r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,9 +154,8 @@ pub fn QuantityVec(comptime len: usize, comptime Q: type) type {
|
|||||||
try writer.print("{d:.2}", .{v});
|
try writer.print("{d:.2}", .{v});
|
||||||
}
|
}
|
||||||
try writer.writeAll(")");
|
try writer.writeAll(")");
|
||||||
var iter = std.EnumSet(Dimension).initFull().iterator();
|
|
||||||
var first = true;
|
var first = true;
|
||||||
while (iter.next()) |bu| {
|
inline for (std.enums.values(Dimension)) |bu| {
|
||||||
const v = dims.get(bu);
|
const v = dims.get(bu);
|
||||||
if (v == 0) continue;
|
if (v == 0) continue;
|
||||||
if (!first) try writer.writeAll(".");
|
if (!first) try writer.writeAll(".");
|
||||||
|
|||||||
@ -31,9 +31,9 @@ pub const UnitScale = enum(i32) {
|
|||||||
pub fn str(self: @This()) []const u8 {
|
pub fn str(self: @This()) []const u8 {
|
||||||
var buf: [16]u8 = undefined;
|
var buf: [16]u8 = undefined;
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.none => "",
|
inline .none => "",
|
||||||
inline .P, .T, .G, .M, .k, .h, .da, .d, .c, .m, .u, .n, .p, .f, .min, .hour, .year => @tagName(self),
|
inline .P, .T, .G, .M, .k, .h, .da, .d, .c, .m, .u, .n, .p, .f, .min, .hour, .year => @tagName(self),
|
||||||
else => std.fmt.bufPrint(&buf, "[{d}]", .{@intFromEnum(self)}) catch "[]",
|
else => std.fmt.bufPrint(&buf, "[{d}]", .{@intFromEnum(self)}) catch "[]", // This cannot be inline because of non exhaustive enum, but that's ok, it is just str, not calculation
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ pub const UnitScale = enum(i32) {
|
|||||||
pub fn getFactor(self: @This()) f64 {
|
pub fn getFactor(self: @This()) f64 {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
inline .P, .T, .G, .M, .k, .h, .da, .none, .d, .c, .m, .u, .n, .p, .f => std.math.pow(f64, 10.0, @floatFromInt(@intFromEnum(self))),
|
inline .P, .T, .G, .M, .k, .h, .da, .none, .d, .c, .m, .u, .n, .p, .f => std.math.pow(f64, 10.0, @floatFromInt(@intFromEnum(self))),
|
||||||
else => @floatFromInt(@intFromEnum(self)),
|
inline else => @floatFromInt(@intFromEnum(self)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ pub const UnitScale = enum(i32) {
|
|||||||
pub fn getFactorInt(self: @This()) i32 {
|
pub fn getFactorInt(self: @This()) i32 {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
inline .P, .T, .G, .M, .k, .h, .da, .none, .d, .c, .m, .u, .n, .p, .f => std.math.powi(i32, 10.0, @intFromEnum(self)) catch 0,
|
inline .P, .T, .G, .M, .k, .h, .da, .none, .d, .c, .m, .u, .n, .p, .f => std.math.powi(i32, 10.0, @intFromEnum(self)) catch 0,
|
||||||
else => @intFromEnum(self),
|
inline else => @intFromEnum(self),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -59,7 +59,7 @@ const Scales = @This();
|
|||||||
data: std.EnumArray(Dimension, UnitScale),
|
data: std.EnumArray(Dimension, UnitScale),
|
||||||
|
|
||||||
pub fn init(comptime init_val: anytype) Scales {
|
pub fn init(comptime init_val: anytype) Scales {
|
||||||
var s = Scales{ .data = std.EnumArray(Dimension, UnitScale).initFill(.none) };
|
comptime var s = Scales{ .data = std.EnumArray(Dimension, UnitScale).initFill(.none) };
|
||||||
inline for (std.meta.fields(@TypeOf(init_val))) |f| {
|
inline for (std.meta.fields(@TypeOf(init_val))) |f| {
|
||||||
if (comptime hlp.isInt(@TypeOf(@field(init_val, f.name))))
|
if (comptime hlp.isInt(@TypeOf(@field(init_val, f.name))))
|
||||||
s.data.set(@field(Dimension, f.name), @enumFromInt(@field(init_val, f.name)))
|
s.data.set(@field(Dimension, f.name), @enumFromInt(@field(init_val, f.name)))
|
||||||
@ -69,30 +69,30 @@ pub fn init(comptime init_val: anytype) Scales {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initFill(val: UnitScale) Scales {
|
pub fn initFill(comptime val: UnitScale) Scales {
|
||||||
return .{ .data = std.EnumArray(Dimension, UnitScale).initFill(val) };
|
return comptime .{ .data = std.EnumArray(Dimension, UnitScale).initFill(val) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: Scales, key: Dimension) UnitScale {
|
pub fn get(comptime self: Scales, comptime key: Dimension) UnitScale {
|
||||||
return self.data.get(key);
|
return comptime self.data.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: *Scales, key: Dimension, val: UnitScale) void {
|
pub fn set(comptime self: *Scales, comptime key: Dimension, comptime val: UnitScale) void {
|
||||||
self.data.set(key, val);
|
comptime self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min(comptime s1: Scales, comptime s2: Scales) Scales {
|
pub fn min(comptime s1: Scales, comptime s2: Scales) Scales {
|
||||||
@setEvalBranchQuota(10_000);
|
@setEvalBranchQuota(10_000);
|
||||||
var out = Scales.initFill(.none);
|
comptime var out = Scales.initFill(.none);
|
||||||
for (std.enums.values(Dimension)) |dim|
|
inline for (std.enums.values(Dimension)) |dim|
|
||||||
out.set(dim, if (s1.get(dim).getFactorInt() > s2.get(dim).getFactorInt()) s2.get(dim) else s1.get(dim));
|
out.set(dim, if (s1.get(dim).getFactorInt() > s2.get(dim).getFactorInt()) s2.get(dim) else s1.get(dim));
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getFactor(comptime s: Scales, comptime d: Dimensions) f64 {
|
pub fn getFactor(comptime s: Scales, comptime d: Dimensions) f64 {
|
||||||
var factor: f64 = 1.0;
|
comptime var factor: f64 = 1.0;
|
||||||
for (std.enums.values(Dimension)) |dim| {
|
inline for (std.enums.values(Dimension)) |dim| {
|
||||||
const power = d.get(dim);
|
const power = d.get(dim);
|
||||||
if (power == 0) continue;
|
if (power == 0) continue;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user