zig-dimal/src/Base.zig
adrien 5f833a5e58 Removed TensorAlloc and made TensorStatic back to just Tensor
Realized I can just do alloc.create instead of a all new struct
2026-05-15 00:46:22 +02:00

261 lines
11 KiB
Zig

const std = @import("std");
// Adjust these imports to match your actual file names
const Dimensions = @import("Dimensions.zig");
const Scales = @import("Scales.zig");
const Tensor = @import("Tensor.zig").Tensor;
fn PhysicalConstant(comptime d: Dimensions.ArgOpts, comptime val: f64, comptime s: Scales.ArgOpts) type {
return struct {
pub const dims = Dimensions.init(d);
pub const scales = Scales.init(s);
/// Instantiates the constant into a specific numeric type.
pub fn Of(comptime T: type) Tensor(T, d, s, &.{1}) {
const casted_val: T = switch (@typeInfo(T)) {
.float => @floatCast(val),
.int => @intFromFloat(val),
else => @compileError("Unsupported type for PhysicalConstant"),
};
return Tensor(T, d, s, &.{1}).splat(casted_val);
}
};
}
fn BaseScalar(comptime d: Dimensions.ArgOpts) type {
return struct {
pub const dims = Dimensions.init(d);
/// Creates a Scalar of this dimension using default scales.
/// Example: const V = Quantities.Velocity.Of(f32);
pub fn Of(comptime T: type) type {
return Tensor(T, d, .{}, &.{1});
}
/// Creates a Scalar of this dimension using custom scales.
/// Example: const Kmh = Quantities.Velocity.Scaled(f32, .{ .L = .k, .T = .hour });
pub fn Scaled(comptime T: type, comptime s: Scales.ArgOpts) type {
return Tensor(T, d, s, &.{1});
}
};
}
// ==========================================
// Physical Constants
// ==========================================
pub const Constants = struct {
/// Speed of light in vacuum (c) [m/s]
pub const SpeedOfLight = PhysicalConstant(.{ .L = 1, .T = -1 }, 299792458.0, .{});
/// Planck constant (h) [J⋅s = kg⋅m²⋅s⁻¹]
pub const Planck = PhysicalConstant(.{ .M = 1, .L = 2, .T = -1 }, 6.62607015e-34, .{ .M = .k });
/// Reduced Planck constant (ℏ) [J⋅s]
pub const ReducedPlanck = PhysicalConstant(.{ .M = 1, .L = 2, .T = -1 }, 1.054571817e-34, .{ .M = .k });
/// Boltzmann constant (k_B) [J⋅K⁻¹ = kg⋅m²⋅s⁻²⋅K⁻¹]
pub const Boltzmann = PhysicalConstant(.{ .M = 1, .L = 2, .T = -2, .Tp = -1 }, 1.380649e-23, .{ .M = .k });
/// Newtonian constant of gravitation (G) [m³⋅kg⁻¹⋅s⁻²]
pub const Gravitational = PhysicalConstant(.{ .M = -1, .L = 3, .T = -2 }, 6.67430e-11, .{ .M = .k });
/// Stefan-Boltzmann constant () [W⋅m⁻²⋅K⁻⁴ = kg⋅s⁻³⋅K⁻⁴]
pub const StefanBoltzmann = PhysicalConstant(.{ .M = 1, .T = -3, .Tp = -4 }, 5.670374419e-8, .{ .M = .k });
/// Elementary charge (e) [C = A⋅s]
pub const ElementaryCharge = PhysicalConstant(.{ .T = 1, .I = 1 }, 1.602176634e-19, .{});
/// Vacuum magnetic permeability (μ_0) [N⋅A⁻² = kg⋅m⋅s⁻²⋅A⁻²]
pub const VacuumPermeability = PhysicalConstant(.{ .M = 1, .L = 1, .T = -2, .I = -2 }, 1.25663706127e-6, .{ .M = .k });
/// Vacuum electric permittivity (ε_0) [F⋅m⁻¹ = A²⋅s⁴⋅kg⁻¹⋅m⁻³]
pub const VacuumPermittivity = PhysicalConstant(.{ .M = -1, .L = -3, .T = 4, .I = 2 }, 8.8541878188e-12, .{ .M = .k });
/// Electron mass (m_e) [kg]
pub const ElectronMass = PhysicalConstant(.{ .M = 1 }, 9.1093837139e-31, .{ .M = .k });
/// Proton mass (m_p) [kg]
pub const ProtonMass = PhysicalConstant(.{ .M = 1 }, 1.67262192595e-27, .{ .M = .k });
/// Neutron mass (m_n) [kg]
pub const NeutronMass = PhysicalConstant(.{ .M = 1 }, 1.67492750056e-27, .{ .M = .k });
/// Fine-structure constant () [Dimensionless]
pub const FineStructure = PhysicalConstant(.{}, 0.0072973525643, .{});
/// Avogadro constant (N_A) [mol⁻¹]
/// Note: Assuming mol is currently treated as dimensionless in the base system,
/// otherwise requires adding an `.N` dimension to Dimensions.ArgOpts.
pub const Avogadro = PhysicalConstant(.{}, 6.02214076e23, .{});
};
// ==========================================
// Base Quantities
// ==========================================
pub const Dimless = BaseScalar(.{});
pub const Meter = BaseScalar(.{ .L = 1 });
pub const Second = BaseScalar(.{ .T = 1 });
pub const Gramm = BaseScalar(.{ .M = 1 });
pub const Kelvin = BaseScalar(.{ .Tr = 1 });
pub const ElectricCurrent = BaseScalar(.{ .I = 1 });
// ==========================================
// Electric
// ==========================================
pub const ElectricConductivity = BaseScalar(.{ .M = -1, .L = -3, .T = 3, .I = 2 });
pub const ElectricCharge = BaseScalar(.{ .T = 1, .I = 1 });
pub const ElectricPotential = BaseScalar(.{ .T = -3, .L = 2, .M = 1, .I = -1 });
pub const ElectricResistance = BaseScalar(.{ .M = 1, .L = 2, .T = -3, .I = -2 });
pub const ElectricResistivity = BaseScalar(.{ .M = 1, .L = 3, .T = -3, .I = -2 });
pub const ElectricCapacitance = BaseScalar(.{ .T = 4, .L = -2, .M = -1, .I = 2 });
pub const ElectricImpedance = ElectricResistance;
pub const MagneticFlux = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .I = -1 });
pub const MagneticDensity = BaseScalar(.{ .M = 1, .T = -2, .I = -1 });
pub const MagneticStrength = BaseScalar(.{ .L = -1, .I = 1 });
pub const MagneticMoment = BaseScalar(.{ .L = 2, .I = 1 });
// ==========================================
// Movement
// ==========================================
pub const Speed = BaseScalar(.{ .L = 1, .T = -1 });
pub const Acceleration = BaseScalar(.{ .L = 1, .T = -2 });
pub const Inertia = BaseScalar(.{ .M = 1, .L = 2 });
// ==========================================
// Forces / Energy
// ==========================================
pub const Force = BaseScalar(.{ .T = -2, .M = 1, .L = 1 });
pub const Pressure = BaseScalar(.{ .T = -2, .L = -1, .M = 1 });
pub const Energy = BaseScalar(.{ .T = -2, .L = 2, .M = 1 });
pub const Power = BaseScalar(.{ .T = -3, .L = 2, .M = 1 });
// ==========================================
// Dimension
// ==========================================
pub const Area = BaseScalar(.{ .L = 2 });
pub const Volume = BaseScalar(.{ .L = 3 });
pub const AreaDensity = BaseScalar(.{ .M = 1, .L = -2 });
pub const Density = BaseScalar(.{ .M = 1, .L = -3 });
// ==========================================
// Thermal
// ==========================================
pub const ThermalHeat = Energy;
pub const ThermalWork = Energy;
pub const ThermalCapacity = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .Tr = -1 });
pub const ThermalCapacityPerMass = BaseScalar(.{ .L = 2, .T = -2, .Tr = -1 });
pub const ThermalFluxDensity = BaseScalar(.{ .M = 1, .T = -3 });
pub const ThermalConductance = BaseScalar(.{ .M = 1, .L = 2, .T = -3, .Tr = -1 });
pub const ThermalConductivity = BaseScalar(.{ .M = 1, .L = 1, .T = -3, .Tr = -1 });
pub const ThermalResistance = BaseScalar(.{ .M = -1, .L = -2, .T = 3, .Tr = 1 });
pub const ThermalResistivity = BaseScalar(.{ .M = -1, .L = -1, .T = 3, .Tr = 1 });
pub const ThermalEntropy = BaseScalar(.{ .M = 1, .L = 2, .T = -2, .Tr = -1 });
// ==========================================
// Others
// ==========================================
pub const Frequency = BaseScalar(.{ .T = -1 });
pub const Viscosity = BaseScalar(.{ .M = 1, .L = -1, .T = -1 });
pub const SurfaceTension = BaseScalar(.{ .M = 1, .T = -2 });
// ==========================================
// Tests
// ==========================================
test "BaseQuantities - Core dimensions instantiation" {
// Basic types via generic wrappers
const M = Meter.Of(f32);
const distance = M.splat(100);
try std.testing.expectEqual(100.0, distance.data[0]);
try std.testing.expectEqual(1, M.dims.get(.L));
try std.testing.expectEqual(0, M.dims.get(.T));
// Test specific scale variants
const Kmh = Speed.Scaled(f32, .{ .L = .k, .T = .hour });
const speed = Kmh.splat(120);
try std.testing.expectEqual(120.0, speed.data[0]);
try std.testing.expectEqual(.k, @TypeOf(speed).scales.get(.L));
try std.testing.expectEqual(.hour, @TypeOf(speed).scales.get(.T));
}
test "BaseQuantities - Kinematics equations" {
const d = Meter.Of(f32).splat(50.0);
const t = Second.Of(f32).splat(2.0);
// Velocity = Distance / Time
const v = d.div(t);
try std.testing.expectEqual(25.0, v.data[0]);
try comptime std.testing.expect(Speed.dims.eql(@TypeOf(v).dims));
// Acceleration = Velocity / Time
const a = v.div(t);
try std.testing.expectEqual(12.5, a.data[0]);
try comptime std.testing.expect(Acceleration.dims.eql(@TypeOf(a).dims));
}
test "BaseQuantities - Dynamics (Force and Work)" {
// 10 kg
const m = Gramm.Scaled(f32, .{ .M = .k }).splat(10.0);
// 9.8 m/s^2
const a = Acceleration.Of(f32).splat(9.8);
// Force = mass * acceleration
const f = m.mul(a);
try std.testing.expectEqual(98, f.data[0]);
try comptime std.testing.expect(Force.dims.eql(@TypeOf(f).dims));
// Energy (Work) = Force * distance
const distance = Meter.Of(f32).splat(5.0);
const energy = f.mul(distance);
try std.testing.expectEqual(490, energy.data[0]);
try comptime std.testing.expect(Energy.dims.eql(@TypeOf(energy).dims));
}
test "BaseQuantities - Electric combinations" {
const current = ElectricCurrent.Of(f32).splat(2); // 2 A
const time = Second.Of(f32).splat(3.0); // 3 s
// Charge = Current * time
const charge = current.mul(time);
try std.testing.expectEqual(6.0, charge.data[0]);
try comptime std.testing.expect(ElectricCharge.dims.eql(@TypeOf(charge).dims));
}
test "Constants - Initialization and dimension checks" {
// Speed of Light
const c = Constants.SpeedOfLight.Of(f64);
try std.testing.expectEqual(299792458.0, c.data[0]);
try std.testing.expectEqual(1, @TypeOf(c).dims.get(.L));
try std.testing.expectEqual(-1, @TypeOf(c).dims.get(.T));
// Electron Mass (verifying scale as well)
const me = Constants.ElectronMass.Of(f64);
try std.testing.expectEqual(9.1093837139e-31, me.data[0]);
try std.testing.expectEqual(1, @TypeOf(me).dims.get(.M));
try std.testing.expectEqual(.k, @TypeOf(me).scales.get(.M)); // Should be scaled to kg
// Boltzmann Constant (Complex derived dimensions)
const kb = Constants.Boltzmann.Of(f64);
try std.testing.expectEqual(1.380649e-23, kb.data[0]);
try std.testing.expectEqual(1, @TypeOf(kb).dims.get(.M));
try std.testing.expectEqual(2, @TypeOf(kb).dims.get(.L));
try std.testing.expectEqual(-2, @TypeOf(kb).dims.get(.T));
try std.testing.expectEqual(-1, @TypeOf(kb).dims.get(.Tp));
try std.testing.expectEqual(.k, @TypeOf(kb).scales.get(.M));
// Vacuum Permittivity
const eps0 = Constants.VacuumPermittivity.Of(f64);
try std.testing.expectEqual(8.8541878188e-12, eps0.data[0]);
try std.testing.expectEqual(-1, @TypeOf(eps0).dims.get(.M));
try std.testing.expectEqual(-3, @TypeOf(eps0).dims.get(.L));
try std.testing.expectEqual(4, @TypeOf(eps0).dims.get(.T));
try std.testing.expectEqual(2, @TypeOf(eps0).dims.get(.I));
// Fine Structure Constant (Dimensionless)
const alpha = Constants.FineStructure.Of(f64);
try std.testing.expectEqual(0.0072973525643, alpha.data[0]);
try std.testing.expectEqual(0, @TypeOf(alpha).dims.get(.M));
try std.testing.expectEqual(0, @TypeOf(alpha).dims.get(.L));
}