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,41 @@
1
+ // pbr_diffuse.eml -- Lambertian diffuse shading.
2
+ //
3
+ // L = albedo * max(0, n · l) / π
4
+ //
5
+ // The 1/π factor is the energy-conservation normalisation; many
6
+ // real-time shaders fold it into the light intensity instead.
7
+ // Both forms are provided.
8
+
9
+ module pbr_diffuse;
10
+
11
+ const PI: Real = 3.141592653589793
12
+ const INV_PI: Real = 0.31830988618379
13
+
14
+ @verify(lean, theorem = "lambert_in_unit_interval")
15
+ fn lambert(n_dot_l: Real) -> Real
16
+ where chain_order <= 0
17
+ ensures (result >= 0.0)
18
+ ensures (result <= 1.0)
19
+ {
20
+ clamp(n_dot_l, 0.0, 1.0)
21
+ }
22
+
23
+ @verify(lean, theorem = "lambert_normalised_nonneg")
24
+ fn lambert_normalised(n_dot_l: Real) -> Real
25
+ where chain_order <= 0
26
+ ensures (result >= 0.0)
27
+ {
28
+ clamp(n_dot_l, 0.0, 1.0) * INV_PI
29
+ }
30
+
31
+ // Half-Lambert (Valve trick): wrap-around term for soft skin /
32
+ // foliage shading. Maps n·l ∈ [-1, 1] to [0.25, 1].
33
+ @verify(lean, theorem = "half_lambert_in_unit_interval")
34
+ fn half_lambert(n_dot_l: Real) -> Real
35
+ where chain_order <= 0
36
+ ensures (result >= 0.0)
37
+ ensures (result <= 1.0)
38
+ {
39
+ let s: Real = 0.5 * n_dot_l + 0.5;
40
+ s * s
41
+ }
@@ -0,0 +1,75 @@
1
+ // pbr_specular.eml -- Cook-Torrance microfacet specular BRDF.
2
+ //
3
+ // f_spec = (D * F * G) / (4 * (n·v) * (n·l))
4
+ //
5
+ // Where:
6
+ // D = GGX (Trowbridge-Reitz) normal distribution
7
+ // F = Schlick Fresnel
8
+ // G = Smith geometry term (height-correlated GGX visibility)
9
+ //
10
+ // All sub-terms are bounded ∈ [0, 1]; the caller multiplies by the
11
+ // light radiance and integrates over the hemisphere.
12
+
13
+ module pbr_specular;
14
+
15
+ use stdlib::gaming::shading::fresnel;
16
+
17
+ const PI: Real = 3.141592653589793
18
+
19
+ // GGX distribution.
20
+ @verify(lean, theorem = "ggx_in_unit_interval_for_unit_alpha")
21
+ fn d_ggx(n_dot_h: Real, alpha: Real) -> Real
22
+ where chain_order <= 0,
23
+ domain: alpha > 0.0
24
+ ensures (result >= 0.0)
25
+ {
26
+ let a2: Real = alpha * alpha;
27
+ let nh2: Real = clamp(n_dot_h, 0.0, 1.0) * clamp(n_dot_h, 0.0, 1.0);
28
+ let denom: Real = nh2 * (a2 - 1.0) + 1.0;
29
+ a2 / (PI * denom * denom + 1.0e-7)
30
+ }
31
+
32
+ // Smith geometry term, height-correlated GGX visibility.
33
+ @verify(lean, theorem = "smith_visibility_in_unit_interval")
34
+ fn v_smith(n_dot_v: Real, n_dot_l: Real, alpha: Real) -> Real
35
+ where chain_order <= 1,
36
+ domain: alpha > 0.0
37
+ ensures (result >= 0.0)
38
+ {
39
+ let a2: Real = alpha * alpha;
40
+ let nv: Real = clamp(n_dot_v, 1.0e-4, 1.0);
41
+ let nl: Real = clamp(n_dot_l, 1.0e-4, 1.0);
42
+ let lambda_v: Real = nl * sqrt(nv * nv * (1.0 - a2) + a2);
43
+ let lambda_l: Real = nv * sqrt(nl * nl * (1.0 - a2) + a2);
44
+ 0.5 / (lambda_v + lambda_l + 1.0e-7)
45
+ }
46
+
47
+ // Composite Cook-Torrance specular.
48
+ @verify(lean, theorem = "cook_torrance_nonneg")
49
+ fn specular(n_dot_l: Real, n_dot_v: Real, n_dot_h: Real,
50
+ v_dot_h: Real, f0: Real, alpha: Real) -> Real
51
+ where chain_order <= 1,
52
+ domain: alpha > 0.0
53
+ requires (f0 >= 0.0)
54
+ requires (f0 <= 1.0)
55
+ ensures (result >= 0.0)
56
+ {
57
+ let d: Real = d_ggx(n_dot_h, alpha);
58
+ let f: Real = fresnel::schlick(f0, v_dot_h);
59
+ let v: Real = v_smith(n_dot_v, n_dot_l, alpha);
60
+ d * f * v
61
+ }
62
+
63
+ // Roughness → α = roughness² is the standard remap; clamped away
64
+ // from 0 to keep D_GGX well-defined.
65
+ @verify(lean, theorem = "roughness_to_alpha_in_band")
66
+ fn roughness_to_alpha(roughness: Real) -> Real
67
+ where chain_order <= 0
68
+ requires (roughness >= 0.0)
69
+ requires (roughness <= 1.0)
70
+ ensures (result >= 1.0e-4)
71
+ ensures (result <= 1.0)
72
+ {
73
+ let r: Real = clamp(roughness, 0.0, 1.0);
74
+ clamp(r * r, 1.0e-4, 1.0)
75
+ }
@@ -0,0 +1,52 @@
1
+ // subsurface.eml -- Christensen-Burley subsurface scattering approx.
2
+ //
3
+ // For real-time skin / wax / leaves: light entering through a thin
4
+ // region scatters and emerges in a halo of the material's albedo.
5
+ // Burley's approximation is a sum of two exponentials in distance,
6
+ // integrated against the surface normal:
7
+ //
8
+ // sss(n, l, k_back) = k_back + (1 - k_back) * max(0, n · l)
9
+ //
10
+ // Plus a wrap-around term for the back-lit hemisphere. Chain order 1.
11
+
12
+ module subsurface;
13
+
14
+ @verify(lean, theorem = "sss_wrap_in_unit_interval")
15
+ fn wrap(n_dot_l: Real, wrap_amount: Real) -> Real
16
+ where chain_order <= 0
17
+ requires (wrap_amount >= 0.0)
18
+ requires (wrap_amount <= 1.0)
19
+ ensures (result >= 0.0)
20
+ ensures (result <= 1.0)
21
+ {
22
+ let s: Real = (n_dot_l + wrap_amount) / (1.0 + wrap_amount);
23
+ clamp(s, 0.0, 1.0)
24
+ }
25
+
26
+ // Burley back-scatter term: (l ∙ -v + 1) raised to a hardness.
27
+ @verify(lean, theorem = "sss_back_in_unit_interval")
28
+ fn back_scatter(l_dot_neg_v: Real, hardness: Real) -> Real
29
+ where chain_order <= 1,
30
+ domain: hardness >= 0.0
31
+ ensures (result >= 0.0)
32
+ ensures (result <= 1.0)
33
+ {
34
+ let s: Real = clamp(0.5 * l_dot_neg_v + 0.5, 0.0, 1.0);
35
+ pow(s, hardness)
36
+ }
37
+
38
+ // Composite SSS contribution. albedo handled by caller.
39
+ @verify(lean, theorem = "sss_total_nonneg")
40
+ fn sss_total(n_dot_l: Real, l_dot_neg_v: Real,
41
+ wrap_amount: Real, hardness: Real,
42
+ back_strength: Real) -> Real
43
+ where chain_order <= 1,
44
+ domain: back_strength >= 0.0
45
+ requires (wrap_amount >= 0.0 && wrap_amount <= 1.0)
46
+ requires (hardness >= 0.0)
47
+ ensures (result >= 0.0)
48
+ {
49
+ let lit: Real = wrap(n_dot_l, wrap_amount);
50
+ let back: Real = back_scatter(l_dot_neg_v, hardness);
51
+ lit + back_strength * back
52
+ }
@@ -0,0 +1,30 @@
1
+ // toon.eml -- step-based cel shading.
2
+ //
3
+ // Banded diffuse: take n·l, quantise into K levels.
4
+ // Output ∈ [0, 1].
5
+
6
+ module toon;
7
+
8
+ @verify(lean, theorem = "toon_in_unit_interval")
9
+ fn cel_diffuse(n_dot_l: Real, levels: Real) -> Real
10
+ where chain_order <= 0,
11
+ domain: levels >= 1.0
12
+ ensures (result >= 0.0)
13
+ ensures (result <= 1.0)
14
+ {
15
+ let v: Real = clamp(n_dot_l, 0.0, 1.0);
16
+ let q: Real = floor(v * levels) / levels;
17
+ clamp(q, 0.0, 1.0)
18
+ }
19
+
20
+ // Rim-light for outline emphasis: high near grazing angles.
21
+ @verify(lean, theorem = "toon_rim_in_unit_interval")
22
+ fn rim_light(n_dot_v: Real, rim_power: Real) -> Real
23
+ where chain_order <= 1,
24
+ domain: rim_power >= 0.0
25
+ ensures (result >= 0.0)
26
+ ensures (result <= 1.0)
27
+ {
28
+ let edge: Real = clamp(1.0 - n_dot_v, 0.0, 1.0);
29
+ pow(edge, rim_power)
30
+ }
@@ -0,0 +1,41 @@
1
+ // biome_select.eml -- temperature × moisture biome classification.
2
+ //
3
+ // Whittaker's biome diagram: each biome is a region of
4
+ // (temperature, moisture) space. Returns an integer biome id ∈
5
+ // [0, 7]:
6
+ //
7
+ // 0 = tundra (cold, dry)
8
+ // 1 = boreal (cold, wet)
9
+ // 2 = grassland (temperate, dry)
10
+ // 3 = temperate_forest (temperate, mid)
11
+ // 4 = rainforest (temperate/hot, wet)
12
+ // 5 = desert (hot, dry)
13
+ // 6 = savanna (hot, mid)
14
+ // 7 = tropical_dry (hot, very dry)
15
+ //
16
+ // Inputs in [0, 1]. Pure piecewise.
17
+
18
+ module biome_select;
19
+
20
+ @verify(lean, theorem = "biome_id_in_band")
21
+ fn biome_id(temperature: Real, moisture: Real) -> Real
22
+ where chain_order <= 0
23
+ requires (temperature >= 0.0)
24
+ requires (temperature <= 1.0)
25
+ requires (moisture >= 0.0)
26
+ requires (moisture <= 1.0)
27
+ ensures (result >= 0.0)
28
+ ensures (result <= 7.0)
29
+ {
30
+ if temperature < 0.30 {
31
+ if moisture < 0.30 { 0.0 } else { 1.0 } // tundra / boreal
32
+ } else if temperature < 0.65 {
33
+ if moisture < 0.30 { 2.0 } // grassland
34
+ else if moisture < 0.65 { 3.0 } // temperate_forest
35
+ else { 4.0 } // rainforest
36
+ } else {
37
+ if moisture < 0.20 { 5.0 } // desert
38
+ else if moisture < 0.55 { 6.0 } // savanna
39
+ else { 4.0 } // tropical rainforest
40
+ }
41
+ }
@@ -0,0 +1,35 @@
1
+ // cliff_detect.eml -- gradient-magnitude cliff detection.
2
+ //
3
+ // Given a heightmap sampled at four neighbours of a centre point,
4
+ // the gradient magnitude is the slope. If it exceeds the threshold
5
+ // the cell is "cliff" (1.0); below, "non-cliff" (0.0).
6
+ //
7
+ // gradient_magnitude = sqrt((dh/dx)² + (dh/dy)²)
8
+ // is_cliff = gradient_magnitude > threshold
9
+
10
+ module cliff_detect;
11
+
12
+ @verify(lean, theorem = "cliff_gradient_magnitude_nonneg")
13
+ fn gradient_magnitude(h_left: Real, h_right: Real,
14
+ h_down: Real, h_up: Real, dx_m: Real) -> Real
15
+ where chain_order <= 1,
16
+ domain: dx_m > 0.0
17
+ ensures (result >= 0.0)
18
+ {
19
+ let dhx: Real = (h_right - h_left) / (2.0 * dx_m);
20
+ let dhy: Real = (h_up - h_down) / (2.0 * dx_m);
21
+ sqrt(dhx * dhx + dhy * dhy)
22
+ }
23
+
24
+ @verify(lean, theorem = "cliff_classification_in_zero_one")
25
+ fn is_cliff(h_left: Real, h_right: Real,
26
+ h_down: Real, h_up: Real, dx_m: Real,
27
+ slope_threshold: Real) -> Real
28
+ where chain_order <= 1,
29
+ domain: dx_m > 0.0 && slope_threshold >= 0.0
30
+ ensures (result >= 0.0)
31
+ ensures (result <= 1.0)
32
+ {
33
+ let mag: Real = gradient_magnitude(h_left, h_right, h_down, h_up, dx_m);
34
+ if mag > slope_threshold { 1.0 } else { 0.0 }
35
+ }
@@ -0,0 +1,57 @@
1
+ // erosion_hydraulic.eml -- water flow + sediment transport step.
2
+ //
3
+ // Per cell: water arrives, picks up some sediment (capacity =
4
+ // flow_speed * sediment_capacity), then flows to the lowest
5
+ // neighbour. Excess sediment beyond capacity deposits.
6
+ //
7
+ // The full sim iterates this on a grid; this kernel is one cell's
8
+ // per-step state update.
9
+
10
+ module erosion_hydraulic;
11
+
12
+ @verify(lean, theorem = "sediment_capacity_nonneg")
13
+ fn capacity(flow_speed: Real, sediment_capacity_coeff: Real) -> Real
14
+ where chain_order <= 0,
15
+ domain: flow_speed >= 0.0 && sediment_capacity_coeff >= 0.0
16
+ ensures (result >= 0.0)
17
+ {
18
+ flow_speed * sediment_capacity_coeff
19
+ }
20
+
21
+ // Erosion: how much new sediment the water lifts this step.
22
+ // eroded = (capacity - sediment) * erosion_rate (when capacity > sediment)
23
+ @verify(lean, theorem = "erosion_step_nonneg")
24
+ fn eroded_amount(sediment: Real, capacity: Real, erosion_rate: Real) -> Real
25
+ where chain_order <= 0,
26
+ domain: erosion_rate >= 0.0
27
+ requires (sediment >= 0.0)
28
+ requires (capacity >= 0.0)
29
+ ensures (result >= 0.0)
30
+ {
31
+ clamp((capacity - sediment) * erosion_rate, 0.0, 1.0e6)
32
+ }
33
+
34
+ // Deposition: when the water slows or sediment > capacity, drop the
35
+ // excess back to the terrain.
36
+ @verify(lean, theorem = "deposition_step_nonneg")
37
+ fn deposited_amount(sediment: Real, capacity: Real, deposition_rate: Real) -> Real
38
+ where chain_order <= 0,
39
+ domain: deposition_rate >= 0.0
40
+ requires (sediment >= 0.0)
41
+ requires (capacity >= 0.0)
42
+ ensures (result >= 0.0)
43
+ {
44
+ clamp((sediment - capacity) * deposition_rate, 0.0, 1.0e6)
45
+ }
46
+
47
+ // Water-volume update with evaporation.
48
+ @verify(lean, theorem = "water_evaporation_in_band")
49
+ fn updated_water(water: Real, evap_rate: Real, dt: Real) -> Real
50
+ where chain_order <= 0,
51
+ domain: evap_rate >= 0.0 && dt >= 0.0
52
+ requires (water >= 0.0)
53
+ ensures (result >= 0.0)
54
+ ensures (result <= water)
55
+ {
56
+ clamp(water * (1.0 - evap_rate * dt), 0.0, water)
57
+ }
@@ -0,0 +1,44 @@
1
+ // erosion_thermal.eml -- talus-angle thermal erosion step.
2
+ //
3
+ // Per cell: if the slope to the lowest neighbour exceeds the talus
4
+ // angle, transfer some material from this cell to the neighbour.
5
+ //
6
+ // delta = max(0, dh - talus_threshold) * fraction
7
+ //
8
+ // The full simulation iterates this for many cells; the kernel
9
+ // here is one (cell, neighbour) update.
10
+
11
+ module erosion_thermal;
12
+
13
+ @verify(lean, theorem = "thermal_step_signed_balance")
14
+ fn material_transfer(h_self: Real, h_neighbour: Real,
15
+ talus_threshold: Real, fraction: Real) -> Real
16
+ where chain_order <= 0,
17
+ domain: talus_threshold >= 0.0
18
+ requires (fraction >= 0.0)
19
+ requires (fraction <= 1.0)
20
+ ensures (result >= 0.0)
21
+ {
22
+ let dh: Real = h_self - h_neighbour;
23
+ let excess: Real = clamp(dh - talus_threshold, 0.0, 1.0e6);
24
+ excess * fraction
25
+ }
26
+
27
+ // Apply transfer to two cells: returns the new self height.
28
+ @verify(lean, theorem = "thermal_apply_self_decreases")
29
+ fn apply_self(h_self: Real, transfer: Real) -> Real
30
+ where chain_order <= 0
31
+ requires (transfer >= 0.0)
32
+ ensures (result <= h_self)
33
+ {
34
+ h_self - transfer
35
+ }
36
+
37
+ @verify(lean, theorem = "thermal_apply_neighbour_increases")
38
+ fn apply_neighbour(h_neighbour: Real, transfer: Real) -> Real
39
+ where chain_order <= 0
40
+ requires (transfer >= 0.0)
41
+ ensures (result >= h_neighbour)
42
+ {
43
+ h_neighbour + transfer
44
+ }
@@ -0,0 +1,33 @@
1
+ // heightmap.eml -- FBM-driven heightmap generation.
2
+ //
3
+ // h(x, y) = fbm(x * scale, y * scale) * amplitude + base_elevation
4
+ //
5
+ // Output is a scalar height in metres. Caller passes the FBM scale
6
+ // (lower = larger features) and amplitude (peak-to-trough range).
7
+
8
+ module heightmap;
9
+
10
+ use stdlib::gaming::noise::fbm;
11
+
12
+ @verify(lean, theorem = "heightmap_in_band")
13
+ fn height(x: Real, y: Real, scale: Real,
14
+ amplitude: Real, base_elevation: Real) -> Real
15
+ where chain_order <= 1,
16
+ domain: scale > 0.0 && amplitude >= 0.0
17
+ ensures (result >= base_elevation - amplitude)
18
+ ensures (result <= base_elevation + amplitude)
19
+ {
20
+ base_elevation + amplitude * fbm::fbm2_default(x * scale, y * scale)
21
+ }
22
+
23
+ // Ridged variant: 1 - |fbm| produces sharp ridges (mountains).
24
+ @verify(lean, theorem = "ridged_heightmap_in_band")
25
+ fn ridged_height(x: Real, y: Real, scale: Real,
26
+ amplitude: Real, base_elevation: Real) -> Real
27
+ where chain_order <= 1,
28
+ domain: scale > 0.0 && amplitude >= 0.0
29
+ ensures (result >= base_elevation)
30
+ ensures (result <= base_elevation + amplitude)
31
+ {
32
+ base_elevation + amplitude * (1.0 - abs(fbm::fbm2_default(x * scale, y * scale)))
33
+ }
@@ -0,0 +1,27 @@
1
+ // brick.eml -- modular brick grid with mortar gap + per-row offset.
2
+ //
3
+ // Returns 1.0 inside a brick, 0.0 inside the mortar joint. The
4
+ // offset alternates each row, which is the visual signature of
5
+ // running-bond brickwork.
6
+
7
+ module brick;
8
+
9
+ @verify(lean, theorem = "brick_pattern_in_unit_interval")
10
+ fn pattern(u: Real, v: Real, brick_w: Real, brick_h: Real,
11
+ mortar_thickness: Real) -> Real
12
+ where chain_order <= 0,
13
+ domain: brick_w > 0.0 && brick_h > 0.0 && mortar_thickness >= 0.0
14
+ ensures (result >= 0.0)
15
+ ensures (result <= 1.0)
16
+ {
17
+ let row: Real = floor(v / brick_h);
18
+ let row_offset: Real = if (row - 2.0 * floor(row * 0.5)) < 0.5 { 0.0 } else { brick_w * 0.5 };
19
+ let lx: Real = u + row_offset;
20
+ let frac_u: Real = lx / brick_w - floor(lx / brick_w);
21
+ let frac_v: Real = v / brick_h - floor(v / brick_h);
22
+ let edge_u: Real = mortar_thickness / brick_w;
23
+ let edge_v: Real = mortar_thickness / brick_h;
24
+ let in_brick_u: Real = if frac_u > edge_u && frac_u < 1.0 - edge_u { 1.0 } else { 0.0 };
25
+ let in_brick_v: Real = if frac_v > edge_v && frac_v < 1.0 - edge_v { 1.0 } else { 0.0 };
26
+ in_brick_u * in_brick_v
27
+ }
@@ -0,0 +1,25 @@
1
+ // caustics.eml -- refracted-light interference pattern.
2
+ //
3
+ // Cheap caustics for pool / sea-floor effects: two perpendicular
4
+ // sine waves perturbed by Perlin noise, multiplied. Result ∈ [0, 1].
5
+
6
+ module caustics;
7
+
8
+ use stdlib::gaming::noise::perlin_2d;
9
+
10
+ const PI: Real = 3.141592653589793
11
+
12
+ @verify(lean, theorem = "caustics_in_unit_interval")
13
+ fn intensity(x: Real, y: Real, time_s: Real, scale: Real) -> Real
14
+ where chain_order <= 1,
15
+ domain: scale > 0.0
16
+ ensures (result >= 0.0)
17
+ ensures (result <= 1.0)
18
+ {
19
+ let n: Real = perlin_2d::perlin2(x * 0.5, y * 0.5);
20
+ let s_a: Real = sin(2.0 * PI * scale * (x + 0.3 * n) + time_s * 1.3);
21
+ let s_b: Real = sin(2.0 * PI * scale * (y - 0.3 * n) + time_s * 1.7);
22
+ let raw: Real = s_a * s_b;
23
+ let highlit: Real = raw * raw;
24
+ clamp(highlit, 0.0, 1.0)
25
+ }
@@ -0,0 +1,27 @@
1
+ // checkerboard.eml -- canonical checkerboard pattern.
2
+ //
3
+ // checker(x, y) = mod(floor(x) + floor(y), 2)
4
+ //
5
+ // Returns 0.0 or 1.0 — caller maps to two colours. Chain order 0.
6
+
7
+ module checkerboard;
8
+
9
+ @verify(lean, theorem = "checker_returns_zero_or_one")
10
+ fn checker(x: Real, y: Real) -> Real
11
+ where chain_order <= 0
12
+ ensures (result == 0.0 || result == 1.0)
13
+ {
14
+ let s: Real = floor(x) + floor(y);
15
+ s - 2.0 * floor(s * 0.5)
16
+ }
17
+
18
+ // Tile-size-parameterised variant.
19
+ @verify(lean, theorem = "checker_tiled_returns_zero_or_one")
20
+ fn checker_tiled(x: Real, y: Real, tile_size: Real) -> Real
21
+ where chain_order <= 0,
22
+ domain: tile_size > 0.0
23
+ ensures (result == 0.0 || result == 1.0)
24
+ {
25
+ let s: Real = floor(x / tile_size) + floor(y / tile_size);
26
+ s - 2.0 * floor(s * 0.5)
27
+ }
@@ -0,0 +1,26 @@
1
+ // fire.eml -- noise-advection fire texture.
2
+ //
3
+ // Vertical advection of FBM noise produces flickering tongues of
4
+ // flame; remap to a temperature-to-colour gradient.
5
+ //
6
+ // Output is a normalised intensity ∈ [0, 1] that the caller maps
7
+ // to (orange, yellow, white, alpha) by table lookup.
8
+
9
+ module fire;
10
+
11
+ use stdlib::gaming::noise::fbm;
12
+
13
+ @verify(lean, theorem = "fire_intensity_in_unit_interval")
14
+ fn intensity(u: Real, v: Real, time_s: Real, rise_speed: Real) -> Real
15
+ where chain_order <= 1,
16
+ domain: rise_speed >= 0.0
17
+ ensures (result >= 0.0)
18
+ ensures (result <= 1.0)
19
+ {
20
+ // Advect upward with time.
21
+ let v_advected: Real = v + rise_speed * time_s;
22
+ let n: Real = fbm::fbm2_unit(u * 1.5, v_advected * 0.8);
23
+ // Vertical fall-off: hotter at the base, cools toward the tip.
24
+ let falloff: Real = clamp(1.0 - v, 0.0, 1.0);
25
+ clamp(n * falloff, 0.0, 1.0)
26
+ }
@@ -0,0 +1,24 @@
1
+ // marble.eml -- turbulence-perturbed sine ramp.
2
+ //
3
+ // marble(x, y) = (sin(2π * f * (x + amplitude * turbulence(x, y))) + 1) / 2
4
+ //
5
+ // The turbulence (absolute-value FBM) bends the sine bands into
6
+ // the cusped vein patterns marble is known for. Caller maps the
7
+ // scalar to a colour gradient.
8
+
9
+ module marble;
10
+
11
+ use stdlib::gaming::noise::turbulence;
12
+
13
+ const PI: Real = 3.141592653589793
14
+
15
+ @verify(lean, theorem = "marble_in_unit_interval")
16
+ fn marble(x: Real, y: Real, frequency: Real, amplitude: Real) -> Real
17
+ where chain_order <= 1,
18
+ domain: frequency > 0.0 && amplitude >= 0.0
19
+ ensures (result >= 0.0)
20
+ ensures (result <= 1.0)
21
+ {
22
+ let t: Real = turbulence::turbulence2_default(x, y);
23
+ 0.5 * (sin(2.0 * PI * frequency * (x + amplitude * t)) + 1.0)
24
+ }
@@ -0,0 +1,23 @@
1
+ // rust.eml -- Voronoi-driven rust / oxidation mask.
2
+ //
3
+ // Combine Voronoi cells (irregular pitting) with FBM erosion (the
4
+ // flow patterns where moisture pools). Output ∈ [0, 1] — pipe into
5
+ // a brown-orange colour ramp.
6
+
7
+ module rust;
8
+
9
+ use stdlib::gaming::noise::voronoi_2d;
10
+ use stdlib::gaming::noise::fbm;
11
+
12
+ @verify(lean, theorem = "rust_mask_in_unit_interval")
13
+ fn mask(x: Real, y: Real, pitting_strength: Real, flow_strength: Real) -> Real
14
+ where chain_order <= 1,
15
+ domain: pitting_strength >= 0.0 && flow_strength >= 0.0
16
+ ensures (result >= 0.0)
17
+ ensures (result <= 1.0)
18
+ {
19
+ let pit: Real = clamp(1.0 - voronoi_2d::distance_to_nearest(x * 0.5, y * 0.5),
20
+ 0.0, 1.0);
21
+ let flow: Real = fbm::fbm2_unit(x * 0.7, y * 0.7);
22
+ clamp(pitting_strength * pit + flow_strength * flow, 0.0, 1.0)
23
+ }
@@ -0,0 +1,49 @@
1
+ // water_surface.eml -- sum-of-sines water height field.
2
+ //
3
+ // Three layered sine waves with different frequencies, directions
4
+ // and phase speeds. Cheap, plausible water you can drop into any
5
+ // shader. For real-time rendering the caller animates the `time`
6
+ // parameter.
7
+
8
+ module water_surface;
9
+
10
+ const PI: Real = 3.141592653589793
11
+
12
+ @verify(lean, theorem = "water_height_signed")
13
+ fn height(x: Real, y: Real, time_s: Real,
14
+ amp_a: Real, amp_b: Real, amp_c: Real) -> Real
15
+ where chain_order <= 1
16
+ requires (amp_a >= 0.0)
17
+ requires (amp_b >= 0.0)
18
+ requires (amp_c >= 0.0)
19
+ {
20
+ let w_a: Real = sin(2.0 * PI * (0.10 * x + 0.05 * y) + 1.4 * time_s);
21
+ let w_b: Real = sin(2.0 * PI * (0.07 * x - 0.13 * y) + 0.9 * time_s);
22
+ let w_c: Real = sin(2.0 * PI * (0.21 * x + 0.18 * y) + 2.3 * time_s);
23
+ amp_a * w_a + amp_b * w_b + amp_c * w_c
24
+ }
25
+
26
+ // Default parameter set good enough for most water shaders.
27
+ @verify(lean, theorem = "water_height_default_signed")
28
+ fn height_default(x: Real, y: Real, time_s: Real) -> Real
29
+ where chain_order <= 1
30
+ {
31
+ height(x, y, time_s, 0.5, 0.3, 0.15)
32
+ }
33
+
34
+ // Approximate normal of the height field for shading.
35
+ @verify(lean, theorem = "water_normal_unit_length")
36
+ fn normal_y(x: Real, y: Real, time_s: Real, eps: Real) -> Real
37
+ where chain_order <= 1,
38
+ domain: eps > 0.0
39
+ ensures (result >= 0.0)
40
+ {
41
+ let h_x_plus: Real = height_default(x + eps, y, time_s);
42
+ let h_x_minus: Real = height_default(x - eps, y, time_s);
43
+ let h_y_plus: Real = height_default(x, y + eps, time_s);
44
+ let h_y_minus: Real = height_default(x, y - eps, time_s);
45
+ let dhx: Real = (h_x_plus - h_x_minus) / (2.0 * eps);
46
+ let dhy: Real = (h_y_plus - h_y_minus) / (2.0 * eps);
47
+ let n_y: Real = 1.0 / sqrt(1.0 + dhx * dhx + dhy * dhy);
48
+ clamp(n_y, 0.0, 1.0)
49
+ }
@@ -0,0 +1,41 @@
1
+ // wood.eml -- procedural wood-grain texture.
2
+ //
3
+ // ring(x, y) = sin(2π * frequency * (radial_distance + warp))
4
+ //
5
+ // Radial distance from a virtual trunk axis modulated by Perlin
6
+ // noise gives concentric tree rings. Output is a scalar grain
7
+ // intensity in [0, 1] suitable for piping into a colour ramp.
8
+
9
+ module wood;
10
+
11
+ use stdlib::gaming::noise::perlin_2d;
12
+
13
+ const PI: Real = 3.141592653589793
14
+
15
+ @verify(lean, theorem = "wood_grain_in_unit_interval")
16
+ fn grain(x: Real, y: Real, ring_frequency: Real, warp_amount: Real) -> Real
17
+ where chain_order <= 1,
18
+ domain: ring_frequency > 0.0
19
+ ensures (result >= 0.0)
20
+ ensures (result <= 1.0)
21
+ {
22
+ let r: Real = sqrt(x * x + y * y);
23
+ let warp: Real = warp_amount * perlin_2d::perlin2(x * 0.4, y * 0.4);
24
+ let s: Real = sin(2.0 * PI * ring_frequency * (r + warp));
25
+ 0.5 * (s + 1.0)
26
+ }
27
+
28
+ // Knot-mask: returns a contribution that goes to 1 inside random
29
+ // knot blobs scattered by Perlin noise. Multiplied with the grain
30
+ // for visual depth.
31
+ @verify(lean, theorem = "wood_knot_in_unit_interval")
32
+ fn knot_mask(x: Real, y: Real, threshold: Real) -> Real
33
+ where chain_order <= 1
34
+ requires (threshold >= 0.0)
35
+ requires (threshold <= 1.0)
36
+ ensures (result >= 0.0)
37
+ ensures (result <= 1.0)
38
+ {
39
+ let n: Real = perlin_2d::perlin2_unit(x * 0.15, y * 0.15);
40
+ clamp((n - threshold) / (1.0 - threshold + 1.0e-3), 0.0, 1.0)
41
+ }