eml-stdlib 0.4.0__tar.gz → 0.5.0__tar.gz

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 (200) hide show
  1. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/PKG-INFO +20 -14
  2. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/README.md +17 -11
  3. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/__init__.py +1 -1
  4. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/wind.eml +2 -2
  5. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/catalog.json +208 -0
  6. eml_stdlib-0.5.0/eml_stdlib/control/attitude_quaternion.eml +75 -0
  7. eml_stdlib-0.5.0/eml_stdlib/control/complementary_filter.eml +89 -0
  8. eml_stdlib-0.5.0/eml_stdlib/control/ekf_range_bearing.eml +60 -0
  9. eml_stdlib-0.5.0/eml_stdlib/control/kalman2d_predict.eml +58 -0
  10. eml_stdlib-0.5.0/eml_stdlib/control/kalman2d_update.eml +83 -0
  11. eml_stdlib-0.5.0/eml_stdlib/control/kalman2d_update_matrix.eml +105 -0
  12. eml_stdlib-0.5.0/eml_stdlib/control/pid3.eml +40 -0
  13. eml_stdlib-0.5.0/eml_stdlib/control/weighted_fusion.eml +69 -0
  14. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/audio/doppler.eml +2 -0
  15. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/camera/fov_projection.eml +8 -2
  16. eml_stdlib-0.5.0/eml_stdlib/math/atan.eml +41 -0
  17. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/atan2.eml +7 -2
  18. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/thermistor.eml +2 -0
  19. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib.egg-info/PKG-INFO +20 -14
  20. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib.egg-info/SOURCES.txt +8 -0
  21. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/pyproject.toml +3 -3
  22. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/tests/test_smoke.py +3 -3
  23. eml_stdlib-0.4.0/eml_stdlib/math/atan.eml +0 -32
  24. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/LICENSE +0 -0
  25. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/air_density.eml +0 -0
  26. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/ballistic_solver.eml +0 -0
  27. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/coriolis.eml +0 -0
  28. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/drag.eml +0 -0
  29. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/gravity.eml +0 -0
  30. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/muzzle_velocity.eml +0 -0
  31. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/spin_drift.eml +0 -0
  32. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ballistics/time_of_flight.eml +0 -0
  33. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/ballistic_armor.eml +0 -0
  34. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/bite_force.eml +0 -0
  35. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/chromatophore.eml +0 -0
  36. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/discharge.eml +0 -0
  37. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/elastic_energy.eml +0 -0
  38. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/locomotion.eml +0 -0
  39. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/muscle_power.eml +0 -0
  40. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/sprint.eml +0 -0
  41. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/texture_match.eml +0 -0
  42. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/abilities/toxin.eml +0 -0
  43. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/cone_l.eml +0 -0
  44. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/cone_s.eml +0 -0
  45. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/cryptochrome.eml +0 -0
  46. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/geomagnetic_field.eml +0 -0
  47. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/goldman_equation.eml +0 -0
  48. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/hill_equation.eml +0 -0
  49. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/hodgkin_huxley.eml +0 -0
  50. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/michaelis_menten.eml +0 -0
  51. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/plume_diffusion.eml +0 -0
  52. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/receptor_binding.eml +0 -0
  53. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/rod_sensitivity.eml +0 -0
  54. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/biology/tapetum.eml +0 -0
  55. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/acoustic_cloak.eml +0 -0
  56. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/ferron_emission.eml +0 -0
  57. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/ferron_logic.eml +0 -0
  58. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/ferron_propagation.eml +0 -0
  59. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/mach_zehnder.eml +0 -0
  60. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/magnon_dispersion.eml +0 -0
  61. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/magnon_logic.eml +0 -0
  62. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/optical_neuron.eml +0 -0
  63. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/phonon_bandgap.eml +0 -0
  64. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/ring_resonator.eml +0 -0
  65. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/spin_torque.eml +0 -0
  66. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/carriers/thermal_rectifier.eml +0 -0
  67. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/buck_converter.eml +0 -0
  68. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/cmos_inverter.eml +0 -0
  69. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/h_bridge.eml +0 -0
  70. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/ldo.eml +0 -0
  71. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/mosfet_iv.eml +0 -0
  72. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/pll_loop.eml +0 -0
  73. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/rc_filter.eml +0 -0
  74. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/circuits/voltage_divider.eml +0 -0
  75. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/bangbang.eml +0 -0
  76. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/deadband.eml +0 -0
  77. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/hysteresis.eml +0 -0
  78. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/kalman_1d.eml +0 -0
  79. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/lqr_1d.eml +0 -0
  80. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/control/pid.eml +0 -0
  81. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/bounce.eml +0 -0
  82. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/ease_in.eml +0 -0
  83. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/ease_in_out.eml +0 -0
  84. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/ease_out.eml +0 -0
  85. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/ik_2bone.eml +0 -0
  86. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/animation/spring.eml +0 -0
  87. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/audio/distance_attenuation.eml +0 -0
  88. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/audio/lowpass_audio.eml +0 -0
  89. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/audio/reverb_delay.eml +0 -0
  90. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/camera/dof_blur.eml +0 -0
  91. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/camera/orbit.eml +0 -0
  92. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/camera/shake.eml +0 -0
  93. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/ambient_occlusion.eml +0 -0
  94. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/area_light.eml +0 -0
  95. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/fog_exp.eml +0 -0
  96. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/fog_exp2.eml +0 -0
  97. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/point_light.eml +0 -0
  98. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/lighting/spot_light.eml +0 -0
  99. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/fbm.eml +0 -0
  100. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/perlin_2d.eml +0 -0
  101. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/perlin_3d.eml +0 -0
  102. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/simplex_2d.eml +0 -0
  103. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/turbulence.eml +0 -0
  104. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/value_noise.eml +0 -0
  105. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/voronoi_2d.eml +0 -0
  106. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/white_noise.eml +0 -0
  107. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/noise/worley.eml +0 -0
  108. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/particles/drag.eml +0 -0
  109. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/particles/emitter_radial.eml +0 -0
  110. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/particles/fade.eml +0 -0
  111. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/particles/gravity_particle.eml +0 -0
  112. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/particles/size_over_life.eml +0 -0
  113. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/aabb_overlap.eml +0 -0
  114. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/buoyancy.eml +0 -0
  115. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/circle_collision.eml +0 -0
  116. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/impulse_resolve.eml +0 -0
  117. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/rigid_body_2d.eml +0 -0
  118. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/spring_damper.eml +0 -0
  119. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/physics/verlet.eml +0 -0
  120. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/fresnel.eml +0 -0
  121. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/matcap.eml +0 -0
  122. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/pbr_diffuse.eml +0 -0
  123. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/pbr_specular.eml +0 -0
  124. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/subsurface.eml +0 -0
  125. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/shading/toon.eml +0 -0
  126. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/terrain/biome_select.eml +0 -0
  127. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/terrain/cliff_detect.eml +0 -0
  128. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/terrain/erosion_hydraulic.eml +0 -0
  129. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/terrain/erosion_thermal.eml +0 -0
  130. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/terrain/heightmap.eml +0 -0
  131. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/brick.eml +0 -0
  132. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/caustics.eml +0 -0
  133. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/checkerboard.eml +0 -0
  134. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/fire.eml +0 -0
  135. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/marble.eml +0 -0
  136. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/rust.eml +0 -0
  137. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/water_surface.eml +0 -0
  138. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/gaming/textures/wood.eml +0 -0
  139. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/abs.eml +0 -0
  140. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/bessel_j0.eml +0 -0
  141. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/cos.eml +0 -0
  142. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/cosh.eml +0 -0
  143. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/erf.eml +0 -0
  144. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/exp.eml +0 -0
  145. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/gamma.eml +0 -0
  146. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/gaussian.eml +0 -0
  147. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/log.eml +0 -0
  148. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/pow.eml +0 -0
  149. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/relu.eml +0 -0
  150. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/sigmoid.eml +0 -0
  151. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/sin.eml +0 -0
  152. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/sinh.eml +0 -0
  153. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/softmax.eml +0 -0
  154. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/sqrt.eml +0 -0
  155. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/tan.eml +0 -0
  156. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/math/tanh.eml +0 -0
  157. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/attention.eml +0 -0
  158. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/cross_entropy.eml +0 -0
  159. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/gelu.eml +0 -0
  160. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/layernorm.eml +0 -0
  161. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/leaky_relu.eml +0 -0
  162. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/relu.eml +0 -0
  163. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/rotary_embed.eml +0 -0
  164. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/silu.eml +0 -0
  165. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/ml/softmax.eml +0 -0
  166. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/coulomb.eml +0 -0
  167. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/damped_oscillator.eml +0 -0
  168. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/diffusion.eml +0 -0
  169. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/gravity.eml +0 -0
  170. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/hooke.eml +0 -0
  171. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/navier_stokes_1d.eml +0 -0
  172. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/planck_radiation.eml +0 -0
  173. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/stefan_boltzmann.eml +0 -0
  174. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/physics/wave_propagation.eml +0 -0
  175. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/cnot.eml +0 -0
  176. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/grover_oracle.eml +0 -0
  177. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/hadamard.eml +0 -0
  178. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/pauli_x.eml +0 -0
  179. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/pauli_z.eml +0 -0
  180. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/phase_gate.eml +0 -0
  181. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/quantum/rotation_rz.eml +0 -0
  182. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/accelerometer.eml +0 -0
  183. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/hall_effect.eml +0 -0
  184. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/photodetector.eml +0 -0
  185. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/rtd.eml +0 -0
  186. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/sensors/strain_gauge.eml +0 -0
  187. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/bandpass.eml +0 -0
  188. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/chirp.eml +0 -0
  189. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/dft_single.eml +0 -0
  190. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/fft_butterfly.eml +0 -0
  191. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/highpass.eml +0 -0
  192. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/lowpass.eml +0 -0
  193. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/matched_filter.eml +0 -0
  194. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/notch_filter.eml +0 -0
  195. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/window_hamming.eml +0 -0
  196. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib/signal/window_hann.eml +0 -0
  197. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib.egg-info/dependency_links.txt +0 -0
  198. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib.egg-info/requires.txt +0 -0
  199. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/eml_stdlib.egg-info/top_level.txt +0 -0
  200. {eml_stdlib-0.4.0 → eml_stdlib-0.5.0}/setup.cfg +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eml-stdlib
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: EML standard-library prototype for game development. PBR shaders, procedural noise, procedural textures, lighting, terrain, animation curves, particles, audio attenuation + Doppler, rigid-body physics, and math/signal/control/biology/ballistics/ML kernels with explicit verification-contract metadata where available.
5
5
  Author: Mosa Creates LLC
6
- Author-email: "Arturo R. Almaguer" <almaguer1986@gmail.com>
7
- Maintainer-email: "Arturo R. Almaguer" <almaguer1986@gmail.com>
6
+ Author-email: "Arturo R. Almaguer" <contact@monogate.dev>
7
+ Maintainer-email: "Arturo R. Almaguer" <contact@monogate.dev>
8
8
  License: MIT
9
9
  Project-URL: Homepage, https://monogate.dev/learn/eml/intro
10
10
  Project-URL: Repository, https://github.com/agent-maestro/eml-stdlib
@@ -36,27 +36,26 @@ Dynamic: license-file
36
36
 
37
37
  # eml-stdlib
38
38
 
39
- **An EML standard-library prototype for game development.**
40
- Shaders, textures, and physics formulas carry explicit verification contracts
41
- or proof-obligation hooks where available.
39
+ **The first verified standard library for game development.**
40
+ Every shader, every texture, every physics formula — with a mathematical proof.
42
41
 
43
42
  Plus the math, signal-processing, control, biology, ballistics, and ML kernels
44
- that built the rest of the Monogate stack. Modules are intended to compile to
45
- GDScript, GLSL, HLSL, C, Python, and Lean through Forge-supported targets;
46
- `@verify` contracts are tracked as proof obligations against MachLib.
43
+ that built the rest of the Monogate stack. Every module compiles to GDScript,
44
+ GLSL, HLSL, C, Python, and Lean (and ~30 other backends via Forge); every
45
+ `@verify` contract has a Lean proof obligation against MachLib.
47
46
 
48
47
  ```bash
49
48
  pip install eml-stdlib
50
49
  eml-compile eml_stdlib/gaming/shading/pbr_specular.eml --target glsl
51
50
  ```
52
51
 
53
- And get a PBR specular shader with explicit verification metadata.
52
+ And get a verified PBR specular shader.
54
53
 
55
54
  ## At a glance
56
55
 
57
- - **178 modules** across **22 categories**
58
- - **521 functions** total
59
- - **466 carry an `@verify(lean, …)` contract** (89%)
56
+ - **185 modules** across **22 categories**
57
+ - **550 functions** total
58
+ - **476 carry an `@verify(lean, …)` contract** (86%)
60
59
  - Every function declares its **Pfaffian chain order** in the type
61
60
 
62
61
  ## Used by
@@ -142,18 +141,25 @@ DSP — filters, FFT, windows, matched-filter.
142
141
  | `window_hamming.eml` | hamming, hamming_at_start, hamming_apply | 0,1 | 3/3 | **new** |
143
142
  | `window_hann.eml` | hann, hann_at_start, hann_apply | 0,1 | 3/3 | **new** |
144
143
 
145
- ### `control/` — 6 modules / 12 fns / 12 verified
144
+ ### `control/` — 13 modules / 41 fns / 22 verified
146
145
 
147
146
  Control — PID, Kalman, LQR, hysteresis, deadband.
148
147
 
149
148
  | File | Functions | Chain | Verified | Origin |
150
149
  |------|-----------|-------|----------|--------|
150
+ | `attitude_quaternion.eml` | quat_mul, quat_conjugate, quat_rotate_vec, quat_normalize | 0 | 1/4 | **new** |
151
151
  | `bangbang.eml` | bangbang, bangbang_symmetric | 0 | 2/2 | **new** |
152
+ | `complementary_filter.eml` | integrate, fuse, fuse_bounded, fuse_tilt | 0 | 2/4 | **new** |
152
153
  | `deadband.eml` | deadband, deadband_asymmetric | 0 | 2/2 | **new** |
154
+ | `ekf_range_bearing.eml` | range, range_jacobian, bearing_jacobian | 0 | 1/3 | **new** |
153
155
  | `hysteresis.eml` | hysteresis_step | 0 | 1/1 | **new** |
156
+ | `kalman2d_predict.eml` | predict_state, cov_predict | 0 | 1/2 | **new** |
157
+ | `kalman2d_update.eml` | innovation, gain, update_state, … (+3) | 0 | 1/6 | **new** |
158
+ | `kalman2d_update_matrix.eml` | innovation, innovation_cov, gain_matrix, … (+4) | 0 | 2/7 | **new** |
154
159
  | `kalman_1d.eml` | kalman1d_predict, kalman1d_update, kalman1d_step | 0 | 3/3 | **new** |
155
160
  | `lqr_1d.eml` | riccati, lqr_gain, lqr_control | 0,1 | 3/3 | **new** |
156
161
  | `pid.eml` | pid | 0 | 1/1 | forge/examples/pid_controller.eml |
162
+ | `weighted_fusion.eml` | fuse3, fuse3_bounded, fuse4_bounded | 0 | 2/3 | **new** |
157
163
 
158
164
  ### `physics/` — 9 modules / 30 fns / 28 verified
159
165
 
@@ -1,26 +1,25 @@
1
1
  # eml-stdlib
2
2
 
3
- **An EML standard-library prototype for game development.**
4
- Shaders, textures, and physics formulas carry explicit verification contracts
5
- or proof-obligation hooks where available.
3
+ **The first verified standard library for game development.**
4
+ Every shader, every texture, every physics formula — with a mathematical proof.
6
5
 
7
6
  Plus the math, signal-processing, control, biology, ballistics, and ML kernels
8
- that built the rest of the Monogate stack. Modules are intended to compile to
9
- GDScript, GLSL, HLSL, C, Python, and Lean through Forge-supported targets;
10
- `@verify` contracts are tracked as proof obligations against MachLib.
7
+ that built the rest of the Monogate stack. Every module compiles to GDScript,
8
+ GLSL, HLSL, C, Python, and Lean (and ~30 other backends via Forge); every
9
+ `@verify` contract has a Lean proof obligation against MachLib.
11
10
 
12
11
  ```bash
13
12
  pip install eml-stdlib
14
13
  eml-compile eml_stdlib/gaming/shading/pbr_specular.eml --target glsl
15
14
  ```
16
15
 
17
- And get a PBR specular shader with explicit verification metadata.
16
+ And get a verified PBR specular shader.
18
17
 
19
18
  ## At a glance
20
19
 
21
- - **178 modules** across **22 categories**
22
- - **521 functions** total
23
- - **466 carry an `@verify(lean, …)` contract** (89%)
20
+ - **185 modules** across **22 categories**
21
+ - **550 functions** total
22
+ - **476 carry an `@verify(lean, …)` contract** (86%)
24
23
  - Every function declares its **Pfaffian chain order** in the type
25
24
 
26
25
  ## Used by
@@ -106,18 +105,25 @@ DSP — filters, FFT, windows, matched-filter.
106
105
  | `window_hamming.eml` | hamming, hamming_at_start, hamming_apply | 0,1 | 3/3 | **new** |
107
106
  | `window_hann.eml` | hann, hann_at_start, hann_apply | 0,1 | 3/3 | **new** |
108
107
 
109
- ### `control/` — 6 modules / 12 fns / 12 verified
108
+ ### `control/` — 13 modules / 41 fns / 22 verified
110
109
 
111
110
  Control — PID, Kalman, LQR, hysteresis, deadband.
112
111
 
113
112
  | File | Functions | Chain | Verified | Origin |
114
113
  |------|-----------|-------|----------|--------|
114
+ | `attitude_quaternion.eml` | quat_mul, quat_conjugate, quat_rotate_vec, quat_normalize | 0 | 1/4 | **new** |
115
115
  | `bangbang.eml` | bangbang, bangbang_symmetric | 0 | 2/2 | **new** |
116
+ | `complementary_filter.eml` | integrate, fuse, fuse_bounded, fuse_tilt | 0 | 2/4 | **new** |
116
117
  | `deadband.eml` | deadband, deadband_asymmetric | 0 | 2/2 | **new** |
118
+ | `ekf_range_bearing.eml` | range, range_jacobian, bearing_jacobian | 0 | 1/3 | **new** |
117
119
  | `hysteresis.eml` | hysteresis_step | 0 | 1/1 | **new** |
120
+ | `kalman2d_predict.eml` | predict_state, cov_predict | 0 | 1/2 | **new** |
121
+ | `kalman2d_update.eml` | innovation, gain, update_state, … (+3) | 0 | 1/6 | **new** |
122
+ | `kalman2d_update_matrix.eml` | innovation, innovation_cov, gain_matrix, … (+4) | 0 | 2/7 | **new** |
118
123
  | `kalman_1d.eml` | kalman1d_predict, kalman1d_update, kalman1d_step | 0 | 3/3 | **new** |
119
124
  | `lqr_1d.eml` | riccati, lqr_gain, lqr_control | 0,1 | 3/3 | **new** |
120
125
  | `pid.eml` | pid | 0 | 1/1 | forge/examples/pid_controller.eml |
126
+ | `weighted_fusion.eml` | fuse3, fuse3_bounded, fuse4_bounded | 0 | 2/3 | **new** |
121
127
 
122
128
  ### `physics/` — 9 modules / 30 fns / 28 verified
123
129
 
@@ -19,7 +19,7 @@ import json
19
19
  from pathlib import Path
20
20
  from typing import Any
21
21
 
22
- __version__ = "0.4.0"
22
+ __version__ = "0.5.0"
23
23
 
24
24
  _PACKAGE_ROOT = Path(__file__).resolve().parent
25
25
  _CATALOG_PATH = _PACKAGE_ROOT / "catalog.json"
@@ -34,14 +34,14 @@ fn relative_airspeed(v_bullet: Real, v_wind_along: Real) -> Real
34
34
  // radians, measured from the shooter's forward direction.
35
35
  // v_perp = v_wind * sin(bearing - heading)
36
36
  // v_along = -v_wind * cos(bearing - heading)
37
- @verify(lean, theorem = "wind_components_pythagorean")
37
+ @verify(lean, theorem = "wind_perp_component")
38
38
  fn perp_component(v_wind: Real, bearing: Real, heading: Real) -> Real
39
39
  where chain_order <= 1
40
40
  {
41
41
  v_wind * sin(bearing - heading)
42
42
  }
43
43
 
44
- @verify(lean, theorem = "wind_components_pythagorean")
44
+ @verify(lean, theorem = "wind_along_component")
45
45
  fn along_component(v_wind: Real, bearing: Real, heading: Real) -> Real
46
46
  where chain_order <= 1
47
47
  {
@@ -1283,6 +1283,35 @@
1283
1283
  "description": "the textbook resistive divider, the",
1284
1284
  "source": "forge/examples/voltage_divider.eml"
1285
1285
  },
1286
+ {
1287
+ "category": "control",
1288
+ "file": "control/attitude_quaternion.eml",
1289
+ "module": "attitude_quaternion",
1290
+ "functions": [
1291
+ {
1292
+ "name": "quat_mul",
1293
+ "chain_order": 0,
1294
+ "verified": false
1295
+ },
1296
+ {
1297
+ "name": "quat_conjugate",
1298
+ "chain_order": 0,
1299
+ "verified": false
1300
+ },
1301
+ {
1302
+ "name": "quat_rotate_vec",
1303
+ "chain_order": 0,
1304
+ "verified": false
1305
+ },
1306
+ {
1307
+ "name": "quat_normalize",
1308
+ "chain_order": 0,
1309
+ "verified": true
1310
+ }
1311
+ ],
1312
+ "description": "quaternion attitude representation, the standard",
1313
+ "source": "new"
1314
+ },
1286
1315
  {
1287
1316
  "category": "control",
1288
1317
  "file": "control/bangbang.eml",
@@ -1302,6 +1331,35 @@
1302
1331
  "description": "bang-bang (relay) controller.",
1303
1332
  "source": "new"
1304
1333
  },
1334
+ {
1335
+ "category": "control",
1336
+ "file": "control/complementary_filter.eml",
1337
+ "module": "complementary_filter",
1338
+ "functions": [
1339
+ {
1340
+ "name": "integrate",
1341
+ "chain_order": 0,
1342
+ "verified": false
1343
+ },
1344
+ {
1345
+ "name": "fuse",
1346
+ "chain_order": 0,
1347
+ "verified": true
1348
+ },
1349
+ {
1350
+ "name": "fuse_bounded",
1351
+ "chain_order": 0,
1352
+ "verified": true
1353
+ },
1354
+ {
1355
+ "name": "fuse_tilt",
1356
+ "chain_order": 0,
1357
+ "verified": false
1358
+ }
1359
+ ],
1360
+ "description": "IMU tilt estimation by gyro/accelerometer",
1361
+ "source": "new"
1362
+ },
1305
1363
  {
1306
1364
  "category": "control",
1307
1365
  "file": "control/deadband.eml",
@@ -1321,6 +1379,30 @@
1321
1379
  "description": "two-sided dead-zone (deadband) saturation.",
1322
1380
  "source": "new"
1323
1381
  },
1382
+ {
1383
+ "category": "control",
1384
+ "file": "control/ekf_range_bearing.eml",
1385
+ "module": "ekf_range_bearing",
1386
+ "functions": [
1387
+ {
1388
+ "name": "range",
1389
+ "chain_order": 0,
1390
+ "verified": true
1391
+ },
1392
+ {
1393
+ "name": "range_jacobian",
1394
+ "chain_order": 0,
1395
+ "verified": false
1396
+ },
1397
+ {
1398
+ "name": "bearing_jacobian",
1399
+ "chain_order": 0,
1400
+ "verified": false
1401
+ }
1402
+ ],
1403
+ "description": "Extended Kalman Filter measurement model for a",
1404
+ "source": "new"
1405
+ },
1324
1406
  {
1325
1407
  "category": "control",
1326
1408
  "file": "control/hysteresis.eml",
@@ -1335,6 +1417,108 @@
1335
1417
  "description": "Schmitt-trigger / hysteresis switching.",
1336
1418
  "source": "new"
1337
1419
  },
1420
+ {
1421
+ "category": "control",
1422
+ "file": "control/kalman2d_predict.eml",
1423
+ "module": "kalman2d_predict",
1424
+ "functions": [
1425
+ {
1426
+ "name": "predict_state",
1427
+ "chain_order": 0,
1428
+ "verified": false
1429
+ },
1430
+ {
1431
+ "name": "cov_predict",
1432
+ "chain_order": 0,
1433
+ "verified": true
1434
+ }
1435
+ ],
1436
+ "description": "N-D Kalman covariance propagation (predict step).",
1437
+ "source": "new"
1438
+ },
1439
+ {
1440
+ "category": "control",
1441
+ "file": "control/kalman2d_update.eml",
1442
+ "module": "kalman2d_update",
1443
+ "functions": [
1444
+ {
1445
+ "name": "innovation",
1446
+ "chain_order": 0,
1447
+ "verified": false
1448
+ },
1449
+ {
1450
+ "name": "gain",
1451
+ "chain_order": 0,
1452
+ "verified": false
1453
+ },
1454
+ {
1455
+ "name": "update_state",
1456
+ "chain_order": 0,
1457
+ "verified": false
1458
+ },
1459
+ {
1460
+ "name": "update_cov",
1461
+ "chain_order": 0,
1462
+ "verified": false
1463
+ },
1464
+ {
1465
+ "name": "joseph_factor",
1466
+ "chain_order": 0,
1467
+ "verified": false
1468
+ },
1469
+ {
1470
+ "name": "update_cov_joseph",
1471
+ "chain_order": 0,
1472
+ "verified": true
1473
+ }
1474
+ ],
1475
+ "description": "2-state Kalman filter, measurement-UPDATE step.",
1476
+ "source": "new"
1477
+ },
1478
+ {
1479
+ "category": "control",
1480
+ "file": "control/kalman2d_update_matrix.eml",
1481
+ "module": "kalman2d_update_matrix",
1482
+ "functions": [
1483
+ {
1484
+ "name": "innovation",
1485
+ "chain_order": 0,
1486
+ "verified": false
1487
+ },
1488
+ {
1489
+ "name": "innovation_cov",
1490
+ "chain_order": 0,
1491
+ "verified": true
1492
+ },
1493
+ {
1494
+ "name": "gain_matrix",
1495
+ "chain_order": 0,
1496
+ "verified": false
1497
+ },
1498
+ {
1499
+ "name": "update_state",
1500
+ "chain_order": 0,
1501
+ "verified": false
1502
+ },
1503
+ {
1504
+ "name": "update_cov",
1505
+ "chain_order": 0,
1506
+ "verified": false
1507
+ },
1508
+ {
1509
+ "name": "joseph_factor",
1510
+ "chain_order": 0,
1511
+ "verified": false
1512
+ },
1513
+ {
1514
+ "name": "update_cov_joseph",
1515
+ "chain_order": 0,
1516
+ "verified": true
1517
+ }
1518
+ ],
1519
+ "description": "2-state Kalman filter, VECTOR-measurement",
1520
+ "source": "new"
1521
+ },
1338
1522
  {
1339
1523
  "category": "control",
1340
1524
  "file": "control/kalman_1d.eml",
@@ -1397,6 +1581,30 @@
1397
1581
  "description": "the textbook PID controller.",
1398
1582
  "source": "forge/examples/pid_controller.eml"
1399
1583
  },
1584
+ {
1585
+ "category": "control",
1586
+ "file": "control/weighted_fusion.eml",
1587
+ "module": "weighted_fusion",
1588
+ "functions": [
1589
+ {
1590
+ "name": "fuse3",
1591
+ "chain_order": 0,
1592
+ "verified": false
1593
+ },
1594
+ {
1595
+ "name": "fuse3_bounded",
1596
+ "chain_order": 0,
1597
+ "verified": true
1598
+ },
1599
+ {
1600
+ "name": "fuse4_bounded",
1601
+ "chain_order": 0,
1602
+ "verified": true
1603
+ }
1604
+ ],
1605
+ "description": "confidence-weighted fusion of redundant sensors.",
1606
+ "source": "new"
1607
+ },
1400
1608
  {
1401
1609
  "category": "gaming/animation",
1402
1610
  "file": "gaming/animation/bounce.eml",
@@ -0,0 +1,75 @@
1
+ // attitude_quaternion.eml -- quaternion attitude representation, the standard
2
+ // state of a 3D orientation / attitude estimator (drones, spacecraft, AHRS).
3
+ //
4
+ // A rotation in 3D is carried as a unit quaternion q = (w, x, y, z): no gimbal
5
+ // lock (unlike Euler angles), and composition is a single product (unlike
6
+ // rotation matrices, 9 numbers with 6 constraints). An attitude filter keeps
7
+ // q as its state, propagates it from the gyro, and corrects it from the
8
+ // accelerometer/magnetometer — the nonlinear rung above the linear/EKF filters
9
+ // in this category.
10
+ //
11
+ // All four kernels are order-0 and element-wise, so Forge emits them to every
12
+ // target: quat_mul / quat_conjugate reach RTL (pure multiply/accumulate) and
13
+ // are ULP-equal across C/Rust/C++/Java; quat_normalize divides (software +
14
+ // proof, not RTL).
15
+ //
16
+ // The flagship is quat_normalize: an attitude filter must RE-NORMALISE the
17
+ // quaternion each step, because gyro integration walks the state off the unit
18
+ // sphere (‖q‖ drifts from 1). @verify proves the result is EXACTLY a unit
19
+ // quaternion, ‖normalize(q)‖² = 1 — sorryAx-free, the same whole-vector
20
+ // unit-norm proof the `normalize` kernel carries, now at dimension 4.
21
+
22
+ module attitude_quaternion;
23
+
24
+ // Hamilton product q ⊗ r -- composition of two rotations (apply r, then q).
25
+ // (w, x, y, z) convention. Not commutative (rotations don't commute).
26
+ fn quat_mul(q: Vec<4>, r: Vec<4>) -> Vec<4>
27
+ where chain_order <= 0
28
+ {
29
+ [q[0]*r[0] - q[1]*r[1] - q[2]*r[2] - q[3]*r[3],
30
+ q[0]*r[1] + q[1]*r[0] + q[2]*r[3] - q[3]*r[2],
31
+ q[0]*r[2] - q[1]*r[3] + q[2]*r[0] + q[3]*r[1],
32
+ q[0]*r[3] + q[1]*r[2] - q[2]*r[1] + q[3]*r[0]]
33
+ }
34
+
35
+ // Conjugate q* = (w, -x, -y, -z). For a UNIT quaternion this is the inverse
36
+ // rotation (q* = q⁻¹), so it rotates a vector back / expresses the opposite
37
+ // frame transform.
38
+ fn quat_conjugate(q: Vec<4>) -> Vec<4>
39
+ where chain_order <= 0
40
+ {
41
+ [q[0], 0.0 - q[1], 0.0 - q[2], 0.0 - q[3]]
42
+ }
43
+
44
+ // Rotate a 3-vector by a unit quaternion: v' = q ⊗ (0,v) ⊗ q*. Written as the
45
+ // expanded rotation matrix R(q)·v (which equals q⊗v⊗q* for a unit q), so it
46
+ // stays a pure multiply/accumulate expression — no quaternion temporaries —
47
+ // and reaches RTL. This is how an attitude estimate is USED: map a body-frame
48
+ // vector to the world frame (or, via quat_conjugate, world gravity into the
49
+ // body frame to compare against the accelerometer).
50
+ fn quat_rotate_vec(q: Vec<4>, v: Vec<3>) -> Vec<3>
51
+ where chain_order <= 0
52
+ {
53
+ [(1.0 - 2.0*(q[2]*q[2] + q[3]*q[3]))*v[0]
54
+ + 2.0*(q[1]*q[2] - q[0]*q[3])*v[1]
55
+ + 2.0*(q[1]*q[3] + q[0]*q[2])*v[2],
56
+ 2.0*(q[1]*q[2] + q[0]*q[3])*v[0]
57
+ + (1.0 - 2.0*(q[1]*q[1] + q[3]*q[3]))*v[1]
58
+ + 2.0*(q[2]*q[3] - q[0]*q[1])*v[2],
59
+ 2.0*(q[1]*q[3] - q[0]*q[2])*v[0]
60
+ + 2.0*(q[2]*q[3] + q[0]*q[1])*v[1]
61
+ + (1.0 - 2.0*(q[1]*q[1] + q[2]*q[2]))*v[2]]
62
+ }
63
+
64
+ // Re-normalise onto the unit sphere: q / ‖q‖. The projection back to a valid
65
+ // rotation an attitude filter applies every step (gyro integration drifts off
66
+ // the sphere). PROVEN: the result is EXACTLY a unit quaternion, ‖result‖² = 1
67
+ // -- the whole-vector unit-norm contract, sorryAx-free, at dimension 4.
68
+ @verify(lean, theorem = "quat_normalize_unit")
69
+ fn quat_normalize(q: Vec<4>) -> Vec<4>
70
+ where chain_order <= 0
71
+ requires (dot(q, q) > 0.0)
72
+ ensures (dot(result, result) == 1.0)
73
+ {
74
+ q / sqrt(dot(q, q))
75
+ }
@@ -0,0 +1,89 @@
1
+ // complementary_filter.eml -- IMU tilt estimation by gyro/accelerometer
2
+ // sensor fusion (the workhorse of drones, self-balancing robots, phones).
3
+ //
4
+ // A gyroscope integrates cleanly over short horizons but DRIFTS without
5
+ // bound; an accelerometer gives an absolute tilt from gravity but is noisy
6
+ // and corrupted by linear acceleration. The complementary filter blends the
7
+ // two with a single tuning weight α ∈ [0,1]:
8
+ //
9
+ // θ_gyro⁺ = θ + ω·dt (integrate the gyro rate)
10
+ // θ⁺ = α·θ_gyro⁺ + (1-α)·θ_accel (convex blend toward accel)
11
+ //
12
+ // α near 1 trusts the gyro (smooth, follows fast motion); α near 0 trusts
13
+ // the accelerometer (drift-free, noisy). It is a one-line, division-free,
14
+ // order-0 kernel -- ideal for a microcontroller ISR -- yet it is exactly a
15
+ // 1-state steady-state Kalman filter, so it earns its place next to the
16
+ // full 2D filter in this category.
17
+ //
18
+ // VERIFIED, stated honestly:
19
+ // * `fuse` carries an @verify(lean) contract that a convex blend of two
20
+ // NON-NEGATIVE estimates stays non-negative -- proven sorryAx-free.
21
+ // * `fuse_bounded` carries the STRONGER property that is the filter's whole
22
+ // reason for existing: INTERVAL PRESERVATION. If both estimates lie in a
23
+ // sensor's physical range [lo, hi], the fused estimate stays in [lo, hi]
24
+ // for ANY α ∈ [0,1] -- the anti-drift guarantee (a gyro alone would walk
25
+ // out of range unboundedly). This is a convexity bound, not a sign fact,
26
+ // so the positivity closers can't reach it; it is discharged by the
27
+ // MachLib lemmas `convex_comb_le` / `convex_comb_ge` (classical-free),
28
+ // proven sorryAx-free. (An earlier revision left this as a documented
29
+ // `sorry`; the convex-combination lemmas closed it.)
30
+
31
+ module complementary_filter;
32
+
33
+ // Gyro dead-reckoning step: θ_gyro⁺ = θ + ω·dt. Affine, and INTENTIONALLY
34
+ // unverified -- integrating a rate has no bounded-output invariant to prove;
35
+ // its unbounded drift is precisely what the fusion step below corrects.
36
+ fn integrate(theta: Real, omega: Real, dt: Real) -> Real
37
+ where chain_order <= 0
38
+ {
39
+ theta + omega * dt
40
+ }
41
+
42
+ // Convex blend of the gyro-integrated angle and the accelerometer angle:
43
+ // θ⁺ = α·g + (1-α)·a. Proven: for α ∈ [0,1] and non-negative inputs the
44
+ // fused estimate is non-negative (a convex combination of non-negatives).
45
+ @verify(lean, theorem = "complementary_fuse_nonneg")
46
+ fn fuse(gyro_est: Real, accel_est: Real, alpha: Real) -> Real
47
+ where chain_order <= 0
48
+ requires (alpha >= 0.0)
49
+ requires (alpha <= 1.0)
50
+ requires (gyro_est >= 0.0)
51
+ requires (accel_est >= 0.0)
52
+ ensures (result >= 0.0)
53
+ {
54
+ alpha * gyro_est + (1.0 - alpha) * accel_est
55
+ }
56
+
57
+ // Interval-preserving blend: same convex combination, but PROVEN to keep the
58
+ // fused estimate inside the sensor's physical range [lo, hi] for any
59
+ // α ∈ [0,1] given both inputs are in range. This is the anti-drift guarantee
60
+ // -- the whole point of fusing an absolute (accel) reference into a drifting
61
+ // (gyro) one. lo/hi are the sensor range (e.g. tilt ∈ [-π, π]); they are
62
+ // specification parameters, not used by the arithmetic.
63
+ @verify(lean, theorem = "complementary_fuse_in_range")
64
+ fn fuse_bounded(gyro_est: Real, accel_est: Real, alpha: Real,
65
+ lo: Real, hi: Real) -> Real
66
+ where chain_order <= 0
67
+ requires (alpha >= 0.0)
68
+ requires (alpha <= 1.0)
69
+ requires (gyro_est <= hi)
70
+ requires (accel_est <= hi)
71
+ requires (gyro_est >= lo)
72
+ requires (accel_est >= lo)
73
+ ensures (result <= hi)
74
+ ensures (result >= lo)
75
+ {
76
+ alpha * gyro_est + (1.0 - alpha) * accel_est
77
+ }
78
+
79
+ // One-shot tilt update: integrate the gyro then blend toward the
80
+ // accelerometer, θ⁺ = α·(θ + ω·dt) + (1-α)·θ_accel. The form embedded
81
+ // filters actually run each IMU sample.
82
+ fn fuse_tilt(theta: Real, omega: Real, accel_angle: Real,
83
+ alpha: Real, dt: Real) -> Real
84
+ where chain_order <= 0
85
+ requires (alpha >= 0.0)
86
+ requires (alpha <= 1.0)
87
+ {
88
+ alpha * (theta + omega * dt) + (1.0 - alpha) * accel_angle
89
+ }
@@ -0,0 +1,60 @@
1
+ // ekf_range_bearing.eml -- Extended Kalman Filter measurement model for a
2
+ // range/bearing sensor observing a known landmark from a 2D robot pose
3
+ // (x, y, θ). The canonical EKF-SLAM / robot-localisation observation.
4
+ //
5
+ // A linear Kalman filter cannot use a range/bearing sensor: the measurement
6
+ // h(x) = [ √(Δx² + Δy²) , atan2(Δy, Δx) − θ ] (Δx = lx−x, Δy = ly−y)
7
+ // is NONLINEAR in the pose. The EXTENDED Kalman filter linearises it about
8
+ // the current estimate with the measurement Jacobian H = ∂h/∂x, then reuses
9
+ // the ordinary matrix update (see kalman2d_update_matrix.eml). Providing H
10
+ // is the whole job of the EKF measurement model -- that is what this file is.
11
+ //
12
+ // The Jacobian rows are RATIONAL in (Δx, Δy, r) -- no atan2 needed for the
13
+ // derivative even though the bearing measurement itself would be -- so they
14
+ // lower to plain scalar arithmetic every Forge backend emits:
15
+ //
16
+ // ∂range/∂(x,y) = [ −Δx/r , −Δy/r ] (unit vector, landmark→robot)
17
+ // ∂bearing/∂(x,y) = [ Δy/r² , −Δx/r² ]
18
+ // ∂bearing/∂θ = −1 (constant; omitted here)
19
+ //
20
+ // VERIFIED vs NUMERICAL, stated honestly:
21
+ // * `range` carries an @verify(lean) contract that the measured range is
22
+ // non-negative (a Euclidean distance) -- proven sorryAx-free.
23
+ // * The Jacobian rows are NUMERICALLY verified (cross-target vs a reference)
24
+ // but carry no proof contract: they divide by r (and r²), so a sound
25
+ // contract needs r>0 side conditions and division reasoning -- deferred,
26
+ // not asserted.
27
+
28
+ module ekf_range_bearing;
29
+
30
+ // Range measurement: r = √((lx−x)² + (ly−y)²). A Euclidean distance, so
31
+ // non-negative for ANY pose/landmark -- proven, not assumed.
32
+ @verify(lean, theorem = "ekf_range_nonneg")
33
+ fn range(x: Real, y: Real, lx: Real, ly: Real) -> Real
34
+ where chain_order <= 0
35
+ ensures (result >= 0.0)
36
+ {
37
+ sqrt((lx - x)*(lx - x) + (ly - y)*(ly - y))
38
+ }
39
+
40
+ // Range row of the measurement Jacobian: ∂range/∂(x,y) = [−Δx/r, −Δy/r].
41
+ // The unit vector pointing from the landmark toward the robot. Requires a
42
+ // non-degenerate observation (robot not exactly on the landmark, r>0).
43
+ fn range_jacobian(x: Real, y: Real, lx: Real, ly: Real) -> Vec<2>
44
+ where chain_order <= 0
45
+ requires ((lx - x)*(lx - x) + (ly - y)*(ly - y) > 0.0)
46
+ {
47
+ [(x - lx) / sqrt((lx - x)*(lx - x) + (ly - y)*(ly - y)),
48
+ (y - ly) / sqrt((lx - x)*(lx - x) + (ly - y)*(ly - y))]
49
+ }
50
+
51
+ // Bearing row of the measurement Jacobian: ∂bearing/∂(x,y) = [Δy/r², −Δx/r²].
52
+ // Rational in the deltas -- the bearing derivative needs no atan2. Requires
53
+ // r²>0 (same non-degeneracy).
54
+ fn bearing_jacobian(x: Real, y: Real, lx: Real, ly: Real) -> Vec<2>
55
+ where chain_order <= 0
56
+ requires ((lx - x)*(lx - x) + (ly - y)*(ly - y) > 0.0)
57
+ {
58
+ [(ly - y) / ((lx - x)*(lx - x) + (ly - y)*(ly - y)),
59
+ (x - lx) / ((lx - x)*(lx - x) + (ly - y)*(ly - y))]
60
+ }