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.
Files changed (185) hide show
  1. eml_stdlib/__init__.py +81 -0
  2. eml_stdlib/ballistics/air_density.eml +73 -0
  3. eml_stdlib/ballistics/ballistic_solver.eml +102 -0
  4. eml_stdlib/ballistics/coriolis.eml +60 -0
  5. eml_stdlib/ballistics/drag.eml +44 -0
  6. eml_stdlib/ballistics/gravity.eml +52 -0
  7. eml_stdlib/ballistics/muzzle_velocity.eml +42 -0
  8. eml_stdlib/ballistics/spin_drift.eml +60 -0
  9. eml_stdlib/ballistics/time_of_flight.eml +79 -0
  10. eml_stdlib/ballistics/wind.eml +58 -0
  11. eml_stdlib/biology/abilities/ballistic_armor.eml +61 -0
  12. eml_stdlib/biology/abilities/bite_force.eml +48 -0
  13. eml_stdlib/biology/abilities/chromatophore.eml +50 -0
  14. eml_stdlib/biology/abilities/discharge.eml +45 -0
  15. eml_stdlib/biology/abilities/elastic_energy.eml +42 -0
  16. eml_stdlib/biology/abilities/locomotion.eml +50 -0
  17. eml_stdlib/biology/abilities/muscle_power.eml +47 -0
  18. eml_stdlib/biology/abilities/sprint.eml +36 -0
  19. eml_stdlib/biology/abilities/texture_match.eml +49 -0
  20. eml_stdlib/biology/abilities/toxin.eml +44 -0
  21. eml_stdlib/biology/cone_l.eml +36 -0
  22. eml_stdlib/biology/cone_s.eml +32 -0
  23. eml_stdlib/biology/cryptochrome.eml +44 -0
  24. eml_stdlib/biology/geomagnetic_field.eml +32 -0
  25. eml_stdlib/biology/goldman_equation.eml +41 -0
  26. eml_stdlib/biology/hill_equation.eml +65 -0
  27. eml_stdlib/biology/hodgkin_huxley.eml +108 -0
  28. eml_stdlib/biology/michaelis_menten.eml +65 -0
  29. eml_stdlib/biology/plume_diffusion.eml +47 -0
  30. eml_stdlib/biology/receptor_binding.eml +35 -0
  31. eml_stdlib/biology/rod_sensitivity.eml +38 -0
  32. eml_stdlib/biology/tapetum.eml +70 -0
  33. eml_stdlib/carriers/acoustic_cloak.eml +56 -0
  34. eml_stdlib/carriers/ferron_emission.eml +55 -0
  35. eml_stdlib/carriers/ferron_logic.eml +45 -0
  36. eml_stdlib/carriers/ferron_propagation.eml +69 -0
  37. eml_stdlib/carriers/mach_zehnder.eml +52 -0
  38. eml_stdlib/carriers/magnon_dispersion.eml +57 -0
  39. eml_stdlib/carriers/magnon_logic.eml +45 -0
  40. eml_stdlib/carriers/optical_neuron.eml +55 -0
  41. eml_stdlib/carriers/phonon_bandgap.eml +54 -0
  42. eml_stdlib/carriers/ring_resonator.eml +48 -0
  43. eml_stdlib/carriers/spin_torque.eml +61 -0
  44. eml_stdlib/carriers/thermal_rectifier.eml +63 -0
  45. eml_stdlib/catalog.json +4209 -0
  46. eml_stdlib/circuits/buck_converter.eml +74 -0
  47. eml_stdlib/circuits/cmos_inverter.eml +75 -0
  48. eml_stdlib/circuits/h_bridge.eml +69 -0
  49. eml_stdlib/circuits/ldo.eml +66 -0
  50. eml_stdlib/circuits/mosfet_iv.eml +59 -0
  51. eml_stdlib/circuits/pll_loop.eml +63 -0
  52. eml_stdlib/circuits/rc_filter.eml +98 -0
  53. eml_stdlib/circuits/voltage_divider.eml +68 -0
  54. eml_stdlib/control/bangbang.eml +34 -0
  55. eml_stdlib/control/deadband.eml +28 -0
  56. eml_stdlib/control/hysteresis.eml +28 -0
  57. eml_stdlib/control/kalman_1d.eml +53 -0
  58. eml_stdlib/control/lqr_1d.eml +47 -0
  59. eml_stdlib/control/pid.eml +38 -0
  60. eml_stdlib/gaming/animation/bounce.eml +39 -0
  61. eml_stdlib/gaming/animation/ease_in.eml +27 -0
  62. eml_stdlib/gaming/animation/ease_in_out.eml +29 -0
  63. eml_stdlib/gaming/animation/ease_out.eml +27 -0
  64. eml_stdlib/gaming/animation/ik_2bone.eml +57 -0
  65. eml_stdlib/gaming/animation/spring.eml +39 -0
  66. eml_stdlib/gaming/audio/distance_attenuation.eml +50 -0
  67. eml_stdlib/gaming/audio/doppler.eml +39 -0
  68. eml_stdlib/gaming/audio/lowpass_audio.eml +32 -0
  69. eml_stdlib/gaming/audio/reverb_delay.eml +41 -0
  70. eml_stdlib/gaming/camera/dof_blur.eml +30 -0
  71. eml_stdlib/gaming/camera/fov_projection.eml +47 -0
  72. eml_stdlib/gaming/camera/orbit.eml +48 -0
  73. eml_stdlib/gaming/camera/shake.eml +20 -0
  74. eml_stdlib/gaming/lighting/ambient_occlusion.eml +40 -0
  75. eml_stdlib/gaming/lighting/area_light.eml +50 -0
  76. eml_stdlib/gaming/lighting/fog_exp.eml +28 -0
  77. eml_stdlib/gaming/lighting/fog_exp2.eml +30 -0
  78. eml_stdlib/gaming/lighting/point_light.eml +33 -0
  79. eml_stdlib/gaming/lighting/spot_light.eml +43 -0
  80. eml_stdlib/gaming/noise/fbm.eml +65 -0
  81. eml_stdlib/gaming/noise/perlin_2d.eml +65 -0
  82. eml_stdlib/gaming/noise/perlin_3d.eml +63 -0
  83. eml_stdlib/gaming/noise/simplex_2d.eml +67 -0
  84. eml_stdlib/gaming/noise/turbulence.eml +46 -0
  85. eml_stdlib/gaming/noise/value_noise.eml +45 -0
  86. eml_stdlib/gaming/noise/voronoi_2d.eml +83 -0
  87. eml_stdlib/gaming/noise/white_noise.eml +47 -0
  88. eml_stdlib/gaming/noise/worley.eml +79 -0
  89. eml_stdlib/gaming/particles/drag.eml +30 -0
  90. eml_stdlib/gaming/particles/emitter_radial.eml +35 -0
  91. eml_stdlib/gaming/particles/fade.eml +36 -0
  92. eml_stdlib/gaming/particles/gravity_particle.eml +32 -0
  93. eml_stdlib/gaming/particles/size_over_life.eml +28 -0
  94. eml_stdlib/gaming/physics/aabb_overlap.eml +38 -0
  95. eml_stdlib/gaming/physics/buoyancy.eml +43 -0
  96. eml_stdlib/gaming/physics/circle_collision.eml +46 -0
  97. eml_stdlib/gaming/physics/impulse_resolve.eml +39 -0
  98. eml_stdlib/gaming/physics/rigid_body_2d.eml +61 -0
  99. eml_stdlib/gaming/physics/spring_damper.eml +30 -0
  100. eml_stdlib/gaming/physics/verlet.eml +29 -0
  101. eml_stdlib/gaming/shading/fresnel.eml +57 -0
  102. eml_stdlib/gaming/shading/matcap.eml +34 -0
  103. eml_stdlib/gaming/shading/pbr_diffuse.eml +41 -0
  104. eml_stdlib/gaming/shading/pbr_specular.eml +75 -0
  105. eml_stdlib/gaming/shading/subsurface.eml +52 -0
  106. eml_stdlib/gaming/shading/toon.eml +30 -0
  107. eml_stdlib/gaming/terrain/biome_select.eml +41 -0
  108. eml_stdlib/gaming/terrain/cliff_detect.eml +35 -0
  109. eml_stdlib/gaming/terrain/erosion_hydraulic.eml +57 -0
  110. eml_stdlib/gaming/terrain/erosion_thermal.eml +44 -0
  111. eml_stdlib/gaming/terrain/heightmap.eml +33 -0
  112. eml_stdlib/gaming/textures/brick.eml +27 -0
  113. eml_stdlib/gaming/textures/caustics.eml +25 -0
  114. eml_stdlib/gaming/textures/checkerboard.eml +27 -0
  115. eml_stdlib/gaming/textures/fire.eml +26 -0
  116. eml_stdlib/gaming/textures/marble.eml +24 -0
  117. eml_stdlib/gaming/textures/rust.eml +23 -0
  118. eml_stdlib/gaming/textures/water_surface.eml +49 -0
  119. eml_stdlib/gaming/textures/wood.eml +41 -0
  120. eml_stdlib/math/abs.eml +45 -0
  121. eml_stdlib/math/atan.eml +32 -0
  122. eml_stdlib/math/atan2.eml +61 -0
  123. eml_stdlib/math/bessel_j0.eml +65 -0
  124. eml_stdlib/math/cos.eml +42 -0
  125. eml_stdlib/math/cosh.eml +24 -0
  126. eml_stdlib/math/erf.eml +66 -0
  127. eml_stdlib/math/exp.eml +49 -0
  128. eml_stdlib/math/gamma.eml +55 -0
  129. eml_stdlib/math/gaussian.eml +18 -0
  130. eml_stdlib/math/log.eml +59 -0
  131. eml_stdlib/math/pow.eml +51 -0
  132. eml_stdlib/math/relu.eml +63 -0
  133. eml_stdlib/math/sigmoid.eml +21 -0
  134. eml_stdlib/math/sin.eml +37 -0
  135. eml_stdlib/math/sinh.eml +24 -0
  136. eml_stdlib/math/softmax.eml +87 -0
  137. eml_stdlib/math/sqrt.eml +46 -0
  138. eml_stdlib/math/tan.eml +36 -0
  139. eml_stdlib/math/tanh.eml +54 -0
  140. eml_stdlib/ml/attention.eml +70 -0
  141. eml_stdlib/ml/cross_entropy.eml +85 -0
  142. eml_stdlib/ml/gelu.eml +51 -0
  143. eml_stdlib/ml/layernorm.eml +49 -0
  144. eml_stdlib/ml/leaky_relu.eml +51 -0
  145. eml_stdlib/ml/relu.eml +63 -0
  146. eml_stdlib/ml/rotary_embed.eml +64 -0
  147. eml_stdlib/ml/silu.eml +40 -0
  148. eml_stdlib/ml/softmax.eml +87 -0
  149. eml_stdlib/physics/coulomb.eml +48 -0
  150. eml_stdlib/physics/damped_oscillator.eml +20 -0
  151. eml_stdlib/physics/diffusion.eml +45 -0
  152. eml_stdlib/physics/gravity.eml +60 -0
  153. eml_stdlib/physics/hooke.eml +56 -0
  154. eml_stdlib/physics/navier_stokes_1d.eml +57 -0
  155. eml_stdlib/physics/planck_radiation.eml +77 -0
  156. eml_stdlib/physics/stefan_boltzmann.eml +75 -0
  157. eml_stdlib/physics/wave_propagation.eml +52 -0
  158. eml_stdlib/quantum/cnot.eml +72 -0
  159. eml_stdlib/quantum/grover_oracle.eml +69 -0
  160. eml_stdlib/quantum/hadamard.eml +73 -0
  161. eml_stdlib/quantum/pauli_x.eml +29 -0
  162. eml_stdlib/quantum/pauli_z.eml +29 -0
  163. eml_stdlib/quantum/phase_gate.eml +76 -0
  164. eml_stdlib/quantum/rotation_rz.eml +92 -0
  165. eml_stdlib/sensors/accelerometer.eml +59 -0
  166. eml_stdlib/sensors/hall_effect.eml +42 -0
  167. eml_stdlib/sensors/photodetector.eml +58 -0
  168. eml_stdlib/sensors/rtd.eml +57 -0
  169. eml_stdlib/sensors/strain_gauge.eml +63 -0
  170. eml_stdlib/sensors/thermistor.eml +71 -0
  171. eml_stdlib/signal/bandpass.eml +39 -0
  172. eml_stdlib/signal/chirp.eml +42 -0
  173. eml_stdlib/signal/dft_single.eml +30 -0
  174. eml_stdlib/signal/fft_butterfly.eml +36 -0
  175. eml_stdlib/signal/highpass.eml +45 -0
  176. eml_stdlib/signal/lowpass.eml +49 -0
  177. eml_stdlib/signal/matched_filter.eml +48 -0
  178. eml_stdlib/signal/notch_filter.eml +47 -0
  179. eml_stdlib/signal/window_hamming.eml +47 -0
  180. eml_stdlib/signal/window_hann.eml +50 -0
  181. eml_stdlib-0.4.0.dist-info/METADATA +453 -0
  182. eml_stdlib-0.4.0.dist-info/RECORD +185 -0
  183. eml_stdlib-0.4.0.dist-info/WHEEL +5 -0
  184. eml_stdlib-0.4.0.dist-info/licenses/LICENSE +21 -0
  185. eml_stdlib-0.4.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,64 @@
1
+ // rotary_embed.eml -- Rotary Position Embedding (RoPE) kernel.
2
+ //
3
+ // RoPE applies a 2D rotation to each (x_even, x_odd) pair in the
4
+ // query/key vector at position m. The rotation angle is
5
+ //
6
+ // theta_i = m / base^(2i/d)
7
+ //
8
+ // where base = 10000 (standard), d is the head dimension, i in
9
+ // [0, d/2). The transformed pair is
10
+ //
11
+ // x_even' = x_even * cos(theta) - x_odd * sin(theta)
12
+ // x_odd' = x_even * sin(theta) + x_odd * cos(theta)
13
+ //
14
+ // Chain order 1 -- one sin, one cos per pair. The dot-product
15
+ // q . k after RoPE encodes the relative position (m - n), which is
16
+ // what the attention layer wants.
17
+
18
+ module rotary_embed;
19
+
20
+ const DEFAULT_BASE: Real = 10000.0
21
+
22
+ // Rotation angle for index i at position m.
23
+ @verify(lean, theorem = "rope_theta_at_zero_position_is_zero")
24
+ fn theta(m: Real, i: Real, d: Real, base: Real) -> Real
25
+ where chain_order <= 1,
26
+ domain: d > 0.0 && base > 0.0
27
+ {
28
+ let exponent = 2.0 * i / d;
29
+ m / pow(base, exponent)
30
+ }
31
+
32
+ // Default-base theta.
33
+ @verify(lean, theorem = "rope_default_theta_at_zero_position_is_zero")
34
+ fn theta_default(m: Real, i: Real, d: Real) -> Real
35
+ where chain_order <= 1,
36
+ domain: d > 0.0
37
+ {
38
+ let exponent = 2.0 * i / d;
39
+ m / pow(DEFAULT_BASE, exponent)
40
+ }
41
+
42
+ // Rotate one (even, odd) pair.
43
+ @verify(lean, theorem = "rope_rotation_preserves_norm")
44
+ fn rotate_pair_even(x_even: Real, x_odd: Real, theta: Real) -> Real
45
+ where chain_order <= 1
46
+ {
47
+ x_even * cos(theta) - x_odd * sin(theta)
48
+ }
49
+
50
+ @verify(lean, theorem = "rope_rotation_pair_norm_preserved")
51
+ fn rotate_pair_odd(x_even: Real, x_odd: Real, theta: Real) -> Real
52
+ where chain_order <= 1
53
+ {
54
+ x_even * sin(theta) + x_odd * cos(theta)
55
+ }
56
+
57
+ // Pythagorean witness: |rotated|^2 = |x_even|^2 + |x_odd|^2.
58
+ @verify(lean, theorem = "rope_pythagorean_witness")
59
+ fn norm_witness(theta: Real) -> Real
60
+ where chain_order <= 1
61
+ ensures (result == 1.0)
62
+ {
63
+ sin(theta) * sin(theta) + cos(theta) * cos(theta)
64
+ }
eml_stdlib/ml/silu.eml ADDED
@@ -0,0 +1,40 @@
1
+ // silu.eml -- SiLU / Swish activation.
2
+ //
3
+ // silu(x) = x * sigmoid(x) = x / (1 + exp(-x))
4
+ //
5
+ // Same shape and chain-order class as sigmoid; the multiplication
6
+ // by x makes the activation unbounded above, which matches the
7
+ // behaviour modern transformer architectures want.
8
+
9
+ module silu;
10
+
11
+ const SILU_X_MAX: Real = 30.0
12
+
13
+ @verify(lean, theorem = "silu_at_zero_is_zero")
14
+ fn silu(x: Real) -> Real
15
+ where chain_order <= 1
16
+ requires (abs(x) < SILU_X_MAX)
17
+ ensures (result >= -1.0) // global lower bound is ~-0.278
18
+ {
19
+ x / (1.0 + exp(-x))
20
+ }
21
+
22
+ // Beta-Swish variant: x * sigmoid(beta * x).
23
+ @verify(lean, theorem = "swish_at_zero_is_zero")
24
+ fn swish(x: Real, beta: Real) -> Real
25
+ where chain_order <= 1
26
+ requires (abs(beta * x) < SILU_X_MAX)
27
+ {
28
+ x / (1.0 + exp(-beta * x))
29
+ }
30
+
31
+ // Derivative -- f'(x) = sigmoid(x) + x * sigmoid'(x)
32
+ // = sigmoid(x) * (1 + x * (1 - sigmoid(x))).
33
+ @verify(lean, theorem = "silu_derivative_at_zero_is_one_half")
34
+ fn silu_grad(x: Real) -> Real
35
+ where chain_order <= 1
36
+ requires (abs(x) < SILU_X_MAX)
37
+ {
38
+ let s = 1.0 / (1.0 + exp(-x));
39
+ s + x * s * (1.0 - s)
40
+ }
@@ -0,0 +1,87 @@
1
+ // softmax.eml -- numerically-stable softmax kernels.
2
+ //
3
+ // Softmax over an N-vector requires (a) subtracting the max for
4
+ // numerical stability and (b) reducing across the vector. EML's
5
+ // scalar-kernel surface naturally splits this into three pure
6
+ // gates that the host loop composes:
7
+ //
8
+ // softmax_shift_exp(logit, max_logit) per-element exp(x - m)
9
+ // softmax_normalize(numer, denom_sum) per-element / sum
10
+ // softmax_two_logit(a, b) closed form for N=2
11
+ //
12
+ // The FPGA allocator (Patent #14) maps the per-element gates to
13
+ // SIMD lanes and the reduction to a tree adder; cross-target
14
+ // equivalence (Patent #22) then guarantees the C / Rust / Lean
15
+ // reference matches the Verilog bit-for-bit at IEEE-754
16
+ // rounding.
17
+
18
+ module softmax;
19
+
20
+ const SOFTMAX_X_MAX: Real = 30.0
21
+
22
+ type SoftmaxNumerator = Real where chain_order <= 1
23
+ type SoftmaxValue = Real where chain_order <= 1
24
+
25
+ // Per-element exp(x - max) -- the numerically-stable softmax
26
+ // numerator. `max_logit` is the running maximum of the logit
27
+ // vector, supplied by the host (computed in a separate reduce).
28
+ // Subtracting it before exp() guarantees the largest numerator
29
+ // equals 1.0 and the smallest doesn't underflow.
30
+ @target(fpga, clock_mhz = 250, precision = float32)
31
+ @verify(lean, theorem = "softmax_numerator_bounded_by_one")
32
+ fn softmax_shift_exp(logit: Real, max_logit: Real) -> SoftmaxNumerator
33
+ where chain_order <= 1
34
+ requires (abs(logit) < SOFTMAX_X_MAX)
35
+ requires (abs(max_logit) < SOFTMAX_X_MAX)
36
+ requires (logit <= max_logit)
37
+ ensures (result >= 0.0)
38
+ ensures (result <= 1.0)
39
+ {
40
+ exp(logit - max_logit)
41
+ }
42
+
43
+ // Per-element normaliser. `denom_sum` is the sum of the shifted
44
+ // numerators; supplied by the host's reduction tree.
45
+ @target(fpga, clock_mhz = 400, precision = float32)
46
+ @verify(lean, theorem = "softmax_value_in_unit_interval")
47
+ fn softmax_normalize(numer: Real, denom_sum: Real) -> SoftmaxValue
48
+ where chain_order <= 0
49
+ requires (numer >= 0.0)
50
+ requires (denom_sum > 0.0)
51
+ requires (numer <= denom_sum)
52
+ ensures (result >= 0.0)
53
+ ensures (result <= 1.0)
54
+ {
55
+ numer / denom_sum
56
+ }
57
+
58
+ // Closed-form softmax for N=2 -- the binary-classifier head.
59
+ // Equivalent to sigmoid(a - b); useful as a sanity-check
60
+ // for the sigmoid-vs-softmax-for-binary debate. Chain order 1.
61
+ @target(fpga, clock_mhz = 250, precision = float32)
62
+ @verify(lean, theorem = "softmax_two_equals_sigmoid_diff")
63
+ fn softmax_two_logit(a: Real, b: Real) -> SoftmaxValue
64
+ where chain_order <= 1
65
+ requires (abs(a) < SOFTMAX_X_MAX)
66
+ requires (abs(b) < SOFTMAX_X_MAX)
67
+ ensures (result >= 0.0)
68
+ ensures (result <= 1.0)
69
+ {
70
+ 1.0 / (1.0 + exp(b - a))
71
+ }
72
+
73
+ // Log-sum-exp (LSE) -- stable computation of log(sum exp(x_i)).
74
+ // The host loop accumulates `running_lse` and `next_logit`
75
+ // pair-wise via this gate. Chain order 2 (ln composes through
76
+ // exp). Used as the cross-entropy denominator in transformer
77
+ // language-model heads.
78
+ @target(fpga, clock_mhz = 200, precision = float32)
79
+ @verify(lean, theorem = "log_sum_exp_pair_associative")
80
+ fn log_sum_exp_pair(a: Real, b: Real) -> Real
81
+ where chain_order <= 2
82
+ requires (abs(a) < SOFTMAX_X_MAX)
83
+ requires (abs(b) < SOFTMAX_X_MAX)
84
+ {
85
+ let m = clamp(a, b, SOFTMAX_X_MAX);
86
+ m + ln(exp(a - m) + exp(b - m))
87
+ }
@@ -0,0 +1,48 @@
1
+ // coulomb.eml -- Coulomb's law for electrostatic force / field.
2
+ //
3
+ // F = k_e * q1 * q2 / r^2
4
+ // E = k_e * q / r^2
5
+ //
6
+ // k_e = 8.9875517923e9 N*m^2/C^2 (Coulomb constant).
7
+ // Chain order 0 -- pure rational arithmetic.
8
+
9
+ module coulomb;
10
+
11
+ const COULOMB_K: Real = 8.9875517923e9
12
+ const EPS_0: Real = 8.8541878128e-12
13
+
14
+ // Force between two point charges separated by r.
15
+ @verify(lean, theorem = "coulomb_force_sign_matches_charge_product")
16
+ fn force(q1: Real, q2: Real, r: Real) -> Real
17
+ where chain_order <= 0,
18
+ domain: r > 0.0
19
+ {
20
+ COULOMB_K * q1 * q2 / (r * r)
21
+ }
22
+
23
+ // Electric field of a single point charge at distance r.
24
+ @verify(lean, theorem = "coulomb_field_sign_matches_charge")
25
+ fn field(q: Real, r: Real) -> Real
26
+ where chain_order <= 0,
27
+ domain: r > 0.0
28
+ {
29
+ COULOMB_K * q / (r * r)
30
+ }
31
+
32
+ // Potential energy of a pair of charges at separation r.
33
+ @verify(lean, theorem = "coulomb_potential_energy_sign_matches_charges")
34
+ fn potential_energy(q1: Real, q2: Real, r: Real) -> Real
35
+ where chain_order <= 0,
36
+ domain: r > 0.0
37
+ {
38
+ COULOMB_K * q1 * q2 / r
39
+ }
40
+
41
+ // Electrostatic potential of a single point charge at distance r.
42
+ @verify(lean, theorem = "coulomb_potential_sign_matches_charge")
43
+ fn potential(q: Real, r: Real) -> Real
44
+ where chain_order <= 0,
45
+ domain: r > 0.0
46
+ {
47
+ COULOMB_K * q / r
48
+ }
@@ -0,0 +1,20 @@
1
+ // damped_wave.eml -- exp * sin, the chain-2 archetype.
2
+ //
3
+ // y(t) = exp(-zeta * t) * sin(omega * t)
4
+ //
5
+ // The bedrock damped oscillation. Two transcendentals nested
6
+ // over polynomial arguments -- chain order 2. This shape
7
+ // describes a settling spring, a reverb tail, a relaxation
8
+ // curve, and the impulse response of a second-order linear
9
+ // system.
10
+
11
+ module damped_wave;
12
+
13
+ fn damped_wave(zeta: Real, omega: Real, t: Real) -> Real
14
+ where chain_order <= 2
15
+ requires (zeta >= 0.0)
16
+ requires (omega >= 0.0)
17
+ requires (t >= 0.0)
18
+ {
19
+ exp(-zeta * t) * sin(omega * t)
20
+ }
@@ -0,0 +1,45 @@
1
+ // diffusion.eml -- 1-D diffusion (heat / mass) equation snapshot.
2
+ //
3
+ // c(x, t) = (M / sqrt(4*pi*D*t)) * exp(-x^2 / (4*D*t))
4
+ //
5
+ // Closed-form Gaussian solution to the diffusion equation
6
+ // dc/dt = D * d^2c/dx^2
7
+ // for an initial impulse of mass M at the origin. Chain order 1.
8
+ // At t = 0 the solution is a delta function -- callers that need
9
+ // the impulse should use the Fick steady-state form instead.
10
+
11
+ module diffusion;
12
+
13
+ const PI: Real = 3.141592653589793
14
+ const SQRT_4_PI: Real = 3.5449077018110318
15
+
16
+ @verify(lean, theorem = "diffusion_concentration_positive_for_finite_time")
17
+ fn concentration(mass: Real, diffusivity: Real, x: Real, t: Real) -> Real
18
+ where chain_order <= 1,
19
+ domain: t > 0.0 && diffusivity > 0.0
20
+ requires (mass > 0.0)
21
+ ensures (result > 0.0)
22
+ {
23
+ let four_dt = 4.0 * diffusivity * t;
24
+ let prefactor = mass / sqrt(PI * four_dt);
25
+ prefactor * exp(-x * x / four_dt)
26
+ }
27
+
28
+ // Standard deviation of the diffusion blob at time t: sigma = sqrt(2*D*t).
29
+ @verify(lean, theorem = "diffusion_sigma_positive_for_finite_time")
30
+ fn sigma(diffusivity: Real, t: Real) -> Real
31
+ where chain_order <= 1,
32
+ domain: t > 0.0 && diffusivity > 0.0
33
+ ensures (result > 0.0)
34
+ {
35
+ sqrt(2.0 * diffusivity * t)
36
+ }
37
+
38
+ // Fick's first law: flux = -D * dc/dx (steady-state form).
39
+ @verify(lean, theorem = "fick_flux_sign_opposes_gradient")
40
+ fn fick_first_law(diffusivity: Real, gradient: Real) -> Real
41
+ where chain_order <= 0,
42
+ domain: diffusivity > 0.0
43
+ {
44
+ -diffusivity * gradient
45
+ }
@@ -0,0 +1,60 @@
1
+ // gravity.eml -- two gravity models for game physics.
2
+ //
3
+ // Newtonian inverse-square gravity is the right model for orbital
4
+ // games (Kerbal-class, space sims, asteroid simulators). Surface
5
+ // (uniform / "constant-g") gravity is the right model for platformers
6
+ // and most ground-based games where the planet is "flat" at game
7
+ // scale. Both kernels are provided so a hybrid game (rocket
8
+ // launch + planet surface) can switch.
9
+ //
10
+ // Newton: a(r) = G * M / r^2 (vector along -r-hat)
11
+ // Surface: a = -g (constant)
12
+ //
13
+ // drift_risk LOW. Sibling to projectile.eml (which uses
14
+ // surface_gravity_acceleration as input) and bounce.eml.
15
+
16
+ module gravity;
17
+
18
+ const ZERO: Real = 0.0
19
+ const ONE: Real = 1.0
20
+ const TINY: Real = 1.0e-9
21
+
22
+ const G_NEWTON: Real = 6.6743e-11 // N m^2 / kg^2
23
+ const M_EARTH: Real = 5.972e24 // kg
24
+ const R_EARTH: Real = 6.371e6 // m
25
+ const R_MIN: Real = 1.0e3 // 1 km floor (avoid singularity)
26
+ const R_MAX: Real = 1.0e12 // 1 Tm cap (outer solar system)
27
+ const M_MAX: Real = 2.0e30 // ~ solar mass cap
28
+ const G_SURFACE_MAX: Real = 100.0 // jovian-grav cap
29
+
30
+ type Accel = Real where chain_order <= 0
31
+
32
+ // Newtonian gravitational acceleration magnitude at distance r
33
+ // from a point mass M. Chain order 0 (rational).
34
+ @target(fpga, clock_mhz = 500, precision = float32)
35
+ @verify(lean, theorem = "newtonian_gravity_inverse_square")
36
+ fn newtonian_acceleration(mass: Real, r: Real) -> Accel
37
+ where chain_order <= 0
38
+ requires (mass >= ZERO)
39
+ requires (mass <= M_MAX)
40
+ requires (r >= R_MIN)
41
+ requires (r <= R_MAX)
42
+ ensures (result >= ZERO)
43
+ {
44
+ G_NEWTON * mass / (r * r + TINY)
45
+ }
46
+
47
+ // Per-frame velocity update under uniform downward gravity. Chain
48
+ // order 0. Most platformer / FPS engines use this -- the planet
49
+ // is treated as flat at game scale and `g` is a tunable.
50
+ @target(fpga, clock_mhz = 500, precision = float32)
51
+ fn surface_gravity_step(v_y: Real, g: Real, dt: Real) -> Real
52
+ where chain_order <= 0
53
+ requires (abs(v_y) <= 1.0e4)
54
+ requires (g >= ZERO)
55
+ requires (g <= G_SURFACE_MAX)
56
+ requires (dt >= 1.0e-5)
57
+ requires (dt <= 0.1)
58
+ {
59
+ v_y - g * dt
60
+ }
@@ -0,0 +1,56 @@
1
+ // hooke.eml -- Hooke's law for springs and elastic media.
2
+ //
3
+ // F = -k * x (restoring force)
4
+ // U = (1/2) * k * x^2 (stored energy)
5
+ //
6
+ // Linear elastic regime only; for stress/strain Mises-yield-style
7
+ // extensions see the construction industry kernels.
8
+
9
+ module hooke;
10
+
11
+ @verify(lean, theorem = "hooke_force_sign_opposes_displacement")
12
+ fn force(stiffness: Real, displacement: Real) -> Real
13
+ where chain_order <= 0,
14
+ domain: stiffness > 0.0
15
+ {
16
+ -stiffness * displacement
17
+ }
18
+
19
+ @verify(lean, theorem = "hooke_energy_nonneg")
20
+ fn potential_energy(stiffness: Real, displacement: Real) -> Real
21
+ where chain_order <= 0,
22
+ domain: stiffness > 0.0
23
+ ensures (result >= 0.0)
24
+ {
25
+ 0.5 * stiffness * displacement * displacement
26
+ }
27
+
28
+ // Series stiffness of two springs.
29
+ @verify(lean, theorem = "hooke_series_stiffness_positive")
30
+ fn series_stiffness(k1: Real, k2: Real) -> Real
31
+ where chain_order <= 0,
32
+ domain: k1 > 0.0 && k2 > 0.0
33
+ ensures (result > 0.0)
34
+ {
35
+ (k1 * k2) / (k1 + k2)
36
+ }
37
+
38
+ // Parallel stiffness of two springs.
39
+ @verify(lean, theorem = "hooke_parallel_stiffness_positive")
40
+ fn parallel_stiffness(k1: Real, k2: Real) -> Real
41
+ where chain_order <= 0,
42
+ domain: k1 > 0.0 && k2 > 0.0
43
+ ensures (result > 0.0)
44
+ {
45
+ k1 + k2
46
+ }
47
+
48
+ // Natural angular frequency of a mass on a spring: omega = sqrt(k/m).
49
+ @verify(lean, theorem = "hooke_omega_positive")
50
+ fn natural_frequency(stiffness: Real, mass: Real) -> Real
51
+ where chain_order <= 1,
52
+ domain: stiffness > 0.0 && mass > 0.0
53
+ ensures (result > 0.0)
54
+ {
55
+ sqrt(stiffness / mass)
56
+ }
@@ -0,0 +1,57 @@
1
+ // navier_stokes_1d.eml -- 1-D incompressible Navier-Stokes step.
2
+ //
3
+ // Simplified to the momentum-only form on a 1-D pipe:
4
+ //
5
+ // du/dt + u * du/dx = -(1/rho) * dp/dx + nu * d^2u/dx^2
6
+ //
7
+ // This module ships the right-hand-side terms separately so users
8
+ // can compose explicit, implicit, or semi-Lagrangian time steppers
9
+ // downstream. Chain order 0 throughout.
10
+
11
+ module navier_stokes_1d;
12
+
13
+ // Pressure-gradient acceleration term.
14
+ @verify(lean, theorem = "ns1d_pressure_term_sign_opposes_gradient")
15
+ fn pressure_term(density: Real, dp_dx: Real) -> Real
16
+ where chain_order <= 0,
17
+ domain: density > 0.0
18
+ {
19
+ -dp_dx / density
20
+ }
21
+
22
+ // Viscous (diffusive) term.
23
+ @verify(lean, theorem = "ns1d_viscous_term_proportional_to_d2u_dx2")
24
+ fn viscous_term(viscosity: Real, d2u_dx2: Real) -> Real
25
+ where chain_order <= 0,
26
+ domain: viscosity >= 0.0
27
+ {
28
+ viscosity * d2u_dx2
29
+ }
30
+
31
+ // Convective (advective) term.
32
+ @verify(lean, theorem = "ns1d_convective_term_signed")
33
+ fn convective_term(u: Real, du_dx: Real) -> Real
34
+ where chain_order <= 0
35
+ {
36
+ -u * du_dx
37
+ }
38
+
39
+ // Full RHS of the momentum equation.
40
+ fn rhs(u: Real, du_dx: Real, d2u_dx2: Real,
41
+ density: Real, dp_dx: Real, viscosity: Real) -> Real
42
+ where chain_order <= 0,
43
+ domain: density > 0.0 && viscosity >= 0.0
44
+ {
45
+ -u * du_dx - dp_dx / density + viscosity * d2u_dx2
46
+ }
47
+
48
+ // Reynolds number: Re = u * L / nu. Determines laminar/turbulent
49
+ // regime; useful invariant for caller's adaptive time step.
50
+ @verify(lean, theorem = "reynolds_nonneg")
51
+ fn reynolds(velocity: Real, length: Real, viscosity: Real) -> Real
52
+ where chain_order <= 0,
53
+ domain: viscosity > 0.0
54
+ requires (length > 0.0)
55
+ {
56
+ velocity * length / viscosity
57
+ }
@@ -0,0 +1,77 @@
1
+ // planck_radiation.eml -- Planck blackbody spectral radiance.
2
+ //
3
+ // Planck's law for the spectral radiance of a blackbody at
4
+ // temperature T:
5
+ //
6
+ // B(lambda, T) = (2*h*c^2 / lambda^5) * 1 / (exp(h*c/(lambda*k*T)) - 1)
7
+ //
8
+ // where h is Planck's constant, c is the speed of light, k is
9
+ // Boltzmann's constant. Used in radiometry, IR remote sensing,
10
+ // astrophysics, and thermal-imaging calibration.
11
+ //
12
+ // Chain order 1 (single exp). Companion of stefan_boltzmann.eml
13
+ // (which is the integral of B over all wavelengths).
14
+
15
+ module planck_radiation;
16
+
17
+ const HC: Real = 1.986445857e-25 // h*c, J*m
18
+ const HC_OVER_K: Real = 0.014387768775039337 // h*c/k, m*K
19
+ const TWO_HC2: Real = 1.191042869e-16 // 2*h*c^2, W*m^4*sr^-1
20
+ const LAMBDA_MIN: Real = 1.0e-9 // 1 nm UV
21
+ const LAMBDA_MAX: Real = 1.0e-3 // 1 mm far-IR
22
+ const T_MIN: Real = 1.0
23
+ const T_MAX: Real = 1.0e5
24
+
25
+ type SpectralRadiance = Real where chain_order <= 1
26
+
27
+ @target(fpga, clock_mhz = 100, precision = float64)
28
+ @verify(lean, theorem = "planck_radiance_increases_with_temperature")
29
+ fn spectral_radiance(wavelength_m: Real, temperature_k: Real) -> SpectralRadiance
30
+ where chain_order <= 1
31
+ requires (wavelength_m >= LAMBDA_MIN)
32
+ requires (wavelength_m <= LAMBDA_MAX)
33
+ requires (temperature_k >= T_MIN)
34
+ requires (temperature_k <= T_MAX)
35
+ ensures (result >= 0.0)
36
+ {
37
+ let lambda5 = wavelength_m * wavelength_m * wavelength_m
38
+ * wavelength_m * wavelength_m;
39
+ let prefactor = TWO_HC2 / lambda5;
40
+ let exponent = HC_OVER_K / (wavelength_m * temperature_k);
41
+ prefactor / (exp(exponent) - 1.0)
42
+ }
43
+
44
+ // Wien displacement: lambda_max * T = b. Reused from
45
+ // stefan_boltzmann; here for completeness in this physics
46
+ // kernel pair.
47
+ @target(fpga, clock_mhz = 500, precision = float64)
48
+ @verify(lean, theorem = "wien_constant_inversely_proportional_to_T")
49
+ fn wien_lambda_max(temperature_k: Real) -> Real
50
+ where chain_order <= 0
51
+ requires (temperature_k >= T_MIN)
52
+ requires (temperature_k <= T_MAX)
53
+ ensures (result >= 0.0)
54
+ {
55
+ 0.002897771955 / temperature_k
56
+ }
57
+
58
+ // Rayleigh-Jeans long-wavelength approximation:
59
+ // B(lambda, T) ~ 2*c*k*T / lambda^4
60
+ // Valid when h*c << lambda*k*T (radio / mm-wave radiometry).
61
+ // Chain order 0 (no exp).
62
+ @target(fpga, clock_mhz = 500, precision = float64)
63
+ @verify(lean, theorem = "rayleigh_jeans_underestimates_at_short_wavelength")
64
+ fn rayleigh_jeans_radiance(
65
+ wavelength_m: Real,
66
+ temperature_k: Real,
67
+ ) -> SpectralRadiance
68
+ where chain_order <= 0
69
+ requires (wavelength_m >= LAMBDA_MIN)
70
+ requires (wavelength_m <= LAMBDA_MAX)
71
+ requires (temperature_k >= T_MIN)
72
+ requires (temperature_k <= T_MAX)
73
+ ensures (result >= 0.0)
74
+ {
75
+ let lambda4 = wavelength_m * wavelength_m * wavelength_m * wavelength_m;
76
+ 2.0 * 299792458.0 * 1.380649e-23 * temperature_k / lambda4
77
+ }
@@ -0,0 +1,75 @@
1
+ // stefan_boltzmann.eml -- blackbody radiative flux.
2
+ //
3
+ // The Stefan-Boltzmann law:
4
+ //
5
+ // j = epsilon * sigma * T^4
6
+ //
7
+ // where:
8
+ // sigma = 5.670374419e-8 W m^-2 K^-4 (Stefan-Boltzmann constant)
9
+ // epsilon = surface emissivity (0..1)
10
+ // T = absolute temperature (K)
11
+ //
12
+ // Chain order 1 (single pow). Used in radiative-balance climate
13
+ // models, spacecraft thermal control, IR-camera calibration,
14
+ // and as the upper-bound term in atmospheric energy budgets.
15
+
16
+ module stefan_boltzmann;
17
+
18
+ const SIGMA_SB: Real = 5.670374419e-8
19
+ const T_MIN: Real = 1.0
20
+ const T_MAX: Real = 6000.0
21
+ const EPS_MIN: Real = 0.0
22
+ const EPS_MAX: Real = 1.0
23
+
24
+ type RadiativeFlux = Real where chain_order <= 1
25
+
26
+ @target(fpga, clock_mhz = 200, precision = float64)
27
+ @verify(lean, theorem = "stefan_boltzmann_monotone_in_T")
28
+ fn radiative_flux(emissivity: Real, temperature_k: Real) -> RadiativeFlux
29
+ where chain_order <= 1
30
+ requires (emissivity >= EPS_MIN)
31
+ requires (emissivity <= EPS_MAX)
32
+ requires (temperature_k >= T_MIN)
33
+ requires (temperature_k <= T_MAX)
34
+ ensures (result >= 0.0)
35
+ {
36
+ emissivity * SIGMA_SB * pow(temperature_k, 4.0)
37
+ }
38
+
39
+ // Net radiative exchange between a surface at T_s and an
40
+ // environment at T_env, both treated as graybodies. Chain
41
+ // order 1 (two pow calls but the same exponent -- SuperBEST
42
+ // can fuse into a single pow on the difference of fourth
43
+ // powers if it sees the pattern).
44
+ @target(fpga, clock_mhz = 200, precision = float64)
45
+ @verify(lean, theorem = "net_exchange_zero_at_equilibrium")
46
+ fn net_exchange(
47
+ emissivity: Real,
48
+ surface_t: Real,
49
+ ambient_t: Real,
50
+ ) -> RadiativeFlux
51
+ where chain_order <= 1
52
+ requires (emissivity >= EPS_MIN)
53
+ requires (emissivity <= EPS_MAX)
54
+ requires (surface_t >= T_MIN)
55
+ requires (surface_t <= T_MAX)
56
+ requires (ambient_t >= T_MIN)
57
+ requires (ambient_t <= T_MAX)
58
+ {
59
+ emissivity * SIGMA_SB * (pow(surface_t, 4.0) - pow(ambient_t, 4.0))
60
+ }
61
+
62
+ // Wien's displacement law -- peak wavelength of a blackbody
63
+ // at temperature T. lambda_max = b / T with b ≈ 2.898e-3 m·K.
64
+ // Chain order 0 (pure division). Companion to Stefan-Boltzmann
65
+ // for diagnosing the spectral peak from surface temperature.
66
+ @target(fpga, clock_mhz = 500, precision = float64)
67
+ @verify(lean, theorem = "wien_inversely_proportional_to_T")
68
+ fn wien_peak_wavelength(temperature_k: Real) -> Real
69
+ where chain_order <= 0
70
+ requires (temperature_k >= T_MIN)
71
+ requires (temperature_k <= T_MAX)
72
+ ensures (result > 0.0)
73
+ {
74
+ 0.002897771955 / temperature_k
75
+ }
@@ -0,0 +1,52 @@
1
+ // wave_propagation.eml -- 1-D linear wave equation snapshot.
2
+ //
3
+ // u(x, t) = A * sin(k*x - omega*t + phi)
4
+ //
5
+ // k = 2*pi / lambda, omega = 2*pi*f, c = omega / k.
6
+ //
7
+ // Chain order 1 -- one transcendental, linear argument. Closed
8
+ // boundary identities: u(x, 0) at phi=0 equals A*sin(k*x), and the
9
+ // wave speed is the constant ratio omega/k.
10
+
11
+ module wave_propagation;
12
+
13
+ const TWO_PI: Real = 6.283185307179586
14
+
15
+ @verify(lean, theorem = "wave_amplitude_in_unit_interval")
16
+ fn wave(amplitude: Real, k: Real, omega: Real, phi: Real,
17
+ x: Real, t: Real) -> Real
18
+ where chain_order <= 1
19
+ ensures (abs(result) <= abs(amplitude))
20
+ {
21
+ amplitude * sin(k * x - omega * t + phi)
22
+ }
23
+
24
+ // Wavelength from wavenumber k = 2*pi / lambda.
25
+ @verify(lean, theorem = "wavelength_positive")
26
+ fn wavelength(k: Real) -> Real
27
+ where chain_order <= 0,
28
+ domain: k > 0.0
29
+ ensures (result > 0.0)
30
+ {
31
+ TWO_PI / k
32
+ }
33
+
34
+ // Frequency from angular frequency omega = 2*pi * f.
35
+ @verify(lean, theorem = "frequency_nonneg")
36
+ fn frequency(omega: Real) -> Real
37
+ where chain_order <= 0,
38
+ domain: omega >= 0.0
39
+ ensures (result >= 0.0)
40
+ {
41
+ omega / TWO_PI
42
+ }
43
+
44
+ // Phase velocity c = omega / k.
45
+ @verify(lean, theorem = "phase_velocity_positive")
46
+ fn phase_velocity(omega: Real, k: Real) -> Real
47
+ where chain_order <= 0,
48
+ domain: k > 0.0 && omega > 0.0
49
+ ensures (result > 0.0)
50
+ {
51
+ omega / k
52
+ }