open LanguagePrimitives // A simple trick enables genericity below: In F#, the shift amount // takes into account the lowest bits only. Therefore, shifting right by -1 // results in the maximum shift and the sign bit gets propagated to the whole word. /// Maximum of zero and the argument for signed integers. A special version using bit manipulation tricks. let inline maxi0 x = x &&& ~~~(x >>> -1) /// Minimum of zero and the argument for signed integers. A special version using bit manipulation tricks. let inline mini0 x = x &&& (x >>> -1) /// Maximum function for signed integers. A special version using bit manipulation tricks. /// Has limited numerical range: requires that a - b is representable. let inline maxi (a : 'a) (b : 'a) : 'a = maxi0 (a - b) + b /// Minimum function for signed integers. A special version using bit manipulation tricks. /// Has limited numerical range: requires that a - b is representable. let inline mini (a : 'a) (b : 'a) : 'a = mini0 (a - b) + b /// Clamps signed integer x to [a, b] (a <= b). A special version using bit manipulation tricks. /// Has limited numerical range: requires that a - b, a - x and b - x are representable. let inline clampi (a : 'a) (b : 'a) (x : 'a) : 'a = maxi a (mini b x) /// Sign function for signed integers that uses bit manipulation tricks. let inline signi (x : 'a) : 'a = ((-x >>> -1) &&& GenericOne) + (x >>> -1) /// Absolute function for signed integers. A special version using bit manipulation tricks. /// The smallest signed value cannot be negated; the standard function raises an exception, /// whereas we return it unchanged. let inline absi (x : 'a) : 'a = let y = x >>> -1 in (x &&& ~~~y) - (x &&& y) /// Negative indicator function for signed integers. Returns 1 if x < 0, and 0 otherwise. let inline negativei x = (x >>> -1) &&& GenericOne /// Positive indicator function for signed integers. Returns 1 if x > 0, and 0 otherwise. let inline positivei x = (-x >>> -1) &&& GenericOne