fixed

Pure Haskell large fixed-width integers and Montgomery arithmetic.
git clone git://git.ppad.tech/fixed.git
Log | Files | Refs | README | LICENSE

commit 1d4f621a15601f53d8690f4fbe8765a7290ebe97
parent 7d533266b4b52a38607b087a9b8bad3ef794c558
Author: Jared Tobin <jared@jtobin.io>
Date:   Sat, 27 Dec 2025 17:25:59 -0330

lib: choice module docs

Diffstat:
Mlib/Data/Choice.hs | 27++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/lib/Data/Choice.hs b/lib/Data/Choice.hs @@ -12,6 +12,13 @@ -- Maintainer: Jared Tobin <jared@ppad.tech> -- -- Primitives for constant-time choice. +-- +-- The 'Choice' type encodes truthy and falsy values as unboxed 'Word#' +-- bit masks. You should convert it to a 'Bool' using 'decide' at the /end/ +-- of a computation that you want to run in constant time. +-- +-- Use the standard logical primitives ('or', 'and', 'xor', 'not', eq') to +-- manipulate "in-flight" 'Choice' values. module Data.Choice ( -- * Choice @@ -126,6 +133,12 @@ decide (Choice c) = Exts.isTrue# (Exts.neWord# c 0##) {-# INLINE decide #-} -- | Convert a 'Choice' to an unboxed 'Word#'. +-- +-- This essentially "unboxes" the 'Choice' for direct manipulation. +-- +-- >>> import qualified GHC.Exts as Exts +-- >>> Exts.isTrue# (Exts.eqWord# 0## (to_word# (false# ()))) +-- True to_word# :: Choice -> Word# to_word# (Choice c) = Exts.and# c 1## {-# INLINE to_word# #-} @@ -230,9 +243,9 @@ from_word_gt# x y = from_word_lt# y x -- | Logically negate a 'Choice'. -- --- >>> C.decide (C.not (C.true# ())) +-- >>> decide (not (true# ())) -- False --- >>> C.decide (C.not (C.false# ())) +-- >>> decide (not (false# ())) -- True not :: Choice -> Choice not (Choice w) = Choice (Exts.not# w) @@ -240,7 +253,7 @@ not (Choice w) = Choice (Exts.not# w) -- | Logical disjunction on 'Choice' values. -- --- >>> C.decide (C.or (C.true# ()) (C.false# ())) +-- >>> decide (or (true# ()) (false# ())) -- True or :: Choice -> Choice -> Choice or (Choice w0) (Choice w1) = Choice (Exts.or# w0 w1) @@ -248,7 +261,7 @@ or (Choice w0) (Choice w1) = Choice (Exts.or# w0 w1) -- | Logical conjunction on 'Choice' values. -- --- >>> C.decide (C.and (C.true# ()) (C.false# ())) +-- >>> decide (and (true# ()) (false# ())) -- False and :: Choice -> Choice -> Choice and (Choice w0) (Choice w1) = Choice (Exts.and# w0 w1) @@ -256,7 +269,7 @@ and (Choice w0) (Choice w1) = Choice (Exts.and# w0 w1) -- | Logical inequality on 'Choice' values. -- --- >>> C.decide (C.xor (C.true# ()) (C.false# ())) +-- >>> decide (xor (true# ()) (false# ())) -- True xor :: Choice -> Choice -> Choice xor (Choice w0) (Choice w1) = Choice (Exts.xor# w0 w1) @@ -264,7 +277,7 @@ xor (Choice w0) (Choice w1) = Choice (Exts.xor# w0 w1) -- | Logical inequality on 'Choice' values. -- --- >>> C.decide (C.ne (C.true# ()) (C.false# ())) +-- >>> decide (ne (true# ()) (false# ())) -- True ne :: Choice -> Choice -> Choice ne c0 c1 = xor c0 c1 @@ -272,7 +285,7 @@ ne c0 c1 = xor c0 c1 -- | Logical equality on 'Choice' values. -- --- >>> C.decide (C.eq (C.true# ()) (C.false# ())) +-- >>> decide (eq (true# ()) (false# ())) -- False eq :: Choice -> Choice -> Choice eq c0 c1 = not (ne c0 c1)