Changed add ans sub to prevent losing info

This commit is contained in:
adrien 2026-04-20 23:56:26 +02:00
parent b3cee0588f
commit eb02b3eb96

View File

@ -45,16 +45,34 @@ pub fn Quantity(T: type, d: Dimensions, s: Scales) type {
return res; return res;
} }
pub fn add(self: Self, rhs: anytype) Self { pub fn add(self: Self, rhs: anytype) Quantity(
T,
dims,
scales.min(@TypeOf(rhs).scales),
) {
if (comptime !dims.eql(@TypeOf(rhs).dims)) if (comptime !dims.eql(@TypeOf(rhs).dims))
@compileError("Dimension mismatch in add"); @compileError("Dimension mismatch in add");
return .{ .value = self.value + rhs.to(Self).value };
const TargetType = Quantity(T, dims, scales.min(@TypeOf(rhs).scales));
const lhs_converted = self.to(TargetType);
const rhs_converted = rhs.to(TargetType);
return .{ .value = lhs_converted.value + rhs_converted.value };
} }
pub fn sub(self: Self, rhs: anytype) Self { pub fn sub(self: Self, rhs: anytype) Quantity(
T,
dims,
scales.min(@TypeOf(rhs).scales),
) {
if (comptime !dims.eql(@TypeOf(rhs).dims)) if (comptime !dims.eql(@TypeOf(rhs).dims))
@compileError("Dimension mismatch in sub"); @compileError("Dimension mismatch in sub");
return .{ .value = self.value - rhs.to(Self).value };
const TargetType = Quantity(T, dims, scales.min(@TypeOf(rhs).scales));
const lhs_converted = self.to(TargetType);
const rhs_converted = rhs.to(TargetType);
return .{ .value = lhs_converted.value - rhs_converted.value };
} }
pub fn mulBy(self: Self, rhs: anytype) Quantity( pub fn mulBy(self: Self, rhs: anytype) Quantity(
@ -155,21 +173,30 @@ pub fn QuantityVec3(Q: type) type {
return .{ .x = v, .y = v, .z = v }; return .{ .x = v, .y = v, .z = v };
} }
pub fn add(self: Self, rhs: anytype) Self { pub fn add(self: Self, rhs: anytype) QuantityVec3(Quantity(T, d, s.min(@TypeOf(rhs).scales))) {
const Tr = @TypeOf(rhs); const Tr = @TypeOf(rhs);
// We leverage the logic in the scalar Quantity.add
const qx = (Q{ .value = self.x }).add(Tr.QuantityType{ .value = rhs.x });
const qy = (Q{ .value = self.y }).add(Tr.QuantityType{ .value = rhs.y });
const qz = (Q{ .value = self.z }).add(Tr.QuantityType{ .value = rhs.z });
return .{ return .{
.x = (Q{ .value = self.x }).add(Tr.QuantityType{ .value = rhs.x }).value, .x = qx.value,
.y = (Q{ .value = self.y }).add(Tr.QuantityType{ .value = rhs.y }).value, .y = qy.value,
.z = (Q{ .value = self.z }).add(Tr.QuantityType{ .value = rhs.z }).value, .z = qz.value,
}; };
} }
pub fn sub(self: Self, rhs: anytype) Self { pub fn sub(self: Self, rhs: anytype) QuantityVec3(Quantity(T, d, s.min(@TypeOf(rhs).scales))) {
const Tr = @TypeOf(rhs); const Tr = @TypeOf(rhs);
const qx = (Q{ .value = self.x }).sub(Tr.QuantityType{ .value = rhs.x });
const qy = (Q{ .value = self.y }).sub(Tr.QuantityType{ .value = rhs.y });
const qz = (Q{ .value = self.z }).sub(Tr.QuantityType{ .value = rhs.z });
return .{ return .{
.x = (Q{ .value = self.x }).sub(Tr.QuantityType{ .value = rhs.x }).value, .x = qx.value,
.y = (Q{ .value = self.y }).sub(Tr.QuantityType{ .value = rhs.y }).value, .y = qy.value,
.z = (Q{ .value = self.z }).sub(Tr.QuantityType{ .value = rhs.z }).value, .z = qz.value,
}; };
} }
@ -318,15 +345,15 @@ test "Add" {
try std.testing.expectEqual(1, @TypeOf(added2).dims.get(.L)); try std.testing.expectEqual(1, @TypeOf(added2).dims.get(.L));
std.debug.print("KiloMeter {f} + {f} = {f} OK\n", .{ distance, distance3, added2 }); std.debug.print("KiloMeter {f} + {f} = {f} OK\n", .{ distance, distance3, added2 });
const added3 = distance3.add(distance); const added3 = distance3.add(distance).to(KiloMeter);
try std.testing.expectEqual(2, added3.value); try std.testing.expectEqual(2, added3.value);
try std.testing.expectEqual(1, @TypeOf(added3).dims.get(.L)); try std.testing.expectEqual(1, @TypeOf(added3).dims.get(.L));
std.debug.print("KiloMeter {f} + {f} = {f} OK\n", .{ distance3, distance, added3 }); std.debug.print("KiloMeter {f} + {f} = {f} OK\n", .{ distance3, distance, added3 });
const KiloMeter_f = Quantity(f64, Dimensions.init(.{ .L = 1 }), Scales.init(.{ .L = .k })); const KiloMeter_f = Quantity(f64, Dimensions.init(.{ .L = 1 }), Scales.init(.{ .L = .k }));
const distance4 = KiloMeter_f{ .value = 2 }; const distance4 = KiloMeter_f{ .value = 2 };
const added4 = distance4.add(distance); const added4 = distance4.add(distance).to(KiloMeter_f);
try std.testing.expectEqual(2.01, added4.value); try std.testing.expectApproxEqAbs(2.01, added4.value, 0.000001);
try std.testing.expectEqual(1, @TypeOf(added4).dims.get(.L)); try std.testing.expectEqual(1, @TypeOf(added4).dims.get(.L));
std.debug.print("KiloMeter_f {f} + {f} = {f} OK\n", .{ distance4, distance, added4 }); std.debug.print("KiloMeter_f {f} + {f} = {f} OK\n", .{ distance4, distance, added4 });
} }
@ -349,7 +376,7 @@ test "Sub" {
const km_f = KiloMeter_f{ .value = 2.5 }; const km_f = KiloMeter_f{ .value = 2.5 };
const m_f = Meter{ .value = 500 }; const m_f = Meter{ .value = 500 };
const diff3 = km_f.sub(m_f); const diff3 = km_f.sub(m_f);
try std.testing.expectApproxEqAbs(@as(f32, 2.0), diff3.value, 1e-4); try std.testing.expectApproxEqAbs(2000, diff3.value, 1e-4);
std.debug.print("Sub float cross-scale: {f} - {f} = {f} OK\n", .{ km_f, m_f, diff3 }); std.debug.print("Sub float cross-scale: {f} - {f} = {f} OK\n", .{ km_f, m_f, diff3 });
} }