(* Resets the state when the reset signal has a rising edge *)
(* y(0) = false y(n) = not (x(n-1)) & x(n) *)
let node rising_bool(x) = y where
  rec y = false -> not (pre x) & x

(* Resets the state when the reset signal has a falling edge *)
let node falling_bool(x) = rising_bool(not x)

let node either_bool(x) = rising_bool(x) or falling_bool(x)
  
(* Resets and holds the output to the initial condition while
 * the reset signal is nonzero *)
let node level_bool(x) = l where
  rec l = x or (false fby x) & (not x)

(* Resets the output to the initial condition
 * when the reset signal is nonzero *)
let node sampled_level_bool(x) = x
    
(* 
For a floatting point signal, if we follow Simulink documentation,
we get:

https://fr.mathworks.com/help/simulink/slref/discretetimeintegrator.html

with a note that ``For the discrete-time integrator block, all trigger
detections are based on signals with positive values.''

*)

let node rising_float(x) = r where
  rec r = (false fby (x < 0.0)) & (x >= 0.0)

let node strictly_rising_float(x) = r where
  rec r = (false fby (x <= 0.0)) & (x > 0.0)

let node falling_float(x) = r where
  rec r = (false fby (x > 0.0)) & (x <= 0.0)

let node strictly_falling_float(x) = r where
  rec r = (false fby (x >= 0.0)) & (x < 0.0)

(* Resets and holds the output to the initial condition while
 * the reset signal is nonzero *)
let node level(x) = l where
  rec z = (x = 0.0)
  and l = (x >= 0.0) & (not z or ((false fby not z) & z))

(* Resets the output to the initial condition
 * when the reset signal is nonzero *)

let node sampled_level(x) = (x > 0.0)