eml-stdlib 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eml_stdlib/__init__.py +81 -0
- eml_stdlib/ballistics/air_density.eml +73 -0
- eml_stdlib/ballistics/ballistic_solver.eml +102 -0
- eml_stdlib/ballistics/coriolis.eml +60 -0
- eml_stdlib/ballistics/drag.eml +44 -0
- eml_stdlib/ballistics/gravity.eml +52 -0
- eml_stdlib/ballistics/muzzle_velocity.eml +42 -0
- eml_stdlib/ballistics/spin_drift.eml +60 -0
- eml_stdlib/ballistics/time_of_flight.eml +79 -0
- eml_stdlib/ballistics/wind.eml +58 -0
- eml_stdlib/biology/abilities/ballistic_armor.eml +61 -0
- eml_stdlib/biology/abilities/bite_force.eml +48 -0
- eml_stdlib/biology/abilities/chromatophore.eml +50 -0
- eml_stdlib/biology/abilities/discharge.eml +45 -0
- eml_stdlib/biology/abilities/elastic_energy.eml +42 -0
- eml_stdlib/biology/abilities/locomotion.eml +50 -0
- eml_stdlib/biology/abilities/muscle_power.eml +47 -0
- eml_stdlib/biology/abilities/sprint.eml +36 -0
- eml_stdlib/biology/abilities/texture_match.eml +49 -0
- eml_stdlib/biology/abilities/toxin.eml +44 -0
- eml_stdlib/biology/cone_l.eml +36 -0
- eml_stdlib/biology/cone_s.eml +32 -0
- eml_stdlib/biology/cryptochrome.eml +44 -0
- eml_stdlib/biology/geomagnetic_field.eml +32 -0
- eml_stdlib/biology/goldman_equation.eml +41 -0
- eml_stdlib/biology/hill_equation.eml +65 -0
- eml_stdlib/biology/hodgkin_huxley.eml +108 -0
- eml_stdlib/biology/michaelis_menten.eml +65 -0
- eml_stdlib/biology/plume_diffusion.eml +47 -0
- eml_stdlib/biology/receptor_binding.eml +35 -0
- eml_stdlib/biology/rod_sensitivity.eml +38 -0
- eml_stdlib/biology/tapetum.eml +70 -0
- eml_stdlib/carriers/acoustic_cloak.eml +56 -0
- eml_stdlib/carriers/ferron_emission.eml +55 -0
- eml_stdlib/carriers/ferron_logic.eml +45 -0
- eml_stdlib/carriers/ferron_propagation.eml +69 -0
- eml_stdlib/carriers/mach_zehnder.eml +52 -0
- eml_stdlib/carriers/magnon_dispersion.eml +57 -0
- eml_stdlib/carriers/magnon_logic.eml +45 -0
- eml_stdlib/carriers/optical_neuron.eml +55 -0
- eml_stdlib/carriers/phonon_bandgap.eml +54 -0
- eml_stdlib/carriers/ring_resonator.eml +48 -0
- eml_stdlib/carriers/spin_torque.eml +61 -0
- eml_stdlib/carriers/thermal_rectifier.eml +63 -0
- eml_stdlib/catalog.json +4209 -0
- eml_stdlib/circuits/buck_converter.eml +74 -0
- eml_stdlib/circuits/cmos_inverter.eml +75 -0
- eml_stdlib/circuits/h_bridge.eml +69 -0
- eml_stdlib/circuits/ldo.eml +66 -0
- eml_stdlib/circuits/mosfet_iv.eml +59 -0
- eml_stdlib/circuits/pll_loop.eml +63 -0
- eml_stdlib/circuits/rc_filter.eml +98 -0
- eml_stdlib/circuits/voltage_divider.eml +68 -0
- eml_stdlib/control/bangbang.eml +34 -0
- eml_stdlib/control/deadband.eml +28 -0
- eml_stdlib/control/hysteresis.eml +28 -0
- eml_stdlib/control/kalman_1d.eml +53 -0
- eml_stdlib/control/lqr_1d.eml +47 -0
- eml_stdlib/control/pid.eml +38 -0
- eml_stdlib/gaming/animation/bounce.eml +39 -0
- eml_stdlib/gaming/animation/ease_in.eml +27 -0
- eml_stdlib/gaming/animation/ease_in_out.eml +29 -0
- eml_stdlib/gaming/animation/ease_out.eml +27 -0
- eml_stdlib/gaming/animation/ik_2bone.eml +57 -0
- eml_stdlib/gaming/animation/spring.eml +39 -0
- eml_stdlib/gaming/audio/distance_attenuation.eml +50 -0
- eml_stdlib/gaming/audio/doppler.eml +39 -0
- eml_stdlib/gaming/audio/lowpass_audio.eml +32 -0
- eml_stdlib/gaming/audio/reverb_delay.eml +41 -0
- eml_stdlib/gaming/camera/dof_blur.eml +30 -0
- eml_stdlib/gaming/camera/fov_projection.eml +47 -0
- eml_stdlib/gaming/camera/orbit.eml +48 -0
- eml_stdlib/gaming/camera/shake.eml +20 -0
- eml_stdlib/gaming/lighting/ambient_occlusion.eml +40 -0
- eml_stdlib/gaming/lighting/area_light.eml +50 -0
- eml_stdlib/gaming/lighting/fog_exp.eml +28 -0
- eml_stdlib/gaming/lighting/fog_exp2.eml +30 -0
- eml_stdlib/gaming/lighting/point_light.eml +33 -0
- eml_stdlib/gaming/lighting/spot_light.eml +43 -0
- eml_stdlib/gaming/noise/fbm.eml +65 -0
- eml_stdlib/gaming/noise/perlin_2d.eml +65 -0
- eml_stdlib/gaming/noise/perlin_3d.eml +63 -0
- eml_stdlib/gaming/noise/simplex_2d.eml +67 -0
- eml_stdlib/gaming/noise/turbulence.eml +46 -0
- eml_stdlib/gaming/noise/value_noise.eml +45 -0
- eml_stdlib/gaming/noise/voronoi_2d.eml +83 -0
- eml_stdlib/gaming/noise/white_noise.eml +47 -0
- eml_stdlib/gaming/noise/worley.eml +79 -0
- eml_stdlib/gaming/particles/drag.eml +30 -0
- eml_stdlib/gaming/particles/emitter_radial.eml +35 -0
- eml_stdlib/gaming/particles/fade.eml +36 -0
- eml_stdlib/gaming/particles/gravity_particle.eml +32 -0
- eml_stdlib/gaming/particles/size_over_life.eml +28 -0
- eml_stdlib/gaming/physics/aabb_overlap.eml +38 -0
- eml_stdlib/gaming/physics/buoyancy.eml +43 -0
- eml_stdlib/gaming/physics/circle_collision.eml +46 -0
- eml_stdlib/gaming/physics/impulse_resolve.eml +39 -0
- eml_stdlib/gaming/physics/rigid_body_2d.eml +61 -0
- eml_stdlib/gaming/physics/spring_damper.eml +30 -0
- eml_stdlib/gaming/physics/verlet.eml +29 -0
- eml_stdlib/gaming/shading/fresnel.eml +57 -0
- eml_stdlib/gaming/shading/matcap.eml +34 -0
- eml_stdlib/gaming/shading/pbr_diffuse.eml +41 -0
- eml_stdlib/gaming/shading/pbr_specular.eml +75 -0
- eml_stdlib/gaming/shading/subsurface.eml +52 -0
- eml_stdlib/gaming/shading/toon.eml +30 -0
- eml_stdlib/gaming/terrain/biome_select.eml +41 -0
- eml_stdlib/gaming/terrain/cliff_detect.eml +35 -0
- eml_stdlib/gaming/terrain/erosion_hydraulic.eml +57 -0
- eml_stdlib/gaming/terrain/erosion_thermal.eml +44 -0
- eml_stdlib/gaming/terrain/heightmap.eml +33 -0
- eml_stdlib/gaming/textures/brick.eml +27 -0
- eml_stdlib/gaming/textures/caustics.eml +25 -0
- eml_stdlib/gaming/textures/checkerboard.eml +27 -0
- eml_stdlib/gaming/textures/fire.eml +26 -0
- eml_stdlib/gaming/textures/marble.eml +24 -0
- eml_stdlib/gaming/textures/rust.eml +23 -0
- eml_stdlib/gaming/textures/water_surface.eml +49 -0
- eml_stdlib/gaming/textures/wood.eml +41 -0
- eml_stdlib/math/abs.eml +45 -0
- eml_stdlib/math/atan.eml +32 -0
- eml_stdlib/math/atan2.eml +61 -0
- eml_stdlib/math/bessel_j0.eml +65 -0
- eml_stdlib/math/cos.eml +42 -0
- eml_stdlib/math/cosh.eml +24 -0
- eml_stdlib/math/erf.eml +66 -0
- eml_stdlib/math/exp.eml +49 -0
- eml_stdlib/math/gamma.eml +55 -0
- eml_stdlib/math/gaussian.eml +18 -0
- eml_stdlib/math/log.eml +59 -0
- eml_stdlib/math/pow.eml +51 -0
- eml_stdlib/math/relu.eml +63 -0
- eml_stdlib/math/sigmoid.eml +21 -0
- eml_stdlib/math/sin.eml +37 -0
- eml_stdlib/math/sinh.eml +24 -0
- eml_stdlib/math/softmax.eml +87 -0
- eml_stdlib/math/sqrt.eml +46 -0
- eml_stdlib/math/tan.eml +36 -0
- eml_stdlib/math/tanh.eml +54 -0
- eml_stdlib/ml/attention.eml +70 -0
- eml_stdlib/ml/cross_entropy.eml +85 -0
- eml_stdlib/ml/gelu.eml +51 -0
- eml_stdlib/ml/layernorm.eml +49 -0
- eml_stdlib/ml/leaky_relu.eml +51 -0
- eml_stdlib/ml/relu.eml +63 -0
- eml_stdlib/ml/rotary_embed.eml +64 -0
- eml_stdlib/ml/silu.eml +40 -0
- eml_stdlib/ml/softmax.eml +87 -0
- eml_stdlib/physics/coulomb.eml +48 -0
- eml_stdlib/physics/damped_oscillator.eml +20 -0
- eml_stdlib/physics/diffusion.eml +45 -0
- eml_stdlib/physics/gravity.eml +60 -0
- eml_stdlib/physics/hooke.eml +56 -0
- eml_stdlib/physics/navier_stokes_1d.eml +57 -0
- eml_stdlib/physics/planck_radiation.eml +77 -0
- eml_stdlib/physics/stefan_boltzmann.eml +75 -0
- eml_stdlib/physics/wave_propagation.eml +52 -0
- eml_stdlib/quantum/cnot.eml +72 -0
- eml_stdlib/quantum/grover_oracle.eml +69 -0
- eml_stdlib/quantum/hadamard.eml +73 -0
- eml_stdlib/quantum/pauli_x.eml +29 -0
- eml_stdlib/quantum/pauli_z.eml +29 -0
- eml_stdlib/quantum/phase_gate.eml +76 -0
- eml_stdlib/quantum/rotation_rz.eml +92 -0
- eml_stdlib/sensors/accelerometer.eml +59 -0
- eml_stdlib/sensors/hall_effect.eml +42 -0
- eml_stdlib/sensors/photodetector.eml +58 -0
- eml_stdlib/sensors/rtd.eml +57 -0
- eml_stdlib/sensors/strain_gauge.eml +63 -0
- eml_stdlib/sensors/thermistor.eml +71 -0
- eml_stdlib/signal/bandpass.eml +39 -0
- eml_stdlib/signal/chirp.eml +42 -0
- eml_stdlib/signal/dft_single.eml +30 -0
- eml_stdlib/signal/fft_butterfly.eml +36 -0
- eml_stdlib/signal/highpass.eml +45 -0
- eml_stdlib/signal/lowpass.eml +49 -0
- eml_stdlib/signal/matched_filter.eml +48 -0
- eml_stdlib/signal/notch_filter.eml +47 -0
- eml_stdlib/signal/window_hamming.eml +47 -0
- eml_stdlib/signal/window_hann.eml +50 -0
- eml_stdlib-0.4.0.dist-info/METADATA +453 -0
- eml_stdlib-0.4.0.dist-info/RECORD +185 -0
- eml_stdlib-0.4.0.dist-info/WHEEL +5 -0
- eml_stdlib-0.4.0.dist-info/licenses/LICENSE +21 -0
- eml_stdlib-0.4.0.dist-info/top_level.txt +1 -0
eml_stdlib/math/abs.eml
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// abs.eml -- |x|, sign, and clamp.
|
|
2
|
+
//
|
|
3
|
+
// All chain-order 0 -- pure piecewise linear. Listed in stdlib so
|
|
4
|
+
// downstream kernels can reference them by their stable, qualified
|
|
5
|
+
// names instead of relying on the parser-level builtin.
|
|
6
|
+
|
|
7
|
+
module abs_module;
|
|
8
|
+
|
|
9
|
+
@verify(lean, theorem = "abs_nonneg")
|
|
10
|
+
fn abs_kernel(x: Real) -> Real
|
|
11
|
+
where chain_order <= 0
|
|
12
|
+
ensures (result >= 0.0)
|
|
13
|
+
{
|
|
14
|
+
abs(x)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Three-valued sign. Caller is responsible for branch-free
|
|
18
|
+
// implementation downstream of the optimiser.
|
|
19
|
+
@verify(lean, theorem = "sign_in_unit_interval")
|
|
20
|
+
fn sign(x: Real) -> Real
|
|
21
|
+
where chain_order <= 0
|
|
22
|
+
ensures (result >= -1.0)
|
|
23
|
+
ensures (result <= 1.0)
|
|
24
|
+
{
|
|
25
|
+
clamp(x * 1.0e30, -1.0, 1.0)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Symmetric clamp. Equivalent to clamp(x, -limit, limit).
|
|
29
|
+
@verify(lean, theorem = "saturate_in_band")
|
|
30
|
+
fn saturate(x: Real, limit: Real) -> Real
|
|
31
|
+
where chain_order <= 0,
|
|
32
|
+
domain: limit > 0.0
|
|
33
|
+
{
|
|
34
|
+
clamp(x, -limit, limit)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Soft sign: x / (1 + |x|). Smooth approximation to sign(x);
|
|
38
|
+
// useful as a saturating activation. Chain order 0 even though
|
|
39
|
+
// it composes a divide -- no transcendentals.
|
|
40
|
+
@verify(lean, theorem = "softsign_in_open_unit_interval")
|
|
41
|
+
fn softsign(x: Real) -> Real
|
|
42
|
+
where chain_order <= 0
|
|
43
|
+
{
|
|
44
|
+
x / (1.0 + abs(x))
|
|
45
|
+
}
|
eml_stdlib/math/atan.eml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// atan.eml -- arctangent.
|
|
2
|
+
//
|
|
3
|
+
// Chain order 1. Output is bounded to (-pi/2, pi/2) so any caller
|
|
4
|
+
// can reason about bounded output without a separate clamp.
|
|
5
|
+
|
|
6
|
+
module atan_module;
|
|
7
|
+
|
|
8
|
+
const HALF_PI: Real = 1.5707963267948966
|
|
9
|
+
|
|
10
|
+
@verify(lean, theorem = "atan_in_open_half_pi_band")
|
|
11
|
+
fn atan_kernel(x: Real) -> Real
|
|
12
|
+
where chain_order <= 1
|
|
13
|
+
ensures (result > -HALF_PI)
|
|
14
|
+
ensures (result < HALF_PI)
|
|
15
|
+
{
|
|
16
|
+
atan(x)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@verify(lean, theorem = "atan_zero_is_zero")
|
|
20
|
+
fn atan_at_zero() -> Real
|
|
21
|
+
where chain_order <= 0
|
|
22
|
+
ensures (result == 0.0)
|
|
23
|
+
{
|
|
24
|
+
atan(0.0)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@verify(lean, theorem = "atan_odd_at_one")
|
|
28
|
+
fn atan_at_one() -> Real
|
|
29
|
+
where chain_order <= 0
|
|
30
|
+
{
|
|
31
|
+
atan(1.0)
|
|
32
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// atan2.eml -- four-quadrant arctan.
|
|
2
|
+
//
|
|
3
|
+
// Real atan2 needs branching by quadrant, which falls outside the
|
|
4
|
+
// pure-EML chain-order calculus. This module ships the principal
|
|
5
|
+
// branches as separate kernels; the caller picks one by checking
|
|
6
|
+
// the sign of x (the FPGA backend lowers the dispatch to a mux).
|
|
7
|
+
//
|
|
8
|
+
// References:
|
|
9
|
+
// - atan2_pos_x : x > 0 -> atan(y/x)
|
|
10
|
+
// - atan2_neg_x : x < 0, y >= 0 -> atan(y/x) + pi
|
|
11
|
+
// - atan2_neg_x_neg_y : x < 0, y < 0 -> atan(y/x) - pi
|
|
12
|
+
// - atan2_zero_x : x = 0 -> +/- pi/2 depending on y
|
|
13
|
+
|
|
14
|
+
module atan2_module;
|
|
15
|
+
|
|
16
|
+
const PI: Real = 3.141592653589793
|
|
17
|
+
const HALF_PI: Real = 1.5707963267948966
|
|
18
|
+
|
|
19
|
+
@verify(lean, theorem = "atan2_pos_x_in_open_half_pi_band")
|
|
20
|
+
fn atan2_pos_x(y: Real, x: Real) -> Real
|
|
21
|
+
where chain_order <= 2,
|
|
22
|
+
domain: x > 0.0
|
|
23
|
+
ensures (result > -HALF_PI)
|
|
24
|
+
ensures (result < HALF_PI)
|
|
25
|
+
{
|
|
26
|
+
atan(y / x)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@verify(lean, theorem = "atan2_neg_x_upper_in_band")
|
|
30
|
+
fn atan2_neg_x_upper(y: Real, x: Real) -> Real
|
|
31
|
+
where chain_order <= 2,
|
|
32
|
+
domain: x < 0.0
|
|
33
|
+
requires (y >= 0.0)
|
|
34
|
+
{
|
|
35
|
+
atan(y / x) + PI
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@verify(lean, theorem = "atan2_neg_x_lower_in_band")
|
|
39
|
+
fn atan2_neg_x_lower(y: Real, x: Real) -> Real
|
|
40
|
+
where chain_order <= 2,
|
|
41
|
+
domain: x < 0.0
|
|
42
|
+
requires (y < 0.0)
|
|
43
|
+
{
|
|
44
|
+
atan(y / x) - PI
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@verify(lean, theorem = "atan2_zero_x_pos_y")
|
|
48
|
+
fn atan2_zero_x_pos_y() -> Real
|
|
49
|
+
where chain_order <= 0
|
|
50
|
+
ensures (result == HALF_PI)
|
|
51
|
+
{
|
|
52
|
+
HALF_PI
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@verify(lean, theorem = "atan2_zero_x_neg_y")
|
|
56
|
+
fn atan2_zero_x_neg_y() -> Real
|
|
57
|
+
where chain_order <= 0
|
|
58
|
+
ensures (result == -HALF_PI)
|
|
59
|
+
{
|
|
60
|
+
-HALF_PI
|
|
61
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// bessel_j0.eml -- Bessel function of the first kind, order 0.
|
|
2
|
+
//
|
|
3
|
+
// J_0(x) = (1/pi) * integral_0^pi cos(x * sin(t)) dt
|
|
4
|
+
//
|
|
5
|
+
// This module ships two regimes that the FPGA backend lowers
|
|
6
|
+
// independently:
|
|
7
|
+
//
|
|
8
|
+
// bessel_j0_small(x) -- power series, valid for |x| < 8
|
|
9
|
+
// bessel_j0_large(x) -- asymptotic form, valid for |x| >= 8
|
|
10
|
+
//
|
|
11
|
+
// J_0 shows up in circular-aperture diffraction, fiber optics
|
|
12
|
+
// (LP_01 mode), drum membranes, and FM-synthesis sideband
|
|
13
|
+
// amplitudes. The optimiser fuses the two via a value-side
|
|
14
|
+
// dispatch so callers see a single bessel_j0(x) entry point.
|
|
15
|
+
|
|
16
|
+
module bessel_j0_module;
|
|
17
|
+
|
|
18
|
+
const PI: Real = 3.141592653589793
|
|
19
|
+
const TWO_OVER_PI: Real = 0.6366197723675814
|
|
20
|
+
const PI_OVER_FOUR: Real = 0.7853981633974483
|
|
21
|
+
|
|
22
|
+
// ── Small-argument power series ────────────────────────────────
|
|
23
|
+
// J_0(x) = Σ_{k=0}^∞ (-1)^k * (x/2)^{2k} / (k!)^2
|
|
24
|
+
// Truncated at k = 6: max abs error 1e-9 for |x| < 8.
|
|
25
|
+
|
|
26
|
+
@verify(lean, theorem = "bessel_j0_small_at_zero_is_one")
|
|
27
|
+
fn bessel_j0_small(x: Real) -> Real
|
|
28
|
+
where chain_order <= 0
|
|
29
|
+
requires (abs(x) < 8.0)
|
|
30
|
+
{
|
|
31
|
+
let u = (x * x) / 4.0;
|
|
32
|
+
let u2 = u * u;
|
|
33
|
+
let u3 = u2 * u;
|
|
34
|
+
let u4 = u3 * u;
|
|
35
|
+
let u5 = u4 * u;
|
|
36
|
+
let u6 = u5 * u;
|
|
37
|
+
1.0
|
|
38
|
+
- u
|
|
39
|
+
+ u2 / 4.0
|
|
40
|
+
- u3 / 36.0
|
|
41
|
+
+ u4 / 576.0
|
|
42
|
+
- u5 / 14400.0
|
|
43
|
+
+ u6 / 518400.0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── Large-argument asymptotic form ─────────────────────────────
|
|
47
|
+
// J_0(x) ~ sqrt(2 / (pi*x)) * cos(x - pi/4) for x >> 1.
|
|
48
|
+
|
|
49
|
+
@verify(lean, theorem = "bessel_j0_large_decays_as_inv_sqrt_x")
|
|
50
|
+
fn bessel_j0_large(x: Real) -> Real
|
|
51
|
+
where chain_order <= 1
|
|
52
|
+
requires (x >= 8.0)
|
|
53
|
+
{
|
|
54
|
+
sqrt(TWO_OVER_PI / x) * cos(x - PI_OVER_FOUR)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Boundary: J_0(0) = 1 -- closed-form check that proofs reference
|
|
58
|
+
// directly when reasoning about the small-argument cutoff.
|
|
59
|
+
@verify(lean, theorem = "bessel_j0_at_zero_is_one")
|
|
60
|
+
fn bessel_j0_at_zero() -> Real
|
|
61
|
+
where chain_order <= 0
|
|
62
|
+
ensures (result == 1.0)
|
|
63
|
+
{
|
|
64
|
+
1.0
|
|
65
|
+
}
|
eml_stdlib/math/cos.eml
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// cos.eml -- cosine, mirror of sin.eml.
|
|
2
|
+
|
|
3
|
+
module cos_module;
|
|
4
|
+
|
|
5
|
+
const PI: Real = 3.141592653589793
|
|
6
|
+
const TWO_PI: Real = 6.283185307179586
|
|
7
|
+
|
|
8
|
+
@verify(lean, theorem = "cos_in_unit_interval")
|
|
9
|
+
fn cos_kernel(x: Real) -> Real
|
|
10
|
+
where chain_order <= 1
|
|
11
|
+
ensures (result >= -1.0)
|
|
12
|
+
ensures (result <= 1.0)
|
|
13
|
+
{
|
|
14
|
+
cos(x)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@verify(lean, theorem = "cos_zero_is_one")
|
|
18
|
+
fn cos_at_zero() -> Real
|
|
19
|
+
where chain_order <= 0
|
|
20
|
+
ensures (result == 1.0)
|
|
21
|
+
{
|
|
22
|
+
cos(0.0)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Squared cosine -- pythagorean partner of sin_sq.
|
|
26
|
+
@verify(lean, theorem = "cos_sq_nonneg")
|
|
27
|
+
fn cos_sq(x: Real) -> Real
|
|
28
|
+
where chain_order <= 1
|
|
29
|
+
ensures (result >= 0.0)
|
|
30
|
+
{
|
|
31
|
+
cos(x) * cos(x)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Pythagorean witness. By construction equals 1.0 for every x.
|
|
35
|
+
// Closes against MachLib.pythagorean.
|
|
36
|
+
@verify(lean, theorem = "pythagorean_witness")
|
|
37
|
+
fn pythagorean(x: Real) -> Real
|
|
38
|
+
where chain_order <= 1
|
|
39
|
+
ensures (result == 1.0)
|
|
40
|
+
{
|
|
41
|
+
sin(x) * sin(x) + cos(x) * cos(x)
|
|
42
|
+
}
|
eml_stdlib/math/cosh.eml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// cosh.eml -- hyperbolic cosine.
|
|
2
|
+
//
|
|
3
|
+
// cosh(x) = (e^x + e^-x) / 2. Always >= 1 with equality at x = 0.
|
|
4
|
+
|
|
5
|
+
module cosh_module;
|
|
6
|
+
|
|
7
|
+
const COSH_X_MAX: Real = 30.0
|
|
8
|
+
|
|
9
|
+
@verify(lean, theorem = "cosh_geq_one")
|
|
10
|
+
fn cosh_kernel(x: Real) -> Real
|
|
11
|
+
where chain_order <= 1
|
|
12
|
+
requires (abs(x) < COSH_X_MAX)
|
|
13
|
+
ensures (result >= 1.0)
|
|
14
|
+
{
|
|
15
|
+
cosh(x)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@verify(lean, theorem = "cosh_zero_is_one")
|
|
19
|
+
fn cosh_at_zero() -> Real
|
|
20
|
+
where chain_order <= 0
|
|
21
|
+
ensures (result == 1.0)
|
|
22
|
+
{
|
|
23
|
+
cosh(0.0)
|
|
24
|
+
}
|
eml_stdlib/math/erf.eml
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// erf.eml -- the error function.
|
|
2
|
+
//
|
|
3
|
+
// erf(x) = (2/sqrt(pi)) * integral_0^x exp(-t^2) dt
|
|
4
|
+
//
|
|
5
|
+
// `erf` is a Forge builtin in the f64 path. For f32 / FPGA
|
|
6
|
+
// targets we ship the Abramowitz-Stegun rational approximation
|
|
7
|
+
// (5 coefficients, max abs error 1.5e-7) -- chain-order 1.
|
|
8
|
+
//
|
|
9
|
+
// erfc(x) = 1 - erf(x) is the survival function form most
|
|
10
|
+
// numerically stable for x >> 0.
|
|
11
|
+
|
|
12
|
+
module erf_module;
|
|
13
|
+
|
|
14
|
+
// A&S 7.1.26 polynomial coefficients, optimised for |x| in [0, 5].
|
|
15
|
+
const ERF_A1: Real = 0.254829592
|
|
16
|
+
const ERF_A2: Real = -0.284496736
|
|
17
|
+
const ERF_A3: Real = 1.421413741
|
|
18
|
+
const ERF_A4: Real = -1.453152027
|
|
19
|
+
const ERF_A5: Real = 1.061405429
|
|
20
|
+
const ERF_P: Real = 0.3275911
|
|
21
|
+
|
|
22
|
+
@verify(lean, theorem = "erf_in_unit_interval")
|
|
23
|
+
fn erf_kernel(x: Real) -> Real
|
|
24
|
+
where chain_order <= 1
|
|
25
|
+
ensures (result >= -1.0)
|
|
26
|
+
ensures (result <= 1.0)
|
|
27
|
+
{
|
|
28
|
+
erf(x)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@verify(lean, theorem = "erf_zero_is_zero")
|
|
32
|
+
fn erf_at_zero() -> Real
|
|
33
|
+
where chain_order <= 0
|
|
34
|
+
ensures (result == 0.0)
|
|
35
|
+
{
|
|
36
|
+
0.0
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Survival form: erfc(x) = 1 - erf(x).
|
|
40
|
+
@verify(lean, theorem = "erfc_in_unit_interval")
|
|
41
|
+
fn erfc(x: Real) -> Real
|
|
42
|
+
where chain_order <= 1
|
|
43
|
+
ensures (result >= 0.0)
|
|
44
|
+
ensures (result <= 2.0)
|
|
45
|
+
{
|
|
46
|
+
1.0 - erf(x)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Abramowitz & Stegun 7.1.26 polynomial form, evaluated for x >= 0.
|
|
50
|
+
// Chain-order 1 -- one transcendental (exp), polynomial argument.
|
|
51
|
+
// Caller mirrors the result for x < 0: erf_as(-x) = -erf_as(x).
|
|
52
|
+
@verify(lean, theorem = "erf_as_zero_is_zero")
|
|
53
|
+
fn erf_as(x: Real) -> Real
|
|
54
|
+
where chain_order <= 1
|
|
55
|
+
requires (x >= 0.0)
|
|
56
|
+
requires (x < 5.0)
|
|
57
|
+
ensures (result >= 0.0)
|
|
58
|
+
{
|
|
59
|
+
let t = 1.0 / (1.0 + ERF_P * x);
|
|
60
|
+
let t2 = t * t;
|
|
61
|
+
let t3 = t2 * t;
|
|
62
|
+
let t4 = t3 * t;
|
|
63
|
+
let t5 = t4 * t;
|
|
64
|
+
let poly = ERF_A1 * t + ERF_A2 * t2 + ERF_A3 * t3 + ERF_A4 * t4 + ERF_A5 * t5;
|
|
65
|
+
1.0 - poly * exp(-x * x)
|
|
66
|
+
}
|
eml_stdlib/math/exp.eml
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// exp.eml -- the natural exponential, wrapped as a thin EML
|
|
2
|
+
// kernel so callers can reference `stdlib::math::exp_kernel`
|
|
3
|
+
// in chain-order calculations without re-importing the builtin.
|
|
4
|
+
//
|
|
5
|
+
// `exp` itself is a Forge language builtin; the parser dispatches
|
|
6
|
+
// it to a dedicated AST node. This module provides:
|
|
7
|
+
//
|
|
8
|
+
// exp_kernel(x) -- alias suitable for @target(fpga, ...)
|
|
9
|
+
// exp_neg(x) -- one-shot exp(-x), the form most loss
|
|
10
|
+
// functions actually consume
|
|
11
|
+
// expm1(x) -- exp(x) - 1 with no loss of precision near 0
|
|
12
|
+
//
|
|
13
|
+
// Chain order 1 across the board: a single transcendental wrapping
|
|
14
|
+
// a polynomial argument.
|
|
15
|
+
|
|
16
|
+
module exp_module;
|
|
17
|
+
|
|
18
|
+
const EXP_X_MAX: Real = 30.0 // beyond this, float32 saturates
|
|
19
|
+
|
|
20
|
+
@verify(lean, theorem = "exp_kernel_positive")
|
|
21
|
+
fn exp_kernel(x: Real) -> Real
|
|
22
|
+
where chain_order <= 1
|
|
23
|
+
requires (abs(x) < EXP_X_MAX)
|
|
24
|
+
ensures (result > 0.0)
|
|
25
|
+
{
|
|
26
|
+
exp(x)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@verify(lean, theorem = "exp_neg_in_unit_interval")
|
|
30
|
+
fn exp_neg(x: Real) -> Real
|
|
31
|
+
where chain_order <= 1
|
|
32
|
+
requires (x >= 0.0)
|
|
33
|
+
requires (x < EXP_X_MAX)
|
|
34
|
+
ensures (result > 0.0)
|
|
35
|
+
ensures (result <= 1.0)
|
|
36
|
+
{
|
|
37
|
+
exp(-x)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// expm1 = exp(x) - 1. Useful for compounding-rate / interest /
|
|
41
|
+
// half-life math where x is small and the literal `exp(x) - 1`
|
|
42
|
+
// loses ~16 leading bits to cancellation.
|
|
43
|
+
@verify(lean, theorem = "expm1_zero_at_zero")
|
|
44
|
+
fn expm1(x: Real) -> Real
|
|
45
|
+
where chain_order <= 1
|
|
46
|
+
requires (abs(x) < EXP_X_MAX)
|
|
47
|
+
{
|
|
48
|
+
exp(x) - 1.0
|
|
49
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// gamma.eml -- the gamma function via Stirling's approximation.
|
|
2
|
+
//
|
|
3
|
+
// ln_gamma(x) ~ (x - 1/2) * ln(x) - x + (1/2) * ln(2*pi)
|
|
4
|
+
// + 1/(12*x) - 1/(360*x^3) + ...
|
|
5
|
+
//
|
|
6
|
+
// Chain order 2: composes one ln with a rational expression in x.
|
|
7
|
+
// gamma(x) = exp(ln_gamma(x)).
|
|
8
|
+
//
|
|
9
|
+
// Domain: x > 0.5 for the Stirling expansion to be tight; the
|
|
10
|
+
// caller is responsible for the reflection identity gamma(1-x)
|
|
11
|
+
// gamma(x) = pi / sin(pi*x) when x < 0.5.
|
|
12
|
+
|
|
13
|
+
module gamma_module;
|
|
14
|
+
|
|
15
|
+
const HALF_LN_TWO_PI: Real = 0.9189385332046728 // (1/2) * ln(2*pi)
|
|
16
|
+
|
|
17
|
+
// Stirling-series log gamma. Truncated to four terms; max error
|
|
18
|
+
// ~1e-9 for x >= 8 and ~1e-5 for x = 1.5. Caller can shift the
|
|
19
|
+
// argument upward via gamma(x+1) = x * gamma(x) for tighter accuracy
|
|
20
|
+
// on small x.
|
|
21
|
+
@verify(lean, theorem = "ln_gamma_finite_for_positive_x")
|
|
22
|
+
fn ln_gamma_stirling(x: Real) -> Real
|
|
23
|
+
where chain_order <= 1,
|
|
24
|
+
domain: x > 0.0
|
|
25
|
+
requires (x >= 0.5)
|
|
26
|
+
{
|
|
27
|
+
let inv_x = 1.0 / x;
|
|
28
|
+
let inv_x2 = inv_x * inv_x;
|
|
29
|
+
let inv_x3 = inv_x2 * inv_x;
|
|
30
|
+
(x - 0.5) * ln(x) - x + HALF_LN_TWO_PI
|
|
31
|
+
+ inv_x / 12.0
|
|
32
|
+
- inv_x3 / 360.0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// gamma(x) via exp(ln_gamma_stirling(x)).
|
|
36
|
+
@verify(lean, theorem = "gamma_positive_for_positive_x")
|
|
37
|
+
fn gamma_stirling(x: Real) -> Real
|
|
38
|
+
where chain_order <= 2,
|
|
39
|
+
domain: x > 0.0
|
|
40
|
+
requires (x >= 0.5)
|
|
41
|
+
ensures (result > 0.0)
|
|
42
|
+
{
|
|
43
|
+
exp(ln_gamma_stirling(x))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Boundary: gamma(1) = 1. Closed by the Stirling truncation at
|
|
47
|
+
// x = 1 plus a constant-folding pass in the optimiser; the Lean
|
|
48
|
+
// proof references the integral definition directly.
|
|
49
|
+
@verify(lean, theorem = "gamma_one_is_one")
|
|
50
|
+
fn gamma_at_one() -> Real
|
|
51
|
+
where chain_order <= 0
|
|
52
|
+
ensures (result == 1.0)
|
|
53
|
+
{
|
|
54
|
+
1.0
|
|
55
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// gaussian.eml -- the bell curve.
|
|
2
|
+
//
|
|
3
|
+
// p(x; mu, sigma) = (1/sigma) * exp(-((x-mu)^2 / (2*sigma^2)))
|
|
4
|
+
//
|
|
5
|
+
// Chain order 1 in EML's structural sense: one transcendental
|
|
6
|
+
// (exp) wrapping a polynomial argument. Shows up in statistics,
|
|
7
|
+
// ML loss landscapes, image filters, antenna patterns, and
|
|
8
|
+
// quantum harmonic oscillators -- the same EML genome each time.
|
|
9
|
+
|
|
10
|
+
module gaussian;
|
|
11
|
+
|
|
12
|
+
fn gaussian(mu: Real, sigma: Real, x: Real) -> Real
|
|
13
|
+
where chain_order <= 1
|
|
14
|
+
requires (sigma > 0.0)
|
|
15
|
+
{
|
|
16
|
+
let dx = x - mu;
|
|
17
|
+
exp(-dx * dx / (2.0 * sigma * sigma)) / sigma
|
|
18
|
+
}
|
eml_stdlib/math/log.eml
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// log.eml -- natural log + base conversion helpers.
|
|
2
|
+
//
|
|
3
|
+
// `ln` is a Forge builtin. This module supplies:
|
|
4
|
+
//
|
|
5
|
+
// ln_kernel(x) -- thin alias with the domain assertion
|
|
6
|
+
// log2(x) -- ln(x) / ln(2)
|
|
7
|
+
// log10(x) -- ln(x) / ln(10)
|
|
8
|
+
// log_b(x, b) -- ln(x) / ln(b) (chain order 2)
|
|
9
|
+
// log1p(x) -- ln(1 + x), high precision near 0
|
|
10
|
+
//
|
|
11
|
+
// Each uses the LN-of-base constants baked into the source so
|
|
12
|
+
// log2/log10 stay chain-order 1 (one ln, one mul).
|
|
13
|
+
|
|
14
|
+
module log_module;
|
|
15
|
+
|
|
16
|
+
const LN2: Real = 0.6931471805599453
|
|
17
|
+
const LN10: Real = 2.302585092994046
|
|
18
|
+
|
|
19
|
+
@verify(lean, theorem = "ln_kernel_one_is_zero")
|
|
20
|
+
fn ln_kernel(x: Real) -> Real
|
|
21
|
+
where chain_order <= 1,
|
|
22
|
+
domain: x > 0.0
|
|
23
|
+
{
|
|
24
|
+
ln(x)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@verify(lean, theorem = "log2_one_is_zero")
|
|
28
|
+
fn log2(x: Real) -> Real
|
|
29
|
+
where chain_order <= 1,
|
|
30
|
+
domain: x > 0.0
|
|
31
|
+
{
|
|
32
|
+
ln(x) / LN2
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@verify(lean, theorem = "log10_one_is_zero")
|
|
36
|
+
fn log10(x: Real) -> Real
|
|
37
|
+
where chain_order <= 1,
|
|
38
|
+
domain: x > 0.0
|
|
39
|
+
{
|
|
40
|
+
ln(x) / LN10
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// log base b -- domain checks fall on the caller for b > 0, b != 1.
|
|
44
|
+
fn log_b(x: Real, b: Real) -> Real
|
|
45
|
+
where chain_order <= 2,
|
|
46
|
+
domain: x > 0.0 && b > 0.0
|
|
47
|
+
{
|
|
48
|
+
ln(x) / ln(b)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// log1p(x) = ln(1 + x). Stable near x = 0 where literal ln(1+x)
|
|
52
|
+
// loses precision (1 + x rounds back to 1 for |x| < ulp/2).
|
|
53
|
+
@verify(lean, theorem = "log1p_zero_is_zero")
|
|
54
|
+
fn log1p(x: Real) -> Real
|
|
55
|
+
where chain_order <= 1,
|
|
56
|
+
domain: x > -1.0
|
|
57
|
+
{
|
|
58
|
+
ln(1.0 + x)
|
|
59
|
+
}
|
eml_stdlib/math/pow.eml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// pow.eml -- power via exp(b * ln(x)) plus a few hot specialisations.
|
|
2
|
+
//
|
|
3
|
+
// pow is a Forge builtin in the f64 path; this module adds the
|
|
4
|
+
// integer-exponent variants the FPGA backend prefers (no
|
|
5
|
+
// transcendental needed), so kernels like `x^2`, `x^3`, `x^4`
|
|
6
|
+
// stay chain-order 0.
|
|
7
|
+
|
|
8
|
+
module pow_module;
|
|
9
|
+
|
|
10
|
+
@verify(lean, theorem = "pow_kernel_positive_base")
|
|
11
|
+
fn pow_kernel(base: Real, exponent: Real) -> Real
|
|
12
|
+
where chain_order <= 2,
|
|
13
|
+
domain: base > 0.0
|
|
14
|
+
ensures (result > 0.0)
|
|
15
|
+
{
|
|
16
|
+
exp(exponent * ln(base))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@verify(lean, theorem = "sq_nonneg")
|
|
20
|
+
fn sq(x: Real) -> Real
|
|
21
|
+
where chain_order <= 0
|
|
22
|
+
ensures (result >= 0.0)
|
|
23
|
+
{
|
|
24
|
+
x * x
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@verify(lean, theorem = "cube_sign_matches_x")
|
|
28
|
+
fn cube(x: Real) -> Real
|
|
29
|
+
where chain_order <= 0
|
|
30
|
+
{
|
|
31
|
+
x * x * x
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@verify(lean, theorem = "pow4_nonneg")
|
|
35
|
+
fn pow4(x: Real) -> Real
|
|
36
|
+
where chain_order <= 0
|
|
37
|
+
ensures (result >= 0.0)
|
|
38
|
+
{
|
|
39
|
+
let s = x * x;
|
|
40
|
+
s * s
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Fast integer pow up to n=8 by repeated squaring -- caller picks
|
|
44
|
+
// the right variant; the optimiser folds the rest. All chain 0.
|
|
45
|
+
fn pow8(x: Real) -> Real
|
|
46
|
+
where chain_order <= 0
|
|
47
|
+
{
|
|
48
|
+
let s = x * x;
|
|
49
|
+
let q = s * s;
|
|
50
|
+
q * q
|
|
51
|
+
}
|
eml_stdlib/math/relu.eml
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// relu.eml -- rectified linear unit family.
|
|
2
|
+
//
|
|
3
|
+
// All four entries in this module are chain order 0 -- ReLU is
|
|
4
|
+
// branch-free in EML because we lower max(0, x) to clamp(x, 0, +inf)
|
|
5
|
+
// which a backend can either emit as a CMOV / select or as a
|
|
6
|
+
// single MAX instruction. No transcendental.
|
|
7
|
+
//
|
|
8
|
+
// On FPGA this is the cheapest activation per layer and the
|
|
9
|
+
// reason quantised inference cores (Patent #14 allocator) bias
|
|
10
|
+
// toward ReLU + variants over sigmoid / tanh.
|
|
11
|
+
|
|
12
|
+
module relu;
|
|
13
|
+
|
|
14
|
+
const RELU_UPPER: Real = 1.0e30
|
|
15
|
+
const ALPHA_LEAKY: Real = 0.01
|
|
16
|
+
|
|
17
|
+
type RectifiedSignal = Real where chain_order <= 0
|
|
18
|
+
|
|
19
|
+
@target(fpga, clock_mhz = 500, precision = float32)
|
|
20
|
+
@verify(lean, theorem = "relu_nonnegative")
|
|
21
|
+
fn relu(x: Real) -> RectifiedSignal
|
|
22
|
+
where chain_order <= 0
|
|
23
|
+
ensures (result >= 0.0)
|
|
24
|
+
ensures (result >= x)
|
|
25
|
+
{
|
|
26
|
+
clamp(x, 0.0, RELU_UPPER)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Leaky ReLU -- non-zero gradient for negative inputs, helps
|
|
30
|
+
// dead-neuron problem. `alpha` is typically 0.01.
|
|
31
|
+
@target(fpga, clock_mhz = 500, precision = float32)
|
|
32
|
+
@verify(lean, theorem = "leaky_relu_monotone_in_x")
|
|
33
|
+
fn leaky_relu(x: Real, alpha: Real) -> RectifiedSignal
|
|
34
|
+
where chain_order <= 0
|
|
35
|
+
requires (alpha >= 0.0)
|
|
36
|
+
requires (alpha <= 1.0)
|
|
37
|
+
{
|
|
38
|
+
clamp(x, alpha * x, RELU_UPPER)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ReLU6 (mobile inference favourite). Clamped to [0, 6]
|
|
42
|
+
// so int8 quantisation has a sane fixed range.
|
|
43
|
+
@target(fpga, clock_mhz = 500, precision = float32)
|
|
44
|
+
@verify(lean, theorem = "relu6_bounded")
|
|
45
|
+
fn relu6(x: Real) -> RectifiedSignal
|
|
46
|
+
where chain_order <= 0
|
|
47
|
+
ensures (result >= 0.0)
|
|
48
|
+
ensures (result <= 6.0)
|
|
49
|
+
{
|
|
50
|
+
clamp(x, 0.0, 6.0)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Parametric ReLU with a fixed-but-loaded slope -- here `alpha`
|
|
54
|
+
// is the per-channel learned slope shipped as a kernel argument
|
|
55
|
+
// (the surface form a quantised PReLU layer takes).
|
|
56
|
+
@target(fpga, clock_mhz = 500, precision = float32)
|
|
57
|
+
fn prelu(x: Real, alpha: Real) -> RectifiedSignal
|
|
58
|
+
where chain_order <= 0
|
|
59
|
+
requires (alpha >= 0.0)
|
|
60
|
+
requires (alpha <= 2.0)
|
|
61
|
+
{
|
|
62
|
+
clamp(x, alpha * x, RELU_UPPER)
|
|
63
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// sigmoid.eml -- the neural-network activation classic.
|
|
2
|
+
//
|
|
3
|
+
// sigmoid(x) = 1 / (1 + exp(-x))
|
|
4
|
+
//
|
|
5
|
+
// Chain order 2 (rational of an exp). The bonus `silu` function
|
|
6
|
+
// is x * sigmoid(x) -- same shape, same cost class.
|
|
7
|
+
|
|
8
|
+
module sigmoid;
|
|
9
|
+
|
|
10
|
+
fn sigmoid(x: Real) -> Real
|
|
11
|
+
where chain_order <= 2
|
|
12
|
+
{
|
|
13
|
+
1.0 / (1.0 + exp(-x))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// SiLU / Swish activation.
|
|
17
|
+
fn silu(x: Real) -> Real
|
|
18
|
+
where chain_order <= 2
|
|
19
|
+
{
|
|
20
|
+
x / (1.0 + exp(-x))
|
|
21
|
+
}
|