Added some doc comments
This commit is contained in:
parent
ec05b60fc3
commit
86841318f2
@ -29,10 +29,16 @@ pub const Dimension = enum {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --------- Dimensions struct ---------
|
||||||
|
|
||||||
|
/// Holds the exponent of each SI base dimension for a given quantity (e.g. velocity = L¹T⁻¹).
|
||||||
|
/// All values are `comptime_int` — no runtime storage.
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
data: std.EnumArray(Dimension, comptime_int),
|
data: std.EnumArray(Dimension, comptime_int),
|
||||||
|
|
||||||
|
/// Create a `Dimensions` from an anonymous struct literal, e.g. `.{ .L = 1, .T = -1 }`.
|
||||||
|
/// Unspecified dimensions default to 0.
|
||||||
pub fn init(comptime init_val: anytype) Self {
|
pub fn init(comptime init_val: anytype) Self {
|
||||||
var s = Self{ .data = std.EnumArray(Dimension, comptime_int).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|
|
||||||
@ -52,6 +58,7 @@ pub fn set(comptime self: *Self, comptime key: Dimension, comptime val: i8) void
|
|||||||
self.data.set(key, val);
|
self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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|
|
for (std.enums.values(Dimension)) |d|
|
||||||
@ -59,6 +66,7 @@ pub fn add(comptime a: Self, comptime b: Self) Self {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Subtract exponents component-wise. Used internally by `divBy`.
|
||||||
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);
|
||||||
@ -67,6 +75,7 @@ pub fn sub(comptime a: Self, comptime b: Self) Self {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if every dimension exponent is equal. Used to enforce type compatibility in `add`, `sub`, `to`.
|
||||||
pub fn eql(comptime a: Self, comptime b: Self) bool {
|
pub fn eql(comptime a: Self, comptime b: Self) bool {
|
||||||
inline 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;
|
||||||
|
|||||||
@ -18,18 +18,29 @@ const Dimension = Dimensions.Dimension;
|
|||||||
// - pow: Scalar power another
|
// - pow: Scalar power another
|
||||||
// - log: Scalar log another
|
// - log: Scalar log another
|
||||||
|
|
||||||
|
/// 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.
|
||||||
pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type {
|
pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type {
|
||||||
@setEvalBranchQuota(10_000_000);
|
@setEvalBranchQuota(10_000_000);
|
||||||
return struct {
|
return struct {
|
||||||
value: T,
|
value: T,
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
/// Type of Vector(3, Self)
|
||||||
pub const Vec3: type = Vector(3, Self);
|
pub const Vec3: type = Vector(3, Self);
|
||||||
|
|
||||||
|
/// Type of underline value, mostly use for Vector
|
||||||
pub const ValueType: type = T;
|
pub const ValueType: type = T;
|
||||||
|
|
||||||
|
/// Dimensions of this type
|
||||||
pub const dims: Dimensions = d;
|
pub const dims: Dimensions = d;
|
||||||
|
|
||||||
|
/// Scales of this type
|
||||||
pub const scales = s;
|
pub const scales = s;
|
||||||
|
|
||||||
|
/// Add two quantities. Dimensions must match — compile error otherwise.
|
||||||
|
/// Scales are auto-resolved to the finer of the two.
|
||||||
pub inline fn add(self: Self, rhs: anytype) Scalar(
|
pub inline fn add(self: Self, rhs: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims,
|
||||||
@ -47,6 +58,8 @@ pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type
|
|||||||
return .{ .value = lhs_val + rhs_val };
|
return .{ .value = lhs_val + rhs_val };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Subtract two quantities. Dimensions must match — compile error otherwise.
|
||||||
|
/// Scales are auto-resolved to the finer of the two.
|
||||||
pub inline fn sub(self: Self, rhs: anytype) Scalar(
|
pub inline fn sub(self: Self, rhs: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims,
|
dims,
|
||||||
@ -64,6 +77,7 @@ pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type
|
|||||||
return .{ .value = lhs_val - rhs_val };
|
return .{ .value = lhs_val - rhs_val };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multiply two quantities. Dimension exponents are summed: `L¹ * T⁻¹ → L¹T⁻¹`.
|
||||||
pub inline fn mulBy(self: Self, rhs: anytype) Scalar(
|
pub inline fn mulBy(self: Self, rhs: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.add(@TypeOf(rhs).dims),
|
dims.add(@TypeOf(rhs).dims),
|
||||||
@ -80,6 +94,8 @@ pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type
|
|||||||
return .{ .value = lhs_val * rhs_val };
|
return .{ .value = lhs_val * rhs_val };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Divide two quantities. Dimension exponents are subtracted: `L¹ / T¹ → L¹T⁻¹`.
|
||||||
|
/// Integer types use truncating division.
|
||||||
pub inline fn divBy(self: Self, rhs: anytype) Scalar(
|
pub inline fn divBy(self: Self, rhs: anytype) Scalar(
|
||||||
T,
|
T,
|
||||||
dims.sub(@TypeOf(rhs).dims),
|
dims.sub(@TypeOf(rhs).dims),
|
||||||
@ -97,6 +113,8 @@ pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert to a compatible unit type. The scale ratio is computed at comptime.
|
||||||
|
/// Compile error if dimensions don't match.
|
||||||
pub inline fn to(self: Self, comptime Dest: type) Dest {
|
pub inline fn to(self: Self, comptime Dest: type) Dest {
|
||||||
if (comptime !dims.eql(Dest.dims))
|
if (comptime !dims.eql(Dest.dims))
|
||||||
@compileError("Dimension mismatch in to: " ++ dims.str() ++ " vs " ++ Dest.dims.str());
|
@compileError("Dimension mismatch in to: " ++ dims.str() ++ " vs " ++ Dest.dims.str());
|
||||||
@ -138,10 +156,17 @@ pub fn Scalar(comptime T: type, comptime d: Dimensions, comptime s: Scales) type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Vec(self: Self, comptime len: comptime_int) Vector(len, Self) {
|
/// Return a `Vector(len, Self)` type.
|
||||||
|
pub fn Vec(_: Self, comptime len: comptime_int) type {
|
||||||
|
return Vector(len, Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a `Vector(len, Self)` with all components set to this value.
|
||||||
|
pub fn vec(self: Self, comptime len: comptime_int) Vector(len, Self) {
|
||||||
return Vector(len, Self).initDefault(self.value);
|
return Vector(len, Self).initDefault(self.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shorthand for `Vec(3)` — wrap this value into a 3-component vector.
|
||||||
pub fn vec3(self: Self) Vec3 {
|
pub fn vec3(self: Self) Vec3 {
|
||||||
return Vec3.initDefault(self.value);
|
return Vec3.initDefault(self.value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,9 @@ const hlp = @import("helper.zig");
|
|||||||
const Dimensions = @import("Dimensions.zig");
|
const Dimensions = @import("Dimensions.zig");
|
||||||
const Dimension = @import("Dimensions.zig").Dimension;
|
const Dimension = @import("Dimensions.zig").Dimension;
|
||||||
|
|
||||||
|
/// SI prefix (pico…peta) plus time-unit aliases (min, hour, year).
|
||||||
|
/// The integer value encodes the exponent for SI prefixes (e.g. `k = 3` → 10³),
|
||||||
|
/// and the literal factor for time units (e.g. `hour = 3600`).
|
||||||
pub const UnitScale = enum(isize) {
|
pub const UnitScale = enum(isize) {
|
||||||
P = 15,
|
P = 15,
|
||||||
T = 12,
|
T = 12,
|
||||||
@ -54,10 +57,13 @@ pub const UnitScale = enum(isize) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Maps each SI base dimension to its `UnitScale`. Stored and resolved entirely at comptime.
|
||||||
const Scales = @This();
|
const Scales = @This();
|
||||||
|
|
||||||
data: std.EnumArray(Dimension, UnitScale),
|
data: std.EnumArray(Dimension, UnitScale),
|
||||||
|
|
||||||
|
/// Create a `Scales` from an anonymous struct literal, e.g. `.{ .L = .k, .T = .hour }`.
|
||||||
|
/// Unspecified dimensions default to `.none` (factor 1).
|
||||||
pub fn init(comptime init_val: anytype) Scales {
|
pub fn init(comptime init_val: anytype) Scales {
|
||||||
comptime 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| {
|
||||||
@ -81,6 +87,8 @@ pub fn set(comptime self: *Scales, comptime key: Dimension, comptime val: UnitSc
|
|||||||
comptime self.data.set(key, val);
|
comptime self.data.set(key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute the combined scale factor for a given dimension signature.
|
||||||
|
/// 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: Scales, comptime d: Dimensions) comptime_float {
|
||||||
comptime var factor: f64 = 1.0;
|
comptime var factor: f64 = 1.0;
|
||||||
inline for (std.enums.values(Dimension)) |dim| {
|
inline for (std.enums.values(Dimension)) |dim| {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ const UnitScale = Scales.UnitScale;
|
|||||||
const Dimensions = @import("Dimensions.zig");
|
const Dimensions = @import("Dimensions.zig");
|
||||||
const Dimension = Dimensions.Dimension;
|
const Dimension = Dimensions.Dimension;
|
||||||
|
|
||||||
|
/// A fixed-size array of `len` elements sharing the same dimension and scale as scalar type `Q`.
|
||||||
pub fn Vector(comptime len: usize, comptime Q: type) type {
|
pub fn Vector(comptime len: usize, comptime Q: type) type {
|
||||||
const T = Q.ValueType;
|
const T = Q.ValueType;
|
||||||
const d: Dimensions = Q.dims;
|
const d: Dimensions = Q.dims;
|
||||||
@ -30,6 +31,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return .{ .data = data };
|
return .{ .data = data };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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,
|
||||||
@ -43,7 +45,7 @@ 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.
|
||||||
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,
|
||||||
@ -58,6 +60,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Element-wise division. Dimension exponents are subtracted per component.
|
||||||
pub inline fn divBy(
|
pub inline fn divBy(
|
||||||
self: Self,
|
self: Self,
|
||||||
rhs: anytype,
|
rhs: anytype,
|
||||||
@ -75,6 +78,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Element-wise multiplication. Dimension exponents are summed per component.
|
||||||
pub inline fn mulBy(
|
pub inline fn mulBy(
|
||||||
self: Self,
|
self: Self,
|
||||||
rhs: anytype,
|
rhs: anytype,
|
||||||
@ -92,6 +96,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Divide every component by a single scalar. Dimensions are subtracted (e.g. position / time → velocity).
|
||||||
pub inline fn divByScalar(
|
pub inline fn divByScalar(
|
||||||
self: Self,
|
self: Self,
|
||||||
scalar: anytype,
|
scalar: anytype,
|
||||||
@ -108,6 +113,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multiply every component by a single scalar. Dimensions are summed.
|
||||||
pub inline fn mulByScalar(
|
pub inline fn mulByScalar(
|
||||||
self: Self,
|
self: Self,
|
||||||
scalar: anytype,
|
scalar: anytype,
|
||||||
@ -124,6 +130,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Negate all components. Dimensions are preserved.
|
||||||
pub fn negate(self: Self) Self {
|
pub fn negate(self: Self) Self {
|
||||||
var res: Self = undefined;
|
var res: Self = undefined;
|
||||||
inline for (self.data, 0..) |v, i|
|
inline for (self.data, 0..) |v, i|
|
||||||
@ -131,6 +138,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert all components to a compatible scalar type. Compile error on dimension mismatch.
|
||||||
pub inline fn to(self: Self, comptime DestQ: type) Vector(len, DestQ) {
|
pub inline fn to(self: Self, comptime DestQ: type) Vector(len, DestQ) {
|
||||||
var res: Vector(len, DestQ) = undefined;
|
var res: Vector(len, DestQ) = undefined;
|
||||||
inline for (self.data, 0..) |v, i|
|
inline for (self.data, 0..) |v, i|
|
||||||
@ -138,6 +146,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sum of squared components. Cheaper than `length` — use for comparisons.
|
||||||
pub inline fn lengthSqr(self: Self) T {
|
pub inline fn lengthSqr(self: Self) T {
|
||||||
var sum: T = 0;
|
var sum: T = 0;
|
||||||
inline for (self.data) |v|
|
inline for (self.data) |v|
|
||||||
@ -145,6 +154,7 @@ pub fn Vector(comptime len: usize, comptime Q: type) type {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Euclidean length. Integer types use integer sqrt (truncated).
|
||||||
pub inline fn length(self: Self) T {
|
pub inline fn length(self: Self) T {
|
||||||
const len_sq = self.lengthSqr();
|
const len_sq = self.lengthSqr();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user