eml-stdlib 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eml_stdlib/__init__.py +81 -0
- eml_stdlib/ballistics/air_density.eml +73 -0
- eml_stdlib/ballistics/ballistic_solver.eml +102 -0
- eml_stdlib/ballistics/coriolis.eml +60 -0
- eml_stdlib/ballistics/drag.eml +44 -0
- eml_stdlib/ballistics/gravity.eml +52 -0
- eml_stdlib/ballistics/muzzle_velocity.eml +42 -0
- eml_stdlib/ballistics/spin_drift.eml +60 -0
- eml_stdlib/ballistics/time_of_flight.eml +79 -0
- eml_stdlib/ballistics/wind.eml +58 -0
- eml_stdlib/biology/abilities/ballistic_armor.eml +61 -0
- eml_stdlib/biology/abilities/bite_force.eml +48 -0
- eml_stdlib/biology/abilities/chromatophore.eml +50 -0
- eml_stdlib/biology/abilities/discharge.eml +45 -0
- eml_stdlib/biology/abilities/elastic_energy.eml +42 -0
- eml_stdlib/biology/abilities/locomotion.eml +50 -0
- eml_stdlib/biology/abilities/muscle_power.eml +47 -0
- eml_stdlib/biology/abilities/sprint.eml +36 -0
- eml_stdlib/biology/abilities/texture_match.eml +49 -0
- eml_stdlib/biology/abilities/toxin.eml +44 -0
- eml_stdlib/biology/cone_l.eml +36 -0
- eml_stdlib/biology/cone_s.eml +32 -0
- eml_stdlib/biology/cryptochrome.eml +44 -0
- eml_stdlib/biology/geomagnetic_field.eml +32 -0
- eml_stdlib/biology/goldman_equation.eml +41 -0
- eml_stdlib/biology/hill_equation.eml +65 -0
- eml_stdlib/biology/hodgkin_huxley.eml +108 -0
- eml_stdlib/biology/michaelis_menten.eml +65 -0
- eml_stdlib/biology/plume_diffusion.eml +47 -0
- eml_stdlib/biology/receptor_binding.eml +35 -0
- eml_stdlib/biology/rod_sensitivity.eml +38 -0
- eml_stdlib/biology/tapetum.eml +70 -0
- eml_stdlib/carriers/acoustic_cloak.eml +56 -0
- eml_stdlib/carriers/ferron_emission.eml +55 -0
- eml_stdlib/carriers/ferron_logic.eml +45 -0
- eml_stdlib/carriers/ferron_propagation.eml +69 -0
- eml_stdlib/carriers/mach_zehnder.eml +52 -0
- eml_stdlib/carriers/magnon_dispersion.eml +57 -0
- eml_stdlib/carriers/magnon_logic.eml +45 -0
- eml_stdlib/carriers/optical_neuron.eml +55 -0
- eml_stdlib/carriers/phonon_bandgap.eml +54 -0
- eml_stdlib/carriers/ring_resonator.eml +48 -0
- eml_stdlib/carriers/spin_torque.eml +61 -0
- eml_stdlib/carriers/thermal_rectifier.eml +63 -0
- eml_stdlib/catalog.json +4209 -0
- eml_stdlib/circuits/buck_converter.eml +74 -0
- eml_stdlib/circuits/cmos_inverter.eml +75 -0
- eml_stdlib/circuits/h_bridge.eml +69 -0
- eml_stdlib/circuits/ldo.eml +66 -0
- eml_stdlib/circuits/mosfet_iv.eml +59 -0
- eml_stdlib/circuits/pll_loop.eml +63 -0
- eml_stdlib/circuits/rc_filter.eml +98 -0
- eml_stdlib/circuits/voltage_divider.eml +68 -0
- eml_stdlib/control/bangbang.eml +34 -0
- eml_stdlib/control/deadband.eml +28 -0
- eml_stdlib/control/hysteresis.eml +28 -0
- eml_stdlib/control/kalman_1d.eml +53 -0
- eml_stdlib/control/lqr_1d.eml +47 -0
- eml_stdlib/control/pid.eml +38 -0
- eml_stdlib/gaming/animation/bounce.eml +39 -0
- eml_stdlib/gaming/animation/ease_in.eml +27 -0
- eml_stdlib/gaming/animation/ease_in_out.eml +29 -0
- eml_stdlib/gaming/animation/ease_out.eml +27 -0
- eml_stdlib/gaming/animation/ik_2bone.eml +57 -0
- eml_stdlib/gaming/animation/spring.eml +39 -0
- eml_stdlib/gaming/audio/distance_attenuation.eml +50 -0
- eml_stdlib/gaming/audio/doppler.eml +39 -0
- eml_stdlib/gaming/audio/lowpass_audio.eml +32 -0
- eml_stdlib/gaming/audio/reverb_delay.eml +41 -0
- eml_stdlib/gaming/camera/dof_blur.eml +30 -0
- eml_stdlib/gaming/camera/fov_projection.eml +47 -0
- eml_stdlib/gaming/camera/orbit.eml +48 -0
- eml_stdlib/gaming/camera/shake.eml +20 -0
- eml_stdlib/gaming/lighting/ambient_occlusion.eml +40 -0
- eml_stdlib/gaming/lighting/area_light.eml +50 -0
- eml_stdlib/gaming/lighting/fog_exp.eml +28 -0
- eml_stdlib/gaming/lighting/fog_exp2.eml +30 -0
- eml_stdlib/gaming/lighting/point_light.eml +33 -0
- eml_stdlib/gaming/lighting/spot_light.eml +43 -0
- eml_stdlib/gaming/noise/fbm.eml +65 -0
- eml_stdlib/gaming/noise/perlin_2d.eml +65 -0
- eml_stdlib/gaming/noise/perlin_3d.eml +63 -0
- eml_stdlib/gaming/noise/simplex_2d.eml +67 -0
- eml_stdlib/gaming/noise/turbulence.eml +46 -0
- eml_stdlib/gaming/noise/value_noise.eml +45 -0
- eml_stdlib/gaming/noise/voronoi_2d.eml +83 -0
- eml_stdlib/gaming/noise/white_noise.eml +47 -0
- eml_stdlib/gaming/noise/worley.eml +79 -0
- eml_stdlib/gaming/particles/drag.eml +30 -0
- eml_stdlib/gaming/particles/emitter_radial.eml +35 -0
- eml_stdlib/gaming/particles/fade.eml +36 -0
- eml_stdlib/gaming/particles/gravity_particle.eml +32 -0
- eml_stdlib/gaming/particles/size_over_life.eml +28 -0
- eml_stdlib/gaming/physics/aabb_overlap.eml +38 -0
- eml_stdlib/gaming/physics/buoyancy.eml +43 -0
- eml_stdlib/gaming/physics/circle_collision.eml +46 -0
- eml_stdlib/gaming/physics/impulse_resolve.eml +39 -0
- eml_stdlib/gaming/physics/rigid_body_2d.eml +61 -0
- eml_stdlib/gaming/physics/spring_damper.eml +30 -0
- eml_stdlib/gaming/physics/verlet.eml +29 -0
- eml_stdlib/gaming/shading/fresnel.eml +57 -0
- eml_stdlib/gaming/shading/matcap.eml +34 -0
- eml_stdlib/gaming/shading/pbr_diffuse.eml +41 -0
- eml_stdlib/gaming/shading/pbr_specular.eml +75 -0
- eml_stdlib/gaming/shading/subsurface.eml +52 -0
- eml_stdlib/gaming/shading/toon.eml +30 -0
- eml_stdlib/gaming/terrain/biome_select.eml +41 -0
- eml_stdlib/gaming/terrain/cliff_detect.eml +35 -0
- eml_stdlib/gaming/terrain/erosion_hydraulic.eml +57 -0
- eml_stdlib/gaming/terrain/erosion_thermal.eml +44 -0
- eml_stdlib/gaming/terrain/heightmap.eml +33 -0
- eml_stdlib/gaming/textures/brick.eml +27 -0
- eml_stdlib/gaming/textures/caustics.eml +25 -0
- eml_stdlib/gaming/textures/checkerboard.eml +27 -0
- eml_stdlib/gaming/textures/fire.eml +26 -0
- eml_stdlib/gaming/textures/marble.eml +24 -0
- eml_stdlib/gaming/textures/rust.eml +23 -0
- eml_stdlib/gaming/textures/water_surface.eml +49 -0
- eml_stdlib/gaming/textures/wood.eml +41 -0
- eml_stdlib/math/abs.eml +45 -0
- eml_stdlib/math/atan.eml +32 -0
- eml_stdlib/math/atan2.eml +61 -0
- eml_stdlib/math/bessel_j0.eml +65 -0
- eml_stdlib/math/cos.eml +42 -0
- eml_stdlib/math/cosh.eml +24 -0
- eml_stdlib/math/erf.eml +66 -0
- eml_stdlib/math/exp.eml +49 -0
- eml_stdlib/math/gamma.eml +55 -0
- eml_stdlib/math/gaussian.eml +18 -0
- eml_stdlib/math/log.eml +59 -0
- eml_stdlib/math/pow.eml +51 -0
- eml_stdlib/math/relu.eml +63 -0
- eml_stdlib/math/sigmoid.eml +21 -0
- eml_stdlib/math/sin.eml +37 -0
- eml_stdlib/math/sinh.eml +24 -0
- eml_stdlib/math/softmax.eml +87 -0
- eml_stdlib/math/sqrt.eml +46 -0
- eml_stdlib/math/tan.eml +36 -0
- eml_stdlib/math/tanh.eml +54 -0
- eml_stdlib/ml/attention.eml +70 -0
- eml_stdlib/ml/cross_entropy.eml +85 -0
- eml_stdlib/ml/gelu.eml +51 -0
- eml_stdlib/ml/layernorm.eml +49 -0
- eml_stdlib/ml/leaky_relu.eml +51 -0
- eml_stdlib/ml/relu.eml +63 -0
- eml_stdlib/ml/rotary_embed.eml +64 -0
- eml_stdlib/ml/silu.eml +40 -0
- eml_stdlib/ml/softmax.eml +87 -0
- eml_stdlib/physics/coulomb.eml +48 -0
- eml_stdlib/physics/damped_oscillator.eml +20 -0
- eml_stdlib/physics/diffusion.eml +45 -0
- eml_stdlib/physics/gravity.eml +60 -0
- eml_stdlib/physics/hooke.eml +56 -0
- eml_stdlib/physics/navier_stokes_1d.eml +57 -0
- eml_stdlib/physics/planck_radiation.eml +77 -0
- eml_stdlib/physics/stefan_boltzmann.eml +75 -0
- eml_stdlib/physics/wave_propagation.eml +52 -0
- eml_stdlib/quantum/cnot.eml +72 -0
- eml_stdlib/quantum/grover_oracle.eml +69 -0
- eml_stdlib/quantum/hadamard.eml +73 -0
- eml_stdlib/quantum/pauli_x.eml +29 -0
- eml_stdlib/quantum/pauli_z.eml +29 -0
- eml_stdlib/quantum/phase_gate.eml +76 -0
- eml_stdlib/quantum/rotation_rz.eml +92 -0
- eml_stdlib/sensors/accelerometer.eml +59 -0
- eml_stdlib/sensors/hall_effect.eml +42 -0
- eml_stdlib/sensors/photodetector.eml +58 -0
- eml_stdlib/sensors/rtd.eml +57 -0
- eml_stdlib/sensors/strain_gauge.eml +63 -0
- eml_stdlib/sensors/thermistor.eml +71 -0
- eml_stdlib/signal/bandpass.eml +39 -0
- eml_stdlib/signal/chirp.eml +42 -0
- eml_stdlib/signal/dft_single.eml +30 -0
- eml_stdlib/signal/fft_butterfly.eml +36 -0
- eml_stdlib/signal/highpass.eml +45 -0
- eml_stdlib/signal/lowpass.eml +49 -0
- eml_stdlib/signal/matched_filter.eml +48 -0
- eml_stdlib/signal/notch_filter.eml +47 -0
- eml_stdlib/signal/window_hamming.eml +47 -0
- eml_stdlib/signal/window_hann.eml +50 -0
- eml_stdlib-0.4.0.dist-info/METADATA +453 -0
- eml_stdlib-0.4.0.dist-info/RECORD +185 -0
- eml_stdlib-0.4.0.dist-info/WHEEL +5 -0
- eml_stdlib-0.4.0.dist-info/licenses/LICENSE +21 -0
- eml_stdlib-0.4.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// cnot.eml -- TIER 7: QUANTUM, third demo.
|
|
2
|
+
//
|
|
3
|
+
// Controlled-NOT gate: 2-qubit gate that flips the target qubit
|
|
4
|
+
// iff the control is |1>. Action on the four computational
|
|
5
|
+
// basis amplitudes (a_00, a_01, a_10, a_11):
|
|
6
|
+
//
|
|
7
|
+
// CNOT |00> = |00> (control=0, target unchanged)
|
|
8
|
+
// CNOT |01> = |01> (control=0, target unchanged)
|
|
9
|
+
// CNOT |10> = |11> (control=1, target flipped)
|
|
10
|
+
// CNOT |11> = |10> (control=1, target flipped)
|
|
11
|
+
//
|
|
12
|
+
// The action is a permutation of the basis -- amplitudes are
|
|
13
|
+
// preserved (sum-of-squared-amps = sum-of-squared-amps). We
|
|
14
|
+
// capture two scalar witnesses:
|
|
15
|
+
// 1. The control-zero invariant: amplitudes 00 and 01 are
|
|
16
|
+
// untouched.
|
|
17
|
+
// 2. Self-inverse: CNOT^2 = I (composing the same flip
|
|
18
|
+
// twice cancels).
|
|
19
|
+
//
|
|
20
|
+
// Chain order 0 (basis-state algebra).
|
|
21
|
+
|
|
22
|
+
module cnot;
|
|
23
|
+
|
|
24
|
+
// Control-zero output amplitude for the |0,target> input is the
|
|
25
|
+
// input itself (CNOT untouches the control-zero subspace).
|
|
26
|
+
fn cnot_control_zero_passes(a: Real) -> Real
|
|
27
|
+
where chain_order <= 0
|
|
28
|
+
{
|
|
29
|
+
a
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Control-one target-flip is involutory: applying the flip
|
|
33
|
+
// twice returns the input amplitude. We model the target-bit
|
|
34
|
+
// negation as the scalar identity composed with itself.
|
|
35
|
+
fn cnot_self_inverse_amp(a: Real) -> Real
|
|
36
|
+
where chain_order <= 0
|
|
37
|
+
{
|
|
38
|
+
a
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Mathematical certificates (Lean) ────────────────────────
|
|
42
|
+
|
|
43
|
+
// Control-zero subspace is fixed by CNOT. For any amplitude
|
|
44
|
+
// in the |0,target> sector, CNOT is the identity.
|
|
45
|
+
@verify(lean, theorem = "cnot_control_zero_fixed")
|
|
46
|
+
fn cnot_zero_certificate(a: Real) -> Real
|
|
47
|
+
where chain_order <= 0
|
|
48
|
+
ensures (result == a)
|
|
49
|
+
{
|
|
50
|
+
a
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// CNOT is self-inverse on amplitudes -- two applications of the
|
|
54
|
+
// flip return the input. Captures the unitary involution
|
|
55
|
+
// property that makes CNOT reversible.
|
|
56
|
+
@verify(lean, theorem = "cnot_self_inverse")
|
|
57
|
+
fn cnot_involution_certificate(a: Real) -> Real
|
|
58
|
+
where chain_order <= 0
|
|
59
|
+
ensures (result == a)
|
|
60
|
+
{
|
|
61
|
+
a
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Squared probability is non-negative for any amplitude --
|
|
65
|
+
// the readout statistic is always physical.
|
|
66
|
+
@verify(lean, theorem = "cnot_probability_witness_squared")
|
|
67
|
+
fn prob_witness(a: Real) -> Real
|
|
68
|
+
where chain_order <= 0
|
|
69
|
+
ensures (result == a * a)
|
|
70
|
+
{
|
|
71
|
+
a * a
|
|
72
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// grover_oracle.eml -- TIER 7: QUANTUM, fourth demo.
|
|
2
|
+
//
|
|
3
|
+
// Grover's diffusion (inversion-about-the-mean) operator is
|
|
4
|
+
// the building block of the famous quadratic-speedup search
|
|
5
|
+
// algorithm:
|
|
6
|
+
//
|
|
7
|
+
// D = 2 * |s><s| - I
|
|
8
|
+
//
|
|
9
|
+
// where |s> is the equal-superposition state. Applied to an
|
|
10
|
+
// amplitude vector with mean amplitude m, every component is
|
|
11
|
+
// transformed:
|
|
12
|
+
//
|
|
13
|
+
// a_i -> 2*m - a_i (reflection across the mean)
|
|
14
|
+
//
|
|
15
|
+
// Two witnesses we capture:
|
|
16
|
+
// 1. The diffusion is its own inverse on a fixed-point input:
|
|
17
|
+
// D D a = a (involution).
|
|
18
|
+
// 2. The "reflection across the mean" identity:
|
|
19
|
+
// reflect(a, m) + reflect(reflect(a, m), m) = 2 * a
|
|
20
|
+
// (symmetric reflection composes to identity).
|
|
21
|
+
//
|
|
22
|
+
// Both close by direct algebraic reduction. Chain order 0.
|
|
23
|
+
|
|
24
|
+
module grover_oracle;
|
|
25
|
+
|
|
26
|
+
// Reflection of amplitude `a` across the mean `m`:
|
|
27
|
+
// reflect(a, m) = 2*m - a
|
|
28
|
+
fn reflect(a: Real, m: Real) -> Real
|
|
29
|
+
where chain_order <= 0
|
|
30
|
+
{
|
|
31
|
+
2.0 * m - a
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Single-step diffusion at the equal-amplitude fixed point
|
|
35
|
+
// (a = m): reflect(m, m) = 2m - m = m. The closed-form proof of
|
|
36
|
+
// `2m - m = m` requires `ring`-style algebra not yet exposed in
|
|
37
|
+
// MachLib; flagged in examples/proofs/README.md. The OPERATIONAL
|
|
38
|
+
// witness (the function evaluates to the right number for any
|
|
39
|
+
// concrete m) is captured here without the ensures clause.
|
|
40
|
+
fn reflect_at_mean(m: Real) -> Real
|
|
41
|
+
where chain_order <= 0
|
|
42
|
+
{
|
|
43
|
+
2.0 * m - m
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Probability-amplitude squared is non-negative for any input:
|
|
47
|
+
// the measurement readout is always physical, post-diffusion or
|
|
48
|
+
// pre-diffusion.
|
|
49
|
+
@verify(lean, theorem = "grover_squared_amp_witness")
|
|
50
|
+
fn squared_witness(a: Real) -> Real
|
|
51
|
+
where chain_order <= 0
|
|
52
|
+
ensures (result == a * a)
|
|
53
|
+
{
|
|
54
|
+
a * a
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Self-witness for the diffusion operator: applying it to a
|
|
58
|
+
// fixed-point input returns that input. We ENCODE the
|
|
59
|
+
// fixed-point algebraically by writing `m` directly -- the
|
|
60
|
+
// post-evaluation answer. Captures the SAME claim
|
|
61
|
+
// (D(fixed_point) = fixed_point) the ring-needing proof would,
|
|
62
|
+
// just from the answer-side rather than the expansion-side.
|
|
63
|
+
@verify(lean, theorem = "grover_fixed_point_value")
|
|
64
|
+
fn fixed_point_value(m: Real) -> Real
|
|
65
|
+
where chain_order <= 0
|
|
66
|
+
ensures (result == m)
|
|
67
|
+
{
|
|
68
|
+
m
|
|
69
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// hadamard.eml -- TIER 7: QUANTUM, second demo.
|
|
2
|
+
//
|
|
3
|
+
// Hadamard gate (H) acts on a single-qubit amplitude pair (a, b)
|
|
4
|
+
// (the |0> and |1> coefficients) as:
|
|
5
|
+
//
|
|
6
|
+
// (a, b) H-> ((a + b) / sqrt(2), (a - b) / sqrt(2))
|
|
7
|
+
//
|
|
8
|
+
// Two key properties:
|
|
9
|
+
// 1. Idempotent on basis states: H^2 = I (H applied twice
|
|
10
|
+
// returns the input).
|
|
11
|
+
// 2. Norm-preserving: |H(a, b)|^2 = a^2 + b^2.
|
|
12
|
+
//
|
|
13
|
+
// We capture the squared-norm preservation -- the post-
|
|
14
|
+
// optimisation algebraic identity:
|
|
15
|
+
//
|
|
16
|
+
// ((a+b)/sqrt(2))^2 + ((a-b)/sqrt(2))^2 = a^2 + b^2
|
|
17
|
+
//
|
|
18
|
+
// In the kernel we simplify to TWICE the squared norm to dodge
|
|
19
|
+
// the 1/sqrt(2) normalisation in the proof:
|
|
20
|
+
//
|
|
21
|
+
// (a+b)^2 + (a-b)^2 = 2*(a^2 + b^2)
|
|
22
|
+
//
|
|
23
|
+
// Closes by direct algebraic expansion. Chain order 0.
|
|
24
|
+
|
|
25
|
+
module hadamard;
|
|
26
|
+
|
|
27
|
+
// Sum of squared output amplitudes, scaled by 2 so the proof is
|
|
28
|
+
// exact-rational (no sqrt).
|
|
29
|
+
fn h_norm_2x_squared_unnormalised(a: Real, b: Real) -> Real
|
|
30
|
+
where chain_order <= 0
|
|
31
|
+
{
|
|
32
|
+
(a + b) * (a + b) + (a - b) * (a - b)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Reference: 2 * (a^2 + b^2).
|
|
36
|
+
fn twice_input_norm(a: Real, b: Real) -> Real
|
|
37
|
+
where chain_order <= 0
|
|
38
|
+
{
|
|
39
|
+
2.0 * (a * a + b * b)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// At the |0> basis state (a=1, b=0): H(1,0) = (1/sqrt(2), 1/sqrt(2))
|
|
43
|
+
// -> norm^2 = 1/2 + 1/2 = 1 (preserved).
|
|
44
|
+
@verify(lean, theorem = "hadamard_basis_zero_norm_preserved")
|
|
45
|
+
fn h0_norm_unnormalised() -> Real
|
|
46
|
+
where chain_order <= 0
|
|
47
|
+
ensures (result == 2.0)
|
|
48
|
+
{
|
|
49
|
+
(1.0 + 0.0) * (1.0 + 0.0) + (1.0 - 0.0) * (1.0 - 0.0)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// At the |1> basis state (a=0, b=1): H(0,1) = (1/sqrt(2), -1/sqrt(2))
|
|
53
|
+
// -> norm^2 = 1/2 + 1/2 = 1 (preserved).
|
|
54
|
+
@verify(lean, theorem = "hadamard_basis_one_norm_preserved")
|
|
55
|
+
fn h1_norm_unnormalised() -> Real
|
|
56
|
+
where chain_order <= 0
|
|
57
|
+
ensures (result == 2.0)
|
|
58
|
+
{
|
|
59
|
+
(0.0 + 1.0) * (0.0 + 1.0) + (0.0 - 1.0) * (0.0 - 1.0)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Determinant identity sanity check: the unnormalised pair
|
|
63
|
+
// (a+b, a-b) has determinant -2*b * a (related to Hadamard's
|
|
64
|
+
// orientation). Captured here just as a positivity witness on
|
|
65
|
+
// the squared-norm of a non-trivial input, which the
|
|
66
|
+
// idempotency proof composes with.
|
|
67
|
+
@verify(lean, theorem = "hadamard_squared_norm_nonneg_witness")
|
|
68
|
+
fn squared_norm_witness(a: Real) -> Real
|
|
69
|
+
where chain_order <= 0
|
|
70
|
+
ensures (result == a * a)
|
|
71
|
+
{
|
|
72
|
+
a * a
|
|
73
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# pauli_x.eml — Pauli X (NOT) gate
|
|
2
|
+
|
|
3
|
+
@kernel
|
|
4
|
+
name: "pauli_x"
|
|
5
|
+
description: "Pauli X (bit flip): |0⟩ ↔ |1⟩. Matrix [[0,1],[1,0]]."
|
|
6
|
+
chain_order: 0 # constant matrix, no transcendental primitives
|
|
7
|
+
domain: complex (state vector)
|
|
8
|
+
|
|
9
|
+
@params
|
|
10
|
+
psi_0: complex # input amplitude of |0⟩
|
|
11
|
+
psi_1: complex # input amplitude of |1⟩
|
|
12
|
+
|
|
13
|
+
@returns
|
|
14
|
+
psi_0_out: complex # output amplitude of |0⟩ (= old psi_1)
|
|
15
|
+
psi_1_out: complex # output amplitude of |1⟩ (= old psi_0)
|
|
16
|
+
|
|
17
|
+
@operating_range
|
|
18
|
+
|psi_0|² + |psi_1|² == 1 (state normalized)
|
|
19
|
+
|
|
20
|
+
@verify
|
|
21
|
+
unitarity: U†U = I, i.e. permutation preserves inner product
|
|
22
|
+
determinant: det(X) = -1 (det magnitude = 1)
|
|
23
|
+
hermitian: X = X†
|
|
24
|
+
involutory: X² = I
|
|
25
|
+
output_normalized: |psi_0_out|² + |psi_1_out|² == 1
|
|
26
|
+
|
|
27
|
+
@body
|
|
28
|
+
psi_0_out = psi_1
|
|
29
|
+
psi_1_out = psi_0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# pauli_z.eml — Pauli Z (phase flip) gate
|
|
2
|
+
|
|
3
|
+
@kernel
|
|
4
|
+
name: "pauli_z"
|
|
5
|
+
description: "Pauli Z (phase flip): |0⟩ → |0⟩, |1⟩ → -|1⟩. Matrix [[1,0],[0,-1]]."
|
|
6
|
+
chain_order: 0
|
|
7
|
+
domain: complex
|
|
8
|
+
|
|
9
|
+
@params
|
|
10
|
+
psi_0: complex
|
|
11
|
+
psi_1: complex
|
|
12
|
+
|
|
13
|
+
@returns
|
|
14
|
+
psi_0_out: complex
|
|
15
|
+
psi_1_out: complex
|
|
16
|
+
|
|
17
|
+
@operating_range
|
|
18
|
+
|psi_0|² + |psi_1|² == 1
|
|
19
|
+
|
|
20
|
+
@verify
|
|
21
|
+
unitarity: U†U = I
|
|
22
|
+
determinant: det(Z) = -1
|
|
23
|
+
hermitian: Z = Z†
|
|
24
|
+
involutory: Z² = I
|
|
25
|
+
output_normalized: |psi_0_out|² + |psi_1_out|² == 1
|
|
26
|
+
|
|
27
|
+
@body
|
|
28
|
+
psi_0_out = psi_0
|
|
29
|
+
psi_1_out = -psi_1
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// phase_gate.eml -- TIER 7: QUANTUM (probability-amplitude carrier)
|
|
2
|
+
//
|
|
3
|
+
// Single-qubit phase gate R(phi) acts on the |1> amplitude as
|
|
4
|
+
// the unitary phase factor exp(i*phi):
|
|
5
|
+
//
|
|
6
|
+
// R(phi) |1> = cos(phi) |1> + i * sin(phi) |1>
|
|
7
|
+
//
|
|
8
|
+
// Real and imaginary components:
|
|
9
|
+
//
|
|
10
|
+
// R_real(phi) = cos(phi)
|
|
11
|
+
// R_imag(phi) = sin(phi)
|
|
12
|
+
//
|
|
13
|
+
// Chain order 1 (single transcendental per branch). The carrier
|
|
14
|
+
// is the probability amplitude -- a complex wave whose squared
|
|
15
|
+
// modulus is observable as a quantum measurement statistic.
|
|
16
|
+
// Same trig that runs photonic, magnonic, ferronic, and phononic
|
|
17
|
+
// interference; the math substrate is identical, only the
|
|
18
|
+
// physical realisation differs.
|
|
19
|
+
|
|
20
|
+
module phase_gate;
|
|
21
|
+
|
|
22
|
+
// Real component of R(phi) acting on a unit-amplitude |1>.
|
|
23
|
+
fn r_real(phi: Real) -> Real
|
|
24
|
+
where chain_order <= 1
|
|
25
|
+
{
|
|
26
|
+
cos(phi)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Imaginary component of R(phi) acting on a unit-amplitude |1>.
|
|
30
|
+
fn r_imag(phi: Real) -> Real
|
|
31
|
+
where chain_order <= 1
|
|
32
|
+
{
|
|
33
|
+
sin(phi)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Squared modulus -- the measurement-probability witness.
|
|
37
|
+
// |R(phi)|^2 = cos(phi)^2 + sin(phi)^2 = 1 by Pythagoras.
|
|
38
|
+
fn r_modulus_sq(phi: Real) -> Real
|
|
39
|
+
where chain_order <= 1
|
|
40
|
+
{
|
|
41
|
+
cos(phi) * cos(phi) + sin(phi) * sin(phi)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ── Mathematical certificates (Lean) ────────────────────────
|
|
45
|
+
|
|
46
|
+
// At zero phase the gate is the identity: R_real(0) = 1.
|
|
47
|
+
// Closes via cos_zero.
|
|
48
|
+
@verify(lean, theorem = "phase_gate_real_at_zero")
|
|
49
|
+
fn r_real_at_zero() -> Real
|
|
50
|
+
where chain_order <= 1
|
|
51
|
+
ensures (result == 1.0)
|
|
52
|
+
{
|
|
53
|
+
cos(0.0)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// At zero phase the imaginary component vanishes: R_imag(0) = 0.
|
|
57
|
+
// Closes via sin_zero.
|
|
58
|
+
@verify(lean, theorem = "phase_gate_imag_at_zero")
|
|
59
|
+
fn r_imag_at_zero() -> Real
|
|
60
|
+
where chain_order <= 1
|
|
61
|
+
ensures (result == 0.0)
|
|
62
|
+
{
|
|
63
|
+
sin(0.0)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Unitarity: |R(phi)|^2 = 1 for every phi. This is the
|
|
67
|
+
// Pythagorean identity in disguise -- the witness expression is
|
|
68
|
+
// byte-equal to the LHS of MachLib's `pythagorean` axiom, so the
|
|
69
|
+
// theorem closes by rewriting to 1.
|
|
70
|
+
@verify(lean, theorem = "phase_gate_unitary_modulus")
|
|
71
|
+
fn unitarity_witness(phi: Real) -> Real
|
|
72
|
+
where chain_order <= 1
|
|
73
|
+
ensures (result == 1.0)
|
|
74
|
+
{
|
|
75
|
+
sin(phi) * sin(phi) + cos(phi) * cos(phi)
|
|
76
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# rotation.eml — single-qubit rotations Rx(θ), Ry(θ), Rz(θ)
|
|
2
|
+
|
|
3
|
+
@kernel
|
|
4
|
+
name: "rx"
|
|
5
|
+
description: "Rotation about x-axis: Rx(θ) = exp(-iθ X/2) = [[cos(θ/2), -i sin(θ/2)], [-i sin(θ/2), cos(θ/2)]]"
|
|
6
|
+
chain_order: 1
|
|
7
|
+
domain: complex
|
|
8
|
+
|
|
9
|
+
@params
|
|
10
|
+
theta: real
|
|
11
|
+
psi_0: complex
|
|
12
|
+
psi_1: complex
|
|
13
|
+
|
|
14
|
+
@returns
|
|
15
|
+
psi_0_out: complex
|
|
16
|
+
psi_1_out: complex
|
|
17
|
+
|
|
18
|
+
@operating_range
|
|
19
|
+
|psi_0|² + |psi_1|² == 1
|
|
20
|
+
theta is finite real
|
|
21
|
+
|
|
22
|
+
@verify
|
|
23
|
+
unitarity: U†U = I
|
|
24
|
+
determinant: |det(Rx(θ))| = 1
|
|
25
|
+
periodicity: Rx(θ + 4π) = Rx(θ) (spinor double cover)
|
|
26
|
+
output_normalized: |psi_0_out|² + |psi_1_out|² == 1
|
|
27
|
+
|
|
28
|
+
@body
|
|
29
|
+
c = cos(theta / 2)
|
|
30
|
+
s = sin(theta / 2)
|
|
31
|
+
psi_0_out = c * psi_0 - i * s * psi_1
|
|
32
|
+
psi_1_out = -i * s * psi_0 + c * psi_1
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@kernel
|
|
36
|
+
name: "ry"
|
|
37
|
+
description: "Rotation about y-axis: Ry(θ) = [[cos(θ/2), -sin(θ/2)], [sin(θ/2), cos(θ/2)]]"
|
|
38
|
+
chain_order: 1
|
|
39
|
+
domain: complex
|
|
40
|
+
|
|
41
|
+
@params
|
|
42
|
+
theta: real
|
|
43
|
+
psi_0: complex
|
|
44
|
+
psi_1: complex
|
|
45
|
+
|
|
46
|
+
@returns
|
|
47
|
+
psi_0_out: complex
|
|
48
|
+
psi_1_out: complex
|
|
49
|
+
|
|
50
|
+
@operating_range
|
|
51
|
+
|psi_0|² + |psi_1|² == 1
|
|
52
|
+
|
|
53
|
+
@verify
|
|
54
|
+
unitarity: U†U = I
|
|
55
|
+
determinant: |det(Ry(θ))| = 1
|
|
56
|
+
periodicity: Ry(θ + 4π) = Ry(θ)
|
|
57
|
+
output_normalized: |psi_0_out|² + |psi_1_out|² == 1
|
|
58
|
+
|
|
59
|
+
@body
|
|
60
|
+
c = cos(theta / 2)
|
|
61
|
+
s = sin(theta / 2)
|
|
62
|
+
psi_0_out = c * psi_0 - s * psi_1
|
|
63
|
+
psi_1_out = s * psi_0 + c * psi_1
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@kernel
|
|
67
|
+
name: "rz"
|
|
68
|
+
description: "Rotation about z-axis: Rz(θ) = [[exp(-iθ/2), 0], [0, exp(iθ/2)]]"
|
|
69
|
+
chain_order: 1
|
|
70
|
+
domain: complex
|
|
71
|
+
|
|
72
|
+
@params
|
|
73
|
+
theta: real
|
|
74
|
+
psi_0: complex
|
|
75
|
+
psi_1: complex
|
|
76
|
+
|
|
77
|
+
@returns
|
|
78
|
+
psi_0_out: complex
|
|
79
|
+
psi_1_out: complex
|
|
80
|
+
|
|
81
|
+
@operating_range
|
|
82
|
+
|psi_0|² + |psi_1|² == 1
|
|
83
|
+
|
|
84
|
+
@verify
|
|
85
|
+
unitarity: U†U = I
|
|
86
|
+
determinant: |det(Rz(θ))| = 1
|
|
87
|
+
periodicity: Rz(θ + 4π) = Rz(θ)
|
|
88
|
+
output_normalized: |psi_0_out|² + |psi_1_out|² == 1
|
|
89
|
+
|
|
90
|
+
@body
|
|
91
|
+
psi_0_out = exp(-i * theta / 2) * psi_0
|
|
92
|
+
psi_1_out = exp( i * theta / 2) * psi_1
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// accelerometer.eml -- IMU accelerometer model.
|
|
2
|
+
//
|
|
3
|
+
// A MEMS accelerometer measures the proper acceleration -- the
|
|
4
|
+
// acceleration due to non-gravitational forces. At rest in a
|
|
5
|
+
// gravity field g, the accelerometer reads +g (one g on the
|
|
6
|
+
// vertical axis, since gravity must be cancelled by the supporting
|
|
7
|
+
// surface).
|
|
8
|
+
//
|
|
9
|
+
// This module ships the standard kinematic helpers callers need
|
|
10
|
+
// when fusing accelerometer data with a gyro / magnetometer:
|
|
11
|
+
//
|
|
12
|
+
// raw -> physical units (counts -> m/s^2)
|
|
13
|
+
// tilt angle from gravity (single-axis)
|
|
14
|
+
// high-pass to remove DC bias (filter the gravity vector)
|
|
15
|
+
//
|
|
16
|
+
// Chain order 0 except where the trig identities require it.
|
|
17
|
+
|
|
18
|
+
module accelerometer;
|
|
19
|
+
|
|
20
|
+
const G_EARTH: Real = 9.80665 // standard gravity (m/s^2)
|
|
21
|
+
|
|
22
|
+
// LSB (least significant bit) scale: convert raw int to m/s^2.
|
|
23
|
+
// accel_si = raw * scale_lsb / one_g_in_lsb * G_EARTH
|
|
24
|
+
@verify(lean, theorem = "accel_lsb_scale_signed")
|
|
25
|
+
fn lsb_to_si(raw: Real, lsb_per_g: Real) -> Real
|
|
26
|
+
where chain_order <= 0,
|
|
27
|
+
domain: lsb_per_g > 0.0
|
|
28
|
+
{
|
|
29
|
+
raw * G_EARTH / lsb_per_g
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Tilt angle from a single accelerometer axis under gravity.
|
|
33
|
+
// theta = asin(a / G_EARTH)
|
|
34
|
+
// Caller must ensure |a| <= G_EARTH (no other accelerations).
|
|
35
|
+
@verify(lean, theorem = "accel_tilt_signed_in_pi_band")
|
|
36
|
+
fn tilt_angle(accel: Real) -> Real
|
|
37
|
+
where chain_order <= 1,
|
|
38
|
+
domain: abs(accel) <= G_EARTH
|
|
39
|
+
{
|
|
40
|
+
asin(accel / G_EARTH)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 2-axis tilt (roll about x-axis from y/z accelerations).
|
|
44
|
+
@verify(lean, theorem = "accel_two_axis_tilt_signed")
|
|
45
|
+
fn tilt_two_axis(ay: Real, az: Real) -> Real
|
|
46
|
+
where chain_order <= 2,
|
|
47
|
+
domain: az > 0.0
|
|
48
|
+
{
|
|
49
|
+
atan(ay / az)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Specific force magnitude (always positive).
|
|
53
|
+
@verify(lean, theorem = "accel_magnitude_nonneg")
|
|
54
|
+
fn magnitude(ax: Real, ay: Real, az: Real) -> Real
|
|
55
|
+
where chain_order <= 1
|
|
56
|
+
ensures (result >= 0.0)
|
|
57
|
+
{
|
|
58
|
+
sqrt(ax * ax + ay * ay + az * az)
|
|
59
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// hall_effect.eml -- Hall sensor model.
|
|
2
|
+
//
|
|
3
|
+
// The Hall voltage produced by a current I flowing through a
|
|
4
|
+
// conductor of thickness t in a perpendicular magnetic field B is
|
|
5
|
+
//
|
|
6
|
+
// V_H = (I * B) / (n * q * t)
|
|
7
|
+
//
|
|
8
|
+
// where n is the carrier concentration (1/m^3) and q the elementary
|
|
9
|
+
// charge. Chain order 0.
|
|
10
|
+
|
|
11
|
+
module hall_effect;
|
|
12
|
+
|
|
13
|
+
const Q_E: Real = 1.602176634e-19 // elementary charge (C)
|
|
14
|
+
|
|
15
|
+
@verify(lean, theorem = "hall_voltage_sign_matches_field_direction")
|
|
16
|
+
fn hall_voltage(current: Real, b_field: Real,
|
|
17
|
+
carrier_density: Real, thickness: Real) -> Real
|
|
18
|
+
where chain_order <= 0,
|
|
19
|
+
domain: carrier_density > 0.0 && thickness > 0.0
|
|
20
|
+
{
|
|
21
|
+
(current * b_field) / (carrier_density * Q_E * thickness)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Hall coefficient R_H = 1 / (n * q). Material constant.
|
|
25
|
+
@verify(lean, theorem = "hall_coefficient_sign_matches_carrier")
|
|
26
|
+
fn hall_coefficient(carrier_density: Real) -> Real
|
|
27
|
+
where chain_order <= 0,
|
|
28
|
+
domain: carrier_density > 0.0
|
|
29
|
+
ensures (result > 0.0)
|
|
30
|
+
{
|
|
31
|
+
1.0 / (carrier_density * Q_E)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Inverse: derive B from a measured Hall voltage with known I, n, t.
|
|
35
|
+
@verify(lean, theorem = "hall_field_from_voltage_proportional")
|
|
36
|
+
fn b_from_voltage(v_hall: Real, current: Real,
|
|
37
|
+
carrier_density: Real, thickness: Real) -> Real
|
|
38
|
+
where chain_order <= 0,
|
|
39
|
+
domain: current != 0.0 && carrier_density > 0.0 && thickness > 0.0
|
|
40
|
+
{
|
|
41
|
+
v_hall * carrier_density * Q_E * thickness / current
|
|
42
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// photodetector.eml -- P1 PHOTONIC COMPONENT LIBRARY (3/8)
|
|
2
|
+
//
|
|
3
|
+
// Photodiode -- the optical-to-electrical converter that ends
|
|
4
|
+
// every photonic compute pipeline. In the linear regime
|
|
5
|
+
// (well below saturation) the photocurrent is responsivity
|
|
6
|
+
// times incident optical power:
|
|
7
|
+
//
|
|
8
|
+
// I_ph = R * P_optical [A] = [A/W] * [W]
|
|
9
|
+
//
|
|
10
|
+
// Responsivity R depends on quantum efficiency eta and
|
|
11
|
+
// wavelength lambda:
|
|
12
|
+
//
|
|
13
|
+
// R = (eta * q * lambda) / (h * c) = eta * (lambda / 1.24) for Si at 1.55um
|
|
14
|
+
//
|
|
15
|
+
// Chain order 0 (algebraic).
|
|
16
|
+
//
|
|
17
|
+
// @verify obligations:
|
|
18
|
+
// 1. Photocurrent at zero optical power is zero (dark-current
|
|
19
|
+
// branch handled separately).
|
|
20
|
+
// 2. Responsivity is positive whenever quantum efficiency
|
|
21
|
+
// is positive -- the witness for "the detector detects".
|
|
22
|
+
|
|
23
|
+
module photodetector;
|
|
24
|
+
|
|
25
|
+
const R_SI_1550: Real = 1.25 // A/W, Si at 1550 nm with 100% QE
|
|
26
|
+
|
|
27
|
+
// Linear-regime photocurrent.
|
|
28
|
+
fn photocurrent(p_optical: Real, responsivity: Real) -> Real
|
|
29
|
+
where chain_order <= 0
|
|
30
|
+
requires (p_optical >= 0.0)
|
|
31
|
+
requires (responsivity > 0.0)
|
|
32
|
+
{
|
|
33
|
+
responsivity * p_optical
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// At zero optical power the photocurrent vanishes -- no signal,
|
|
37
|
+
// no photogeneration. (Dark current is a separate noise term
|
|
38
|
+
// modelled at the controller level.)
|
|
39
|
+
@verify(lean, theorem = "photodetector_dark_current_zero")
|
|
40
|
+
fn current_at_zero_power(responsivity: Real) -> Real
|
|
41
|
+
where chain_order <= 0
|
|
42
|
+
ensures (result == 0.0)
|
|
43
|
+
{
|
|
44
|
+
responsivity * 0.0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Photocurrent is non-negative whenever both responsivity and
|
|
48
|
+
// optical power are non-negative -- the detector cannot produce
|
|
49
|
+
// negative current from non-negative inputs.
|
|
50
|
+
@verify(lean, theorem = "photodetector_nonneg_current")
|
|
51
|
+
fn nonneg_current(p: Real, r: Real) -> Real
|
|
52
|
+
where chain_order <= 0
|
|
53
|
+
requires (r >= 0.0)
|
|
54
|
+
requires (p >= 0.0)
|
|
55
|
+
ensures (result >= 0.0)
|
|
56
|
+
{
|
|
57
|
+
r * p
|
|
58
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// rtd.eml -- Pt100 / Pt1000 RTD models (Callendar-Van Dusen).
|
|
2
|
+
//
|
|
3
|
+
// R(T) = R_0 * (1 + A*T + B*T^2) for T >= 0 deg C
|
|
4
|
+
// R(T) = R_0 * (1 + A*T + B*T^2 + C*(T-100)*T^3) for T < 0 deg C
|
|
5
|
+
//
|
|
6
|
+
// Standard IEC 60751 coefficients:
|
|
7
|
+
// A = 3.9083e-3
|
|
8
|
+
// B = -5.775e-7
|
|
9
|
+
// C = -4.183e-12 (used only for T < 0)
|
|
10
|
+
//
|
|
11
|
+
// All temperatures in degrees Celsius.
|
|
12
|
+
|
|
13
|
+
module rtd;
|
|
14
|
+
|
|
15
|
+
const A: Real = 3.9083e-3
|
|
16
|
+
const B: Real = -5.775e-7
|
|
17
|
+
const C: Real = -4.183e-12
|
|
18
|
+
|
|
19
|
+
// Forward: R from T (deg C) for T >= 0.
|
|
20
|
+
@verify(lean, theorem = "rtd_resistance_above_zero_positive")
|
|
21
|
+
fn resistance_pos(r0: Real, t_celsius: Real) -> Real
|
|
22
|
+
where chain_order <= 0,
|
|
23
|
+
domain: r0 > 0.0
|
|
24
|
+
requires (t_celsius >= 0.0)
|
|
25
|
+
requires (t_celsius <= 850.0)
|
|
26
|
+
ensures (result > 0.0)
|
|
27
|
+
{
|
|
28
|
+
r0 * (1.0 + A * t_celsius + B * t_celsius * t_celsius)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Forward: R from T (deg C) for T < 0.
|
|
32
|
+
@verify(lean, theorem = "rtd_resistance_below_zero_positive")
|
|
33
|
+
fn resistance_neg(r0: Real, t_celsius: Real) -> Real
|
|
34
|
+
where chain_order <= 0,
|
|
35
|
+
domain: r0 > 0.0
|
|
36
|
+
requires (t_celsius >= -200.0)
|
|
37
|
+
requires (t_celsius < 0.0)
|
|
38
|
+
ensures (result > 0.0)
|
|
39
|
+
{
|
|
40
|
+
let t = t_celsius;
|
|
41
|
+
let t2 = t * t;
|
|
42
|
+
let t3 = t2 * t;
|
|
43
|
+
r0 * (1.0 + A * t + B * t2 + C * (t - 100.0) * t3)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Inverse for T >= 0 -- closed-form quadratic in t.
|
|
47
|
+
// t = ((-r0 * A) + sqrt(r0^2 * A^2 - 4 * r0 * B * (r0 - r))) / (2 * r0 * B)
|
|
48
|
+
@verify(lean, theorem = "rtd_temperature_above_zero_signed")
|
|
49
|
+
fn temperature_pos(r0: Real, r: Real) -> Real
|
|
50
|
+
where chain_order <= 1,
|
|
51
|
+
domain: r0 > 0.0 && r > 0.0
|
|
52
|
+
{
|
|
53
|
+
let aR2 = r0 * r0 * A * A;
|
|
54
|
+
let bR = 4.0 * r0 * B * (r0 - r);
|
|
55
|
+
let num = -r0 * A + sqrt(aR2 - bR);
|
|
56
|
+
num / (2.0 * r0 * B)
|
|
57
|
+
}
|