Removed ugly Scalar_
This commit is contained in:
parent
e4d55e36ab
commit
6c50a01d6e
@ -68,10 +68,17 @@ pub fn set(comptime self: *Self, comptime key: Dimension, comptime val: i8) void
|
|||||||
self.data.set(key, val);
|
self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn argsOpt(self: Self) ArgOpts {
|
||||||
|
var args: ArgOpts = undefined;
|
||||||
|
inline for (std.enums.values(Dimension)) |d|
|
||||||
|
@field(args, @tagName(d)) = self.get(d);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
/// Add exponents component-wise. Used internally by `mulBy`.
|
/// Add exponents component-wise. Used internally by `mulBy`.
|
||||||
pub fn add(comptime a: Self, comptime b: Self) Self {
|
pub fn add(comptime a: Self, comptime b: Self) Self {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ pub fn isScalarType(comptime T: type) bool {
|
|||||||
pub fn rhsScalarType(comptime BaseT: type, comptime RhsT: type) type {
|
pub fn rhsScalarType(comptime BaseT: type, comptime RhsT: type) type {
|
||||||
if (comptime isScalarType(RhsT)) return RhsT;
|
if (comptime isScalarType(RhsT)) return RhsT;
|
||||||
if (comptime RhsT == comptime_int or RhsT == comptime_float or RhsT == BaseT)
|
if (comptime RhsT == comptime_int or RhsT == comptime_float or RhsT == BaseT)
|
||||||
return Scalar_(BaseT, Dimensions.init(.{}), Scales.init(.{}));
|
return Scalar(BaseT, .{}, .{});
|
||||||
@compileError(
|
@compileError(
|
||||||
"rhs must be a Scalar, " ++ @typeName(BaseT) ++
|
"rhs must be a Scalar, " ++ @typeName(BaseT) ++
|
||||||
", comptime_int, or comptime_float; got " ++ @typeName(RhsT),
|
", comptime_int, or comptime_float; got " ++ @typeName(RhsT),
|
||||||
@ -40,7 +40,7 @@ pub fn rhsScalarType(comptime BaseT: type, comptime RhsT: type) type {
|
|||||||
/// Convert `rhs` to its normalised Scalar form (see `rhsScalarType`).
|
/// Convert `rhs` to its normalised Scalar form (see `rhsScalarType`).
|
||||||
pub inline fn toRhsScalar(comptime BaseT: type, rhs: anytype) rhsScalarType(BaseT, @TypeOf(rhs)) {
|
pub inline fn toRhsScalar(comptime BaseT: type, rhs: anytype) rhsScalarType(BaseT, @TypeOf(rhs)) {
|
||||||
if (comptime isScalarType(@TypeOf(rhs))) return rhs;
|
if (comptime isScalarType(@TypeOf(rhs))) return rhs;
|
||||||
const DimLess = Scalar_(BaseT, Dimensions.init(.{}), Scales.init(.{}));
|
const DimLess = Scalar(BaseT, .{}, .{});
|
||||||
return DimLess{ .value = @as(BaseT, rhs) };
|
return DimLess{ .value = @as(BaseT, rhs) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,11 +49,9 @@ pub inline fn toRhsScalar(comptime BaseT: type, rhs: anytype) rhsScalarType(Base
|
|||||||
/// A dimensioned scalar value. `T` is the numeric type, `d` the dimension exponents, `s` the SI scales.
|
/// A dimensioned scalar value. `T` is the numeric type, `d` the dimension exponents, `s` the SI scales.
|
||||||
/// All dimension and unit tracking is resolved at comptime — zero runtime overhead.
|
/// All dimension and unit tracking is resolved at comptime — zero runtime overhead.
|
||||||
pub fn Scalar(comptime T: type, comptime d_opt: Dimensions.ArgOpts, comptime s_opt: Scales.ArgOpts) type {
|
pub fn Scalar(comptime T: type, comptime d_opt: Dimensions.ArgOpts, comptime s_opt: Scales.ArgOpts) type {
|
||||||
return Scalar_(T, Dimensions.init(d_opt), Scales.init(s_opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) type {
|
|
||||||
@setEvalBranchQuota(10_000_000);
|
@setEvalBranchQuota(10_000_000);
|
||||||
|
const d = Dimensions.init(d_opt);
|
||||||
|
const s = Scales.init(s_opt);
|
||||||
return struct {
|
return struct {
|
||||||
value: T,
|
value: T,
|
||||||
|
|
||||||
@ -93,10 +91,10 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
/// Scales are auto-resolved to the finer of the two.
|
/// Scales are auto-resolved to the finer of the two.
|
||||||
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`
|
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`
|
||||||
/// (bare numbers are treated as dimensionless).
|
/// (bare numbers are treated as dimensionless).
|
||||||
pub inline fn add(self: Self, r: anytype) Scalar_(
|
pub inline fn add(self: Self, r: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims.argsOpt(),
|
||||||
hlp.finerScales(Self, RhsT(@TypeOf(r))),
|
hlp.finerScales(Self, RhsT(@TypeOf(r))).argsOpt(),
|
||||||
) {
|
) {
|
||||||
const rhs_s = rhs(r);
|
const rhs_s = rhs(r);
|
||||||
const RhsType = @TypeOf(rhs_s);
|
const RhsType = @TypeOf(rhs_s);
|
||||||
@ -105,7 +103,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return .{ .value = self.value + rhs_s.value };
|
return .{ .value = self.value + rhs_s.value };
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return .{ .value = lhs_val + rhs_val };
|
return .{ .value = lhs_val + rhs_val };
|
||||||
@ -114,10 +112,10 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
/// Subtract two quantities. Dimensions must match — compile error otherwise.
|
/// Subtract two quantities. Dimensions must match — compile error otherwise.
|
||||||
/// Scales are auto-resolved to the finer of the two.
|
/// Scales are auto-resolved to the finer of the two.
|
||||||
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`.
|
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`.
|
||||||
pub inline fn sub(self: Self, r: anytype) Scalar_(
|
pub inline fn sub(self: Self, r: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims.argsOpt(),
|
||||||
hlp.finerScales(Self, RhsT(@TypeOf(r))),
|
hlp.finerScales(Self, RhsT(@TypeOf(r))).argsOpt(),
|
||||||
) {
|
) {
|
||||||
const rhs_s = rhs(r);
|
const rhs_s = rhs(r);
|
||||||
const RhsType = @TypeOf(rhs_s);
|
const RhsType = @TypeOf(rhs_s);
|
||||||
@ -126,7 +124,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return .{ .value = self.value - rhs_s.value };
|
return .{ .value = self.value - rhs_s.value };
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return .{ .value = lhs_val - rhs_val };
|
return .{ .value = lhs_val - rhs_val };
|
||||||
@ -135,15 +133,15 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
/// Multiply two quantities. Dimension exponents are summed: `L¹ * T⁻¹ → L¹T⁻¹`.
|
/// Multiply two quantities. Dimension exponents are summed: `L¹ * T⁻¹ → L¹T⁻¹`.
|
||||||
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`
|
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`
|
||||||
/// (bare numbers are treated as dimensionless — dimensions pass through unchanged).
|
/// (bare numbers are treated as dimensionless — dimensions pass through unchanged).
|
||||||
pub inline fn mulBy(self: Self, r: anytype) Scalar_(
|
pub inline fn mulBy(self: Self, r: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(RhsT(@TypeOf(r)).dims),
|
dims.add(RhsT(@TypeOf(r)).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, RhsT(@TypeOf(r))),
|
hlp.finerScales(Self, RhsT(@TypeOf(r))).argsOpt(),
|
||||||
) {
|
) {
|
||||||
const rhs_s = rhs(r);
|
const rhs_s = rhs(r);
|
||||||
const RhsType = @TypeOf(rhs_s);
|
const RhsType = @TypeOf(rhs_s);
|
||||||
const SelfNorm = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const SelfNorm = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const RhsNorm = Scalar_(T, RhsType.dims, hlp.finerScales(Self, RhsType));
|
const RhsNorm = Scalar(T, RhsType.dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
if (comptime Self == SelfNorm and RhsType == RhsNorm)
|
if (comptime Self == SelfNorm and RhsType == RhsNorm)
|
||||||
return .{ .value = self.value * rhs_s.value };
|
return .{ .value = self.value * rhs_s.value };
|
||||||
|
|
||||||
@ -155,15 +153,15 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
/// Divide two quantities. Dimension exponents are subtracted: `L¹ / T¹ → L¹T⁻¹`.
|
/// Divide two quantities. Dimension exponents are subtracted: `L¹ / T¹ → L¹T⁻¹`.
|
||||||
/// Integer types use truncating division.
|
/// Integer types use truncating division.
|
||||||
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`.
|
/// `rhs` may be a Scalar, `T`, `comptime_int`, or `comptime_float`.
|
||||||
pub inline fn divBy(self: Self, r: anytype) Scalar_(
|
pub inline fn divBy(self: Self, r: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.sub(RhsT(@TypeOf(r)).dims),
|
dims.sub(RhsT(@TypeOf(r)).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, RhsT(@TypeOf(r))),
|
hlp.finerScales(Self, RhsT(@TypeOf(r))).argsOpt(),
|
||||||
) {
|
) {
|
||||||
const rhs_s = rhs(r);
|
const rhs_s = rhs(r);
|
||||||
const RhsType = @TypeOf(rhs_s);
|
const RhsType = @TypeOf(rhs_s);
|
||||||
const SelfNorm = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const SelfNorm = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const RhsNorm = Scalar_(T, RhsType.dims, hlp.finerScales(Self, RhsType));
|
const RhsNorm = Scalar(T, RhsType.dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == SelfNorm) self.value else self.to(SelfNorm).value;
|
const lhs_val = if (comptime Self == SelfNorm) self.value else self.to(SelfNorm).value;
|
||||||
const rhs_val = if (comptime RhsType == RhsNorm) rhs_s.value else rhs_s.to(RhsNorm).value;
|
const rhs_val = if (comptime RhsType == RhsNorm) rhs_s.value else rhs_s.to(RhsNorm).value;
|
||||||
if (comptime @typeInfo(T) == .int) {
|
if (comptime @typeInfo(T) == .int) {
|
||||||
@ -188,10 +186,10 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
|
|
||||||
/// Raises the quantity to a compile-time integer exponent.
|
/// Raises the quantity to a compile-time integer exponent.
|
||||||
/// Dimension exponents are multiplied by the exponent: `(L²)³ → L⁶`.
|
/// Dimension exponents are multiplied by the exponent: `(L²)³ → L⁶`.
|
||||||
pub inline fn pow(self: Self, comptime exp: comptime_int) Scalar_(
|
pub inline fn pow(self: Self, comptime exp: comptime_int) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.scale(exp),
|
dims.scale(exp).argsOpt(),
|
||||||
s,
|
scales.argsOpt(),
|
||||||
) {
|
) {
|
||||||
if (comptime @typeInfo(T) == .int)
|
if (comptime @typeInfo(T) == .int)
|
||||||
return .{ .value = std.math.powi(T, self.value, exp) catch @panic("Integer overflow in pow") }
|
return .{ .value = std.math.powi(T, self.value, exp) catch @panic("Integer overflow in pow") }
|
||||||
@ -199,10 +197,10 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
return .{ .value = std.math.pow(T, self.value, @as(T, @floatFromInt(exp))) };
|
return .{ .value = std.math.pow(T, self.value, @as(T, @floatFromInt(exp))) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn sqrt(self: Self) Scalar_(
|
pub inline fn sqrt(self: Self) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.div(2),
|
dims.div(2).argsOpt(),
|
||||||
s,
|
scales.argsOpt(),
|
||||||
) {
|
) {
|
||||||
if (comptime !dims.isSquare()) // Check if all exponents are divisible by 2
|
if (comptime !dims.isSquare()) // Check if all exponents are divisible by 2
|
||||||
@compileError("Cannot take sqrt of " ++ dims.str() ++ ": exponents must be even.");
|
@compileError("Cannot take sqrt of " ++ dims.str() ++ ": exponents must be even.");
|
||||||
@ -279,7 +277,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value == rhs_s.value;
|
return self.value == rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val == rhs_val;
|
return lhs_val == rhs_val;
|
||||||
@ -296,7 +294,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value != rhs_s.value;
|
return self.value != rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val != rhs_val;
|
return lhs_val != rhs_val;
|
||||||
@ -313,7 +311,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value > rhs_s.value;
|
return self.value > rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val > rhs_val;
|
return lhs_val > rhs_val;
|
||||||
@ -330,7 +328,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value >= rhs_s.value;
|
return self.value >= rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val >= rhs_val;
|
return lhs_val >= rhs_val;
|
||||||
@ -347,7 +345,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value < rhs_s.value;
|
return self.value < rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val < rhs_val;
|
return lhs_val < rhs_val;
|
||||||
@ -364,7 +362,7 @@ pub fn Scalar_(comptime T: type, comptime d: Dimensions, comptime s: Scales) typ
|
|||||||
if (comptime RhsType == Self)
|
if (comptime RhsType == Self)
|
||||||
return self.value <= rhs_s.value;
|
return self.value <= rhs_s.value;
|
||||||
|
|
||||||
const TargetType = Scalar_(T, dims, hlp.finerScales(Self, RhsType));
|
const TargetType = Scalar(T, dims.argsOpt(), hlp.finerScales(Self, RhsType).argsOpt());
|
||||||
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
const lhs_val = if (comptime Self == TargetType) self.value else self.to(TargetType).value;
|
||||||
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
const rhs_val = if (comptime RhsType == TargetType) rhs_s.value else rhs_s.to(TargetType).value;
|
||||||
return lhs_val <= rhs_val;
|
return lhs_val <= rhs_val;
|
||||||
|
|||||||
@ -69,14 +69,14 @@ pub const UnitScale = enum(isize) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Maps each SI base dimension to its `UnitScale`. Stored and resolved entirely at comptime.
|
/// Maps each SI base dimension to its `UnitScale`. Stored and resolved entirely at comptime.
|
||||||
const Scales = @This();
|
const Self = @This();
|
||||||
|
|
||||||
data: std.EnumArray(Dimension, UnitScale),
|
data: std.EnumArray(Dimension, UnitScale),
|
||||||
|
|
||||||
/// Create a `Scales` from a struct literal, e.g. `.{ .L = .k, .T = .hour }`.
|
/// Create a `Scales` from a struct literal, e.g. `.{ .L = .k, .T = .hour }`.
|
||||||
/// Unspecified dimensions default to `.none` (factor 1).
|
/// Unspecified dimensions default to `.none` (factor 1).
|
||||||
pub fn init(comptime init_val: ArgOpts) Scales {
|
pub fn init(comptime init_val: ArgOpts) Self {
|
||||||
comptime var s = Scales{ .data = std.EnumArray(Dimension, UnitScale).initFill(.none) };
|
comptime var s = Self{ .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)))
|
||||||
@ -86,21 +86,28 @@ pub fn init(comptime init_val: ArgOpts) Scales {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initFill(comptime val: UnitScale) Scales {
|
pub fn initFill(comptime val: UnitScale) Self {
|
||||||
return comptime .{ .data = std.EnumArray(Dimension, UnitScale).initFill(val) };
|
return comptime .{ .data = std.EnumArray(Dimension, UnitScale).initFill(val) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(comptime self: Scales, comptime key: Dimension) UnitScale {
|
pub fn get(comptime self: Self, comptime key: Dimension) UnitScale {
|
||||||
return comptime self.data.get(key);
|
return comptime self.data.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(comptime self: *Scales, comptime key: Dimension, comptime val: UnitScale) void {
|
pub fn set(comptime self: *Self, comptime key: Dimension, comptime val: UnitScale) void {
|
||||||
comptime self.data.set(key, val);
|
comptime self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn argsOpt(self: Self) ArgOpts {
|
||||||
|
var args: ArgOpts = undefined;
|
||||||
|
inline for (std.enums.values(Dimension)) |d|
|
||||||
|
@field(args, @tagName(d)) = self.get(d);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute the combined scale factor for a given dimension signature.
|
/// Compute the combined scale factor for a given dimension signature.
|
||||||
/// Each dimension's prefix is raised to its exponent and multiplied together.
|
/// Each dimension's prefix is raised to its exponent and multiplied together.
|
||||||
pub inline fn getFactor(comptime s: Scales, comptime d: Dimensions) comptime_float {
|
pub inline fn getFactor(comptime s: Self, comptime d: Dimensions) comptime_float {
|
||||||
var factor: f64 = 1.0;
|
var factor: f64 = 1.0;
|
||||||
for (std.enums.values(Dimension)) |dim| {
|
for (std.enums.values(Dimension)) |dim| {
|
||||||
const power = comptime d.get(dim);
|
const power = comptime d.get(dim);
|
||||||
|
|||||||
106
src/Vector.zig
106
src/Vector.zig
@ -2,7 +2,6 @@ const std = @import("std");
|
|||||||
const hlp = @import("helper.zig");
|
const hlp = @import("helper.zig");
|
||||||
|
|
||||||
const Scalar = @import("Scalar.zig").Scalar;
|
const Scalar = @import("Scalar.zig").Scalar;
|
||||||
const Scalar_ = @import("Scalar.zig").Scalar_;
|
|
||||||
const Scales = @import("Scales.zig");
|
const Scales = @import("Scales.zig");
|
||||||
const UnitScale = Scales.UnitScale;
|
const UnitScale = Scales.UnitScale;
|
||||||
const Dimensions = @import("Dimensions.zig");
|
const Dimensions = @import("Dimensions.zig");
|
||||||
@ -33,13 +32,17 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Element-wise addition. Dimensions must match; scales resolve to the finer of the two.
|
/// Element-wise addition. Dimensions must match; scales resolve to the finer of the two.
|
||||||
pub inline fn add(self: Self, rhs: anytype) Vector(len, Scalar_(
|
pub inline fn add(self: Self, rhs: anytype) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims.argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
var res: Vector(len, Scalar_(T, d, hlp.finerScales(Self, @TypeOf(rhs)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
dims.argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = (Q{ .value = v }).add(Tr.ScalarType{ .value = rhs.data[i] });
|
const q = (Q{ .value = v }).add(Tr.ScalarType{ .value = rhs.data[i] });
|
||||||
res.data[i] = q.value;
|
res.data[i] = q.value;
|
||||||
@ -47,13 +50,17 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
/// Element-wise subtraction. Dimensions must match; scales resolve to the finer of the two.
|
/// Element-wise subtraction. Dimensions must match; scales resolve to the finer of the two.
|
||||||
pub inline fn sub(self: Self, rhs: anytype) Vector(len, Scalar_(
|
pub inline fn sub(self: Self, rhs: anytype) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims.argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
var res: Vector(len, Scalar_(T, d, hlp.finerScales(Self, @TypeOf(rhs)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
dims.argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = (Q{ .value = v }).sub(Tr.ScalarType{ .value = rhs.data[i] });
|
const q = (Q{ .value = v }).sub(Tr.ScalarType{ .value = rhs.data[i] });
|
||||||
res.data[i] = q.value;
|
res.data[i] = q.value;
|
||||||
@ -65,13 +72,17 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
pub inline fn divBy(
|
pub inline fn divBy(
|
||||||
self: Self,
|
self: Self,
|
||||||
rhs: anytype,
|
rhs: anytype,
|
||||||
) Vector(len, Scalar_(
|
) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims.sub(@TypeOf(rhs).dims),
|
dims.sub(@TypeOf(rhs).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
var res: Vector(len, Scalar_(T, d.sub(Tr.dims), hlp.finerScales(Self, @TypeOf(rhs)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
d.sub(Tr.dims).argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = (Q{ .value = v }).divBy(Tr.ScalarType{ .value = rhs.data[i] });
|
const q = (Q{ .value = v }).divBy(Tr.ScalarType{ .value = rhs.data[i] });
|
||||||
res.data[i] = q.value;
|
res.data[i] = q.value;
|
||||||
@ -83,13 +94,17 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
pub inline fn mulBy(
|
pub inline fn mulBy(
|
||||||
self: Self,
|
self: Self,
|
||||||
rhs: anytype,
|
rhs: anytype,
|
||||||
) Vector(len, Scalar_(
|
) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(@TypeOf(rhs).dims),
|
dims.add(@TypeOf(rhs).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
var res: Vector(len, Scalar_(T, d.add(Tr.dims), hlp.finerScales(Self, @TypeOf(rhs)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
dims.add(Tr.dims).argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = (Q{ .value = v }).mulBy(Tr.ScalarType{ .value = rhs.data[i] });
|
const q = (Q{ .value = v }).mulBy(Tr.ScalarType{ .value = rhs.data[i] });
|
||||||
res.data[i] = q.value;
|
res.data[i] = q.value;
|
||||||
@ -101,12 +116,16 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
pub inline fn divByScalar(
|
pub inline fn divByScalar(
|
||||||
self: Self,
|
self: Self,
|
||||||
scalar: anytype,
|
scalar: anytype,
|
||||||
) Vector(len, Scalar_(
|
) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims.sub(@TypeOf(scalar).dims),
|
dims.sub(@TypeOf(scalar).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(scalar)),
|
hlp.finerScales(Self, @TypeOf(scalar)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
var res: Vector(len, Scalar_(T, d.sub(@TypeOf(scalar).dims), hlp.finerScales(Self, @TypeOf(scalar)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
dims.sub(@TypeOf(scalar).dims).argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(scalar)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = Q{ .value = v };
|
const q = Q{ .value = v };
|
||||||
res.data[i] = q.divBy(scalar).value;
|
res.data[i] = q.divBy(scalar).value;
|
||||||
@ -118,12 +137,16 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
pub inline fn mulByScalar(
|
pub inline fn mulByScalar(
|
||||||
self: Self,
|
self: Self,
|
||||||
scalar: anytype,
|
scalar: anytype,
|
||||||
) Vector(len, Scalar_(
|
) Vector(len, Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(@TypeOf(scalar).dims),
|
dims.add(@TypeOf(scalar).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(scalar)),
|
hlp.finerScales(Self, @TypeOf(scalar)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
var res: Vector(len, Scalar_(T, d.add(@TypeOf(scalar).dims), hlp.finerScales(Self, @TypeOf(scalar)))) = undefined;
|
var res: Vector(len, Scalar(
|
||||||
|
T,
|
||||||
|
dims.add(@TypeOf(scalar).dims).argsOpt(),
|
||||||
|
hlp.finerScales(Self, @TypeOf(scalar)).argsOpt(),
|
||||||
|
)) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = Q{ .value = v };
|
const q = Q{ .value = v };
|
||||||
res.data[i] = q.mulBy(scalar).value;
|
res.data[i] = q.mulBy(scalar).value;
|
||||||
@ -133,10 +156,10 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
|
|
||||||
/// Standard dot product. Dimensions are summed (e.g., Force * Distance = Energy).
|
/// Standard dot product. Dimensions are summed (e.g., Force * Distance = Energy).
|
||||||
/// Returns a Scalar type with the combined dimensions and finest scale.
|
/// Returns a Scalar type with the combined dimensions and finest scale.
|
||||||
pub inline fn dot(self: Self, rhs: anytype) Scalar_(
|
pub inline fn dot(self: Self, rhs: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(@TypeOf(rhs).dims),
|
dims.add(@TypeOf(rhs).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
) {
|
) {
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
|
|
||||||
@ -151,16 +174,16 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
|
|
||||||
/// 3D Cross product. Dimensions are summed.
|
/// 3D Cross product. Dimensions are summed.
|
||||||
/// Only valid for vectors of length 3.
|
/// Only valid for vectors of length 3.
|
||||||
pub inline fn cross(self: Self, rhs: anytype) Vector(3, Scalar_(
|
pub inline fn cross(self: Self, rhs: anytype) Vector(3, Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(@TypeOf(rhs).dims),
|
dims.add(@TypeOf(rhs).dims).argsOpt(),
|
||||||
hlp.finerScales(Self, @TypeOf(rhs)),
|
hlp.finerScales(Self, @TypeOf(rhs)).argsOpt(),
|
||||||
)) {
|
)) {
|
||||||
if (comptime len != 3)
|
if (comptime len != 3)
|
||||||
@compileError("Cross product is only defined for Vector(3, ...)");
|
@compileError("Cross product is only defined for Vector(3, ...)");
|
||||||
|
|
||||||
const Tr = @TypeOf(rhs);
|
const Tr = @TypeOf(rhs);
|
||||||
const ResScalar = Scalar_(T, d.add(Tr.dims), hlp.finerScales(Self, Tr));
|
const ResScalar = Scalar(T, d.add(Tr.dims).argsOpt(), hlp.finerScales(Self, Tr).argsOpt());
|
||||||
const ResVec = Vector(3, ResScalar);
|
const ResVec = Vector(3, ResScalar);
|
||||||
|
|
||||||
// Calculation: [y1*z2 - z1*y2, z1*x2 - x1*z2, x1*y2 - y1*x2]
|
// Calculation: [y1*z2 - z1*y2, z1*x2 - x1*z2, x1*y2 - y1*x2]
|
||||||
@ -203,10 +226,10 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
|
|
||||||
/// Multiplies all components of the vector together.
|
/// Multiplies all components of the vector together.
|
||||||
/// Resulting dimensions are (Original Dims * len).
|
/// Resulting dimensions are (Original Dims * len).
|
||||||
pub inline fn product(self: Self) Scalar_(
|
pub inline fn product(self: Self) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.scale(len),
|
dims.scale(len).argsOpt(),
|
||||||
scales,
|
scales.argsOpt(),
|
||||||
) {
|
) {
|
||||||
var res_val: T = 1;
|
var res_val: T = 1;
|
||||||
inline for (self.data) |v|
|
inline for (self.data) |v|
|
||||||
@ -216,12 +239,15 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
|
|
||||||
/// Raises every component to a compile-time integer power.
|
/// Raises every component to a compile-time integer power.
|
||||||
/// Dimensions are scaled by the exponent.
|
/// Dimensions are scaled by the exponent.
|
||||||
pub inline fn pow(self: Self, comptime exp: comptime_int) Vector(len, Scalar_(
|
pub inline fn pow(self: Self, comptime exp: comptime_int) Vector(
|
||||||
|
len,
|
||||||
|
Scalar(
|
||||||
T,
|
T,
|
||||||
dims.scale(exp),
|
dims.scale(exp).argsOpt(),
|
||||||
scales,
|
scales.argsOpt(),
|
||||||
)) {
|
),
|
||||||
const ResScalar = Scalar_(T, dims.scale(exp), s);
|
) {
|
||||||
|
const ResScalar = Scalar(T, dims.scale(exp).argsOpt(), scales.argsOpt());
|
||||||
var res: Vector(len, ResScalar) = undefined;
|
var res: Vector(len, ResScalar) = undefined;
|
||||||
inline for (self.data, 0..) |v, i| {
|
inline for (self.data, 0..) |v, i| {
|
||||||
const q = Q{ .value = v };
|
const q = Q{ .value = v };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user