Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
1fc21753
by Sylvain Henry at 2026-05-29T13:18:14-04:00
-
717059df
by Sylvain Henry at 2026-05-29T13:18:14-04:00
-
4bb3b1d8
by Sylvain Henry at 2026-05-29T13:18:14-04:00
18 changed files:
- + changelog.d/remove-bignum-check-backend
- + changelog.d/remove-bignum-ffi-backend
- hadrian/README.md
- hadrian/doc/user-settings.md
- hadrian/src/CommandLine.hs
- hadrian/src/Flavour/Type.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghc-bignum/ghc-bignum.cabal
- libraries/ghc-internal/bignum-backend.rst
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Check.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/FFI.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- − libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Selected.hs
Changes:
| 1 | +section: packaging
|
|
| 2 | +synopsis: Remove the Check backend of ghc-bignum
|
|
| 3 | +issues: #27305
|
|
| 4 | +mrs: !16106
|
|
| 5 | + |
|
| 6 | +description: {
|
|
| 7 | + The Check backend of ghc-bignum (now part of ghc-internal), which compared
|
|
| 8 | + the results of the selected backend against the Native backend, has been
|
|
| 9 | + removed along with the ``bignum-check`` cabal flag and the ``check-``
|
|
| 10 | + prefix in Hadrian's ``--bignum`` option.
|
|
| 11 | +} |
| 1 | +section: packaging
|
|
| 2 | +synopsis: Remove the FFI backend of ghc-bignum
|
|
| 3 | +issues: #27305
|
|
| 4 | +mrs: !16106
|
|
| 5 | + |
|
| 6 | +description: {
|
|
| 7 | + The FFI backend of ghc-bignum (now part of ghc-internal) has been removed.
|
|
| 8 | + It had no known users and was easy to recreate by relinking ghc-internal
|
|
| 9 | + with a custom backend implementation. As a result, the ``bignum-ffi``
|
|
| 10 | + cabal flag has been dropped, and selecting the ``ffi`` backend via
|
|
| 11 | + Hadrian's ``--bignum`` option is no longer supported.
|
|
| 12 | +} |
| ... | ... | @@ -101,7 +101,7 @@ Stage2 GHC. |
| 101 | 101 | |
| 102 | 102 | * `--skip-depends`: skips rebuilding Haskell module dependency files.
|
| 103 | 103 | |
| 104 | -* `--bignum={native,gmp,check-gmp,ffi}`: **Deprecated.** Use the `+native_bignum` flavour
|
|
| 104 | +* `--bignum={native,gmp}`: **Deprecated.** Use the `+native_bignum` flavour
|
|
| 105 | 105 | transformer instead (e.g. `--flavour=default+native_bignum`). When building for the
|
| 106 | 106 | JavaScript target, the native bignum backend is enabled automatically.
|
| 107 | 107 |
| ... | ... | @@ -24,10 +24,8 @@ data Flavour = Flavour { |
| 24 | 24 | extraArgs :: Args,
|
| 25 | 25 | -- | Build these packages.
|
| 26 | 26 | packages :: Stage -> Action [Package],
|
| 27 | - -- | Bignum backend: 'native', 'gmp', 'ffi', etc.
|
|
| 27 | + -- | Bignum backend: 'native', 'gmp', etc.
|
|
| 28 | 28 | bignumBackend :: String,
|
| 29 | - -- | Check selected bignum backend against native backend
|
|
| 30 | - bignumCheck :: Bool,
|
|
| 31 | 29 | -- | Build the @text@ package with @simdutf@ support. Disabled by
|
| 32 | 30 | -- default due to packaging difficulties described in #20724.
|
| 33 | 31 | textWithSIMDUTF :: Bool,
|
| 1 | 1 | module CommandLine (
|
| 2 | 2 | optDescrs, cmdLineArgsMap, cmdFlavour, lookupFreeze1, lookupFreeze2, lookupSkipDepends,
|
| 3 | 3 | lookupBignum,
|
| 4 | - cmdBignum, cmdBignumCheck, cmdProgressInfo, cmdCompleteSetting,
|
|
| 4 | + cmdBignum, cmdProgressInfo, cmdCompleteSetting,
|
|
| 5 | 5 | cmdDocsArgs, cmdUnitIdHash, lookupBuildRoot, TestArgs(..), TestSpeed(..), defaultTestArgs,
|
| 6 | 6 | cmdPrefix, cmdChangelogVersion, DocArgs(..), defaultDocArgs,
|
| 7 | 7 | cmdKeepResponseFiles
|
| ... | ... | @@ -32,7 +32,6 @@ data CommandLineArgs = CommandLineArgs |
| 32 | 32 | , skipDepends :: Bool
|
| 33 | 33 | , unitIdHash :: Bool
|
| 34 | 34 | , bignum :: Maybe String
|
| 35 | - , bignumCheck :: Bool
|
|
| 36 | 35 | , progressInfo :: ProgressInfo
|
| 37 | 36 | , buildRoot :: BuildRoot
|
| 38 | 37 | , testArgs :: TestArgs
|
| ... | ... | @@ -54,7 +53,6 @@ defaultCommandLineArgs = CommandLineArgs |
| 54 | 53 | , skipDepends = False
|
| 55 | 54 | , unitIdHash = False
|
| 56 | 55 | , bignum = Nothing
|
| 57 | - , bignumCheck = False
|
|
| 58 | 56 | , progressInfo = Brief
|
| 59 | 57 | , buildRoot = BuildRoot "_build"
|
| 60 | 58 | , testArgs = defaultTestArgs
|
| ... | ... | @@ -132,10 +130,7 @@ readFlavour ms = Right $ \flags -> flags { flavour = lower <$> ms } |
| 132 | 130 | |
| 133 | 131 | readBignum :: Maybe String -> Either String (CommandLineArgs -> CommandLineArgs)
|
| 134 | 132 | readBignum Nothing = Right id
|
| 135 | -readBignum (Just ms) = Right $ \flags -> case break (== '-') (lower ms) of
|
|
| 136 | - (backend,"") -> flags { bignum = Just backend }
|
|
| 137 | - ("check",'-':backend) -> flags { bignum = Just backend, bignumCheck = True }
|
|
| 138 | - _ -> flags { bignum = Just (lower ms) }
|
|
| 133 | +readBignum (Just ms) = Right $ \flags -> flags { bignum = Just (lower ms) }
|
|
| 139 | 134 | |
| 140 | 135 | readBuildRoot :: FilePath -> Either String (CommandLineArgs -> CommandLineArgs)
|
| 141 | 136 | readBuildRoot ms =
|
| ... | ... | @@ -302,7 +297,7 @@ optDescrs = |
| 302 | 297 | , Option [] ["skip-depends"] (NoArg readSkipDepends)
|
| 303 | 298 | "Skip rebuilding dependency information."
|
| 304 | 299 | , Option [] ["bignum"] (OptArg readBignum "BACKEND")
|
| 305 | - "Select bignum backend: native, gmp (default), check-gmp (gmp compared to native), ffi."
|
|
| 300 | + "Select bignum backend: native, gmp (default)."
|
|
| 306 | 301 | , Option [] ["progress-info"] (ReqArg readProgressInfo "STYLE")
|
| 307 | 302 | "Progress info style (None, Brief, Normal or Unicorn)."
|
| 308 | 303 | , Option [] ["docs"] (ReqArg readDocsArg "TARGET")
|
| ... | ... | @@ -429,9 +424,6 @@ cmdUnitIdHash = unitIdHash <$> cmdLineArgs |
| 429 | 424 | cmdBignum :: Action (Maybe String)
|
| 430 | 425 | cmdBignum = bignum <$> cmdLineArgs
|
| 431 | 426 | |
| 432 | -cmdBignumCheck :: Action Bool
|
|
| 433 | -cmdBignumCheck = bignumCheck <$> cmdLineArgs
|
|
| 434 | - |
|
| 435 | 427 | cmdKeepResponseFiles :: Action Bool
|
| 436 | 428 | cmdKeepResponseFiles = keepResponseFiles <$> cmdLineArgs
|
| 437 | 429 |
| ... | ... | @@ -19,10 +19,8 @@ data Flavour = Flavour { |
| 19 | 19 | extraArgs :: Args,
|
| 20 | 20 | -- | Build these packages.
|
| 21 | 21 | packages :: Stage -> Action [Package],
|
| 22 | - -- | Bignum backend: 'native', 'gmp', 'ffi', etc.
|
|
| 22 | + -- | Bignum backend: 'native', 'gmp', etc.
|
|
| 23 | 23 | bignumBackend :: String,
|
| 24 | - -- | Check selected bignum backend against native backend
|
|
| 25 | - bignumCheck :: Bool,
|
|
| 26 | 24 | -- | Build the @text@ package with @simdutf@ support. Disabled by
|
| 27 | 25 | -- default due to packaging difficulties described in #20724.
|
| 28 | 26 | textWithSIMDUTF :: Bool,
|
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | module Settings (
|
| 4 | 4 | getExtraArgs, getArgs, getLibraryWays, getRtsWays, flavour, knownPackages,
|
| 5 | 5 | findPackageByName, unsafeFindPackageByName, unsafeFindPackageByPath,
|
| 6 | - isLibrary, stagePackages, getBignumBackend, getBignumCheck, completeSetting,
|
|
| 6 | + isLibrary, stagePackages, getBignumBackend, completeSetting,
|
|
| 7 | 7 | queryBuildTarget, queryHostTarget, queryTargetTarget,
|
| 8 | 8 | queryBuild, queryHost, queryTarget,
|
| 9 | 9 | queryArch, queryOS, queryVendor
|
| ... | ... | @@ -46,11 +46,6 @@ getRtsWays = expr flavour >>= rtsWays |
| 46 | 46 | getBignumBackend :: Expr String
|
| 47 | 47 | getBignumBackend = bignumBackend <$> expr flavour
|
| 48 | 48 | |
| 49 | -getBignumCheck :: Expr Bool
|
|
| 50 | -getBignumCheck = expr $ cmdBignum >>= \case
|
|
| 51 | - Nothing -> bignumCheck <$> flavour
|
|
| 52 | - Just _ -> cmdBignumCheck
|
|
| 53 | - |
|
| 54 | 49 | stagePackages :: Stage -> Action [Package]
|
| 55 | 50 | stagePackages stage = do
|
| 56 | 51 | f <- flavour
|
| ... | ... | @@ -241,7 +241,6 @@ runTestBuilderArgs = builder Testsuite ? do |
| 241 | 241 | |
| 242 | 242 | -- MP: TODO, these should be queried from the test compiler?
|
| 243 | 243 | bignumBackend <- getBignumBackend
|
| 244 | - bignumCheck <- getBignumCheck
|
|
| 245 | 244 | |
| 246 | 245 | keepFiles <- expr (testKeepFiles <$> userSetting defaultTestArgs)
|
| 247 | 246 | |
| ... | ... | @@ -307,7 +306,7 @@ runTestBuilderArgs = builder Testsuite ? do |
| 307 | 306 | , arg "-e", arg $ "ghc_compiler_always_flags=" ++ quote ghcFlags
|
| 308 | 307 | , arg "-e", arg $ asBool "ghc_with_dynamic_rts=" (hasDynamicRts)
|
| 309 | 308 | , arg "-e", arg $ asBool "config.ghc_with_threaded_rts=" (hasThreadedRts)
|
| 310 | - , arg "-e", arg $ asBool "config.have_fast_bignum=" (bignumBackend /= "native" && not bignumCheck)
|
|
| 309 | + , arg "-e", arg $ asBool "config.have_fast_bignum=" (bignumBackend /= "native")
|
|
| 311 | 310 | , arg "-e", arg $ asBool "config.target_has_smp=" targetWithSMP
|
| 312 | 311 | , arg "-e", arg $ "config.ghc_dynamic=" ++ show hasDynamic
|
| 313 | 312 | , arg "-e", arg $ "config.leading_underscore=" ++ show leadingUnderscore
|
| ... | ... | @@ -293,7 +293,6 @@ defaultFlavour = Flavour |
| 293 | 293 | , extraArgs = defaultExtraArgs
|
| 294 | 294 | , packages = defaultPackages
|
| 295 | 295 | , bignumBackend = defaultBignumBackend
|
| 296 | - , bignumCheck = False
|
|
| 297 | 296 | , textWithSIMDUTF = False
|
| 298 | 297 | , libraryWays = defaultLibraryWays
|
| 299 | 298 | , rtsWays = defaultRtsWays
|
| ... | ... | @@ -240,15 +240,11 @@ ghcInternalArgs = package ghcInternal ? do |
| 240 | 240 | includesGmp <- getSetting GmpIncludeDir
|
| 241 | 241 | |
| 242 | 242 | backend <- getBignumBackend
|
| 243 | - check <- getBignumCheck
|
|
| 244 | 243 | |
| 245 | 244 | mconcat
|
| 246 | 245 | [ -- select bignum backend
|
| 247 | 246 | builder (Cabal Flags) ? arg ("bignum-" <> backend)
|
| 248 | 247 | |
| 249 | - , -- check the selected backend against native backend
|
|
| 250 | - builder (Cabal Flags) ? check `cabalFlag` "bignum-check"
|
|
| 251 | - |
|
| 252 | 248 | -- backend specific
|
| 253 | 249 | , case backend of
|
| 254 | 250 | "gmp" -> mconcat
|
| ... | ... | @@ -36,7 +36,7 @@ library |
| 36 | 36 | GHC.Internal.Bignum.Primitives as GHC.Num.Primitives
|
| 37 | 37 | , GHC.Internal.Bignum.WordArray as GHC.Num.WordArray
|
| 38 | 38 | , GHC.Internal.Bignum.Backend as GHC.Num.Backend
|
| 39 | - , GHC.Internal.Bignum.Backend.Selected as GHC.Num.Backend.Selected
|
|
| 39 | + , GHC.Internal.Bignum.Backend as GHC.Num.Backend.Selected
|
|
| 40 | 40 | , GHC.Internal.Bignum.Backend.Native as GHC.Num.Backend.Native
|
| 41 | 41 | , GHC.Internal.Bignum.BigNat as GHC.Num.BigNat
|
| 42 | 42 | , GHC.Internal.Bignum.Natural as GHC.Num.Natural
|
| ... | ... | @@ -33,20 +33,9 @@ supported: |
| 33 | 33 | integer-simple package. The major difference is that it uses a much more
|
| 34 | 34 | efficient memory representation (integer-simple was based on Haskell lists)
|
| 35 | 35 | and that it allows a lot more code sharing between the different backends than
|
| 36 | - was previously possible between integer-gmp and integer-simple.
|
|
| 37 | - |
|
| 38 | -* FFI: an implementation that relies on external FFI calls. This backend can be
|
|
| 39 | - useful:
|
|
| 40 | - |
|
| 41 | - * for alternative GHC backends that target non native platforms (JavaScript,
|
|
| 42 | - JVM, etc.): the backend can dynamically match and rewrite the FFI calls in
|
|
| 43 | - order to call the appropriate platform specific BigNum API.
|
|
| 44 | -
|
|
| 45 | - * to test new native backends: just tweak the ghc-bignum build to link with
|
|
| 46 | - the native library providing the implementation of the FFI calls
|
|
| 47 | - |
|
| 48 | - Note that the FFI backend module contains the description of the interface
|
|
| 49 | - that needs to be implemented by every backend.
|
|
| 36 | + was previously possible between integer-gmp and integer-simple. The Native
|
|
| 37 | + backend module contains the description of the interface that needs to be
|
|
| 38 | + implemented by every backend.
|
|
| 50 | 39 | |
| 51 | 40 | This package has been designed to make the implementation of new backends
|
| 52 | 41 | relatively easy. Previously you had to implement the whole Integer/Natural
|
| ... | ... | @@ -56,21 +56,11 @@ Flag bignum-native |
| 56 | 56 | Manual: True
|
| 57 | 57 | Default: False
|
| 58 | 58 | |
| 59 | -Flag bignum-ffi
|
|
| 60 | - Description: Enable FFI bignum backend
|
|
| 61 | - Manual: True
|
|
| 62 | - Default: False
|
|
| 63 | - |
|
| 64 | 59 | Flag bignum-gmp
|
| 65 | 60 | Description: Enable GMP bignum backend
|
| 66 | 61 | Manual: True
|
| 67 | 62 | Default: False
|
| 68 | 63 | |
| 69 | -Flag bignum-check
|
|
| 70 | - Description: Validate results of the enabled backend against native backend.
|
|
| 71 | - Manual: True
|
|
| 72 | - Default: False
|
|
| 73 | - |
|
| 74 | 64 | Flag need-atomic
|
| 75 | 65 | Description: Enable linking with "atomic" library (for 64-bit atomic ops on armel, #20549)
|
| 76 | 66 | Manual: True
|
| ... | ... | @@ -382,13 +372,11 @@ Library |
| 382 | 372 | -- Bignum configuration
|
| 383 | 373 | ----------------------------------------
|
| 384 | 374 | -- check that at least one backend is enabled
|
| 385 | - if !flag(bignum-native) && !flag(bignum-gmp) && !flag(bignum-ffi)
|
|
| 375 | + if !flag(bignum-native) && !flag(bignum-gmp)
|
|
| 386 | 376 | buildable: False
|
| 387 | 377 | |
| 388 | 378 | -- check that at most one flag is set
|
| 389 | - if flag(bignum-native) && (flag(bignum-gmp) || flag(bignum-ffi))
|
|
| 390 | - buildable: False
|
|
| 391 | - if flag(bignum-gmp) && flag(bignum-ffi)
|
|
| 379 | + if flag(bignum-native) && flag(bignum-gmp)
|
|
| 392 | 380 | buildable: False
|
| 393 | 381 | |
| 394 | 382 | if flag(bignum-gmp)
|
| ... | ... | @@ -398,25 +386,14 @@ Library |
| 398 | 386 | c-sources:
|
| 399 | 387 | cbits/gmp_wrappers.c
|
| 400 | 388 | |
| 401 | - if flag(bignum-ffi)
|
|
| 402 | - cpp-options: -DBIGNUM_FFI
|
|
| 403 | - other-modules:
|
|
| 404 | - GHC.Internal.Bignum.Backend.FFI
|
|
| 405 | - |
|
| 406 | 389 | if flag(bignum-native)
|
| 407 | 390 | cpp-options: -DBIGNUM_NATIVE
|
| 408 | 391 | |
| 409 | - if flag(bignum-check)
|
|
| 410 | - cpp-options: -DBIGNUM_CHECK
|
|
| 411 | - other-modules:
|
|
| 412 | - GHC.Internal.Bignum.Backend.Check
|
|
| 413 | - |
|
| 414 | 392 | exposed-modules:
|
| 415 | 393 | GHC.Internal.Bignum.Primitives
|
| 416 | 394 | GHC.Internal.Bignum.WordArray
|
| 417 | 395 | GHC.Internal.Bignum.BigNat
|
| 418 | 396 | GHC.Internal.Bignum.Backend
|
| 419 | - GHC.Internal.Bignum.Backend.Selected
|
|
| 420 | 397 | GHC.Internal.Bignum.Backend.Native
|
| 421 | 398 | GHC.Internal.Bignum.Natural
|
| 422 | 399 | GHC.Internal.Bignum.Integer
|
| ... | ... | @@ -7,9 +7,12 @@ module GHC.Internal.Bignum.Backend |
| 7 | 7 | )
|
| 8 | 8 | where
|
| 9 | 9 | |
| 10 | -#if defined(BIGNUM_CHECK)
|
|
| 11 | -import GHC.Internal.Bignum.Backend.Check as Backend
|
|
| 10 | +#if defined(BIGNUM_NATIVE)
|
|
| 11 | +import GHC.Internal.Bignum.Backend.Native as Backend
|
|
| 12 | + |
|
| 13 | +#elif defined(BIGNUM_GMP)
|
|
| 14 | +import GHC.Internal.Bignum.Backend.GMP as Backend
|
|
| 15 | + |
|
| 12 | 16 | #else
|
| 13 | -import GHC.Internal.Bignum.Backend.Selected as Backend
|
|
| 17 | +#error Undefined BigNum backend. Use a flag to select it (e.g. gmp, native)`
|
|
| 14 | 18 | #endif |
| 15 | - |
| 1 | -{-# LANGUAGE CPP #-}
|
|
| 2 | -{-# LANGUAGE NoImplicitPrelude #-}
|
|
| 3 | -{-# LANGUAGE BangPatterns #-}
|
|
| 4 | -{-# LANGUAGE GHCForeignImportPrim #-}
|
|
| 5 | -{-# LANGUAGE MagicHash #-}
|
|
| 6 | -{-# LANGUAGE UnboxedTuples #-}
|
|
| 7 | -{-# LANGUAGE UnliftedFFITypes #-}
|
|
| 8 | -{-# LANGUAGE NegativeLiterals #-}
|
|
| 9 | -{-# LANGUAGE ForeignFunctionInterface #-}
|
|
| 10 | -{-# OPTIONS_GHC -Wno-name-shadowing #-}
|
|
| 11 | - |
|
| 12 | --- | Check Native implementation against another backend
|
|
| 13 | -module GHC.Internal.Bignum.Backend.Check where
|
|
| 14 | - |
|
| 15 | -import GHC.Internal.CString
|
|
| 16 | -import GHC.Internal.Prim
|
|
| 17 | -import GHC.Internal.Types
|
|
| 18 | -import GHC.Internal.Bignum.WordArray
|
|
| 19 | -import GHC.Internal.Bignum.Primitives
|
|
| 20 | -import {-# SOURCE #-} GHC.Internal.Bignum.Integer
|
|
| 21 | -import {-# SOURCE #-} GHC.Internal.Bignum.Natural
|
|
| 22 | -import qualified GHC.Internal.Bignum.Backend.Native as Native
|
|
| 23 | -import qualified GHC.Internal.Bignum.Backend.Selected as Other
|
|
| 24 | - |
|
| 25 | -#if defined(BIGNUM_NATIVE)
|
|
| 26 | -#error You can't validate Native backend against itself. Choose another backend (e.g. gmp, ffi)
|
|
| 27 | -#endif
|
|
| 28 | - |
|
| 29 | -default ()
|
|
| 30 | - |
|
| 31 | --- | ghc-bignum backend name
|
|
| 32 | -backendName :: [Char]
|
|
| 33 | -backendName = unpackAppendCString# "check-"# Other.backendName
|
|
| 34 | - -- we don't have (++) at our disposal, so we directly use
|
|
| 35 | - -- `unpackAppendCString#`
|
|
| 36 | - |
|
| 37 | -bignat_compare
|
|
| 38 | - :: WordArray#
|
|
| 39 | - -> WordArray#
|
|
| 40 | - -> Int#
|
|
| 41 | -bignat_compare a b =
|
|
| 42 | - let
|
|
| 43 | - gr = Other.bignat_compare a b
|
|
| 44 | - nr = Native.bignat_compare a b
|
|
| 45 | - in case gr ==# nr of
|
|
| 46 | - 0# -> unexpectedValue_Int# (# #)
|
|
| 47 | - _ -> gr
|
|
| 48 | - |
|
| 49 | -mwaCompare
|
|
| 50 | - :: MutableWordArray# s
|
|
| 51 | - -> MutableWordArray# s
|
|
| 52 | - -> State# s
|
|
| 53 | - -> (# State# s, Bool# #)
|
|
| 54 | -mwaCompare mwa mwb s =
|
|
| 55 | - case mwaSize# mwa s of
|
|
| 56 | - (# s, szA #) -> case mwaSize# mwb s of
|
|
| 57 | - (# s, szB #) -> case szA ==# szB of
|
|
| 58 | - 0# -> (# s, 0# #)
|
|
| 59 | - _ -> let
|
|
| 60 | - go i s
|
|
| 61 | - | isTrue# (i <# 0#) = (# s, 1# #)
|
|
| 62 | - | True =
|
|
| 63 | - case readWordArray# mwa i s of
|
|
| 64 | - (# s, a #) -> case readWordArray# mwb i s of
|
|
| 65 | - (# s, b #) -> case a `eqWord#` b of
|
|
| 66 | - 0# -> (# s, 0# #)
|
|
| 67 | - _ -> go (i -# 1#) s
|
|
| 68 | - in go (szA -# 1#) s
|
|
| 69 | - |
|
| 70 | -mwaCompareOp
|
|
| 71 | - :: MutableWordArray# s
|
|
| 72 | - -> (MutableWordArray# s -> State# s -> State# s)
|
|
| 73 | - -> (MutableWordArray# s -> State# s -> State# s)
|
|
| 74 | - -> State# s
|
|
| 75 | - -> State# s
|
|
| 76 | -mwaCompareOp mwa f g s =
|
|
| 77 | - case mwaSize# mwa s of { (# s, sz #) ->
|
|
| 78 | - case newWordArray# sz s of { (# s, mwb #) ->
|
|
| 79 | - case f mwa s of { s ->
|
|
| 80 | - case g mwb s of { s ->
|
|
| 81 | - case mwaTrimZeroes# mwa s of { s ->
|
|
| 82 | - case mwaTrimZeroes# mwb s of { s ->
|
|
| 83 | - case mwaCompare mwa mwb s of
|
|
| 84 | - (# s, 0# #) -> case unexpectedValue of
|
|
| 85 | - !_ -> s
|
|
| 86 | - -- see Note [ghc-bignum exceptions] in
|
|
| 87 | - -- GHC.Num.Primitives
|
|
| 88 | - (# s, _ #) -> s
|
|
| 89 | - }}}}}}
|
|
| 90 | - |
|
| 91 | -mwaCompareOp2
|
|
| 92 | - :: MutableWordArray# s
|
|
| 93 | - -> MutableWordArray# s
|
|
| 94 | - -> (MutableWordArray# s -> MutableWordArray# s -> State# s -> State# s)
|
|
| 95 | - -> (MutableWordArray# s -> MutableWordArray# s -> State# s -> State# s)
|
|
| 96 | - -> State# s
|
|
| 97 | - -> State# s
|
|
| 98 | -mwaCompareOp2 mwa mwb f g s =
|
|
| 99 | - case mwaSize# mwa s of { (# s, szA #) ->
|
|
| 100 | - case mwaSize# mwb s of { (# s, szB #) ->
|
|
| 101 | - case newWordArray# szA s of { (# s, mwa' #) ->
|
|
| 102 | - case newWordArray# szB s of { (# s, mwb' #) ->
|
|
| 103 | - case f mwa mwb s of { s ->
|
|
| 104 | - case g mwa' mwb' s of { s ->
|
|
| 105 | - case mwaTrimZeroes# mwa s of { s ->
|
|
| 106 | - case mwaTrimZeroes# mwb s of { s ->
|
|
| 107 | - case mwaTrimZeroes# mwa' s of { s ->
|
|
| 108 | - case mwaTrimZeroes# mwb' s of { s ->
|
|
| 109 | - case mwaCompare mwa mwa' s of { (# s, ba #) ->
|
|
| 110 | - case mwaCompare mwb mwb' s of { (# s, bb #) ->
|
|
| 111 | - case ba &&# bb of
|
|
| 112 | - 0# -> case unexpectedValue of
|
|
| 113 | - !_ -> s
|
|
| 114 | - -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
|
|
| 115 | - _ -> s
|
|
| 116 | - }}}}}}}}}}}}
|
|
| 117 | - |
|
| 118 | -mwaCompareOpBool
|
|
| 119 | - :: MutableWordArray# s
|
|
| 120 | - -> (MutableWordArray# s -> State# s -> (#State# s, Bool# #))
|
|
| 121 | - -> (MutableWordArray# s -> State# s -> (#State# s, Bool# #))
|
|
| 122 | - -> State# s
|
|
| 123 | - -> (# State# s, Bool# #)
|
|
| 124 | -mwaCompareOpBool mwa f g s =
|
|
| 125 | - case mwaSize# mwa s of { (# s, sz #) ->
|
|
| 126 | - case newWordArray# sz s of { (# s, mwb #) ->
|
|
| 127 | - case f mwa s of { (# s, ra #) ->
|
|
| 128 | - case g mwb s of { (# s, rb #) ->
|
|
| 129 | - case ra ==# rb of
|
|
| 130 | - 0# -> case unexpectedValue of
|
|
| 131 | - !_ -> (# s, ra #)
|
|
| 132 | - -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
|
|
| 133 | - _ -> case ra of -- don't compare MWAs if underflow signaled!
|
|
| 134 | - 0# -> (# s, ra #) -- underflow
|
|
| 135 | - _ -> case mwaTrimZeroes# mwa s of { s ->
|
|
| 136 | - case mwaTrimZeroes# mwb s of { s ->
|
|
| 137 | - case mwaCompare mwa mwb s of
|
|
| 138 | - (# s, 0# #) -> case unexpectedValue of
|
|
| 139 | - !_ -> (# s, ra #)
|
|
| 140 | - -- see Note [ghc-bignum exceptions] in
|
|
| 141 | - -- GHC.Num.Primitives
|
|
| 142 | - _ -> (# s, ra #)
|
|
| 143 | - }}}}}}
|
|
| 144 | - |
|
| 145 | -mwaCompareOpWord
|
|
| 146 | - :: MutableWordArray# s
|
|
| 147 | - -> (MutableWordArray# s -> State# s -> (#State# s, Word# #))
|
|
| 148 | - -> (MutableWordArray# s -> State# s -> (#State# s, Word# #))
|
|
| 149 | - -> State# s
|
|
| 150 | - -> (# State# s, Word# #)
|
|
| 151 | -mwaCompareOpWord mwa f g s =
|
|
| 152 | - case mwaSize# mwa s of { (# s, sz #) ->
|
|
| 153 | - case newWordArray# sz s of { (# s, mwb #) ->
|
|
| 154 | - case f mwa s of { (# s, ra #) ->
|
|
| 155 | - case g mwb s of { (# s, rb #) ->
|
|
| 156 | - case mwaTrimZeroes# mwa s of { s ->
|
|
| 157 | - case mwaTrimZeroes# mwb s of { s ->
|
|
| 158 | - case mwaCompare mwa mwb s of
|
|
| 159 | - (# s, b #) -> case b &&# (ra `eqWord#` rb) of
|
|
| 160 | - 0# -> case unexpectedValue of
|
|
| 161 | - !_ -> (# s, ra #)
|
|
| 162 | - -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
|
|
| 163 | - _ -> (# s, ra #)
|
|
| 164 | - }}}}}}
|
|
| 165 | - |
|
| 166 | -bignat_add
|
|
| 167 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 168 | - -> WordArray#
|
|
| 169 | - -> WordArray#
|
|
| 170 | - -> State# RealWorld
|
|
| 171 | - -> State# RealWorld
|
|
| 172 | -bignat_add mwa wa wb
|
|
| 173 | - = mwaCompareOp mwa
|
|
| 174 | - (\m -> Other.bignat_add m wa wb)
|
|
| 175 | - (\m -> Native.bignat_add m wa wb)
|
|
| 176 | - |
|
| 177 | -bignat_add_word
|
|
| 178 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 179 | - -> WordArray#
|
|
| 180 | - -> Word#
|
|
| 181 | - -> State# RealWorld
|
|
| 182 | - -> State# RealWorld
|
|
| 183 | -bignat_add_word mwa wa b
|
|
| 184 | - = mwaCompareOp mwa
|
|
| 185 | - (\m -> Other.bignat_add_word m wa b)
|
|
| 186 | - (\m -> Native.bignat_add_word m wa b)
|
|
| 187 | - |
|
| 188 | -bignat_mul_word
|
|
| 189 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 190 | - -> WordArray#
|
|
| 191 | - -> Word#
|
|
| 192 | - -> State# RealWorld
|
|
| 193 | - -> State# RealWorld
|
|
| 194 | -bignat_mul_word mwa wa b
|
|
| 195 | - = mwaCompareOp mwa
|
|
| 196 | - (\m -> Other.bignat_mul_word m wa b)
|
|
| 197 | - (\m -> Native.bignat_mul_word m wa b)
|
|
| 198 | - |
|
| 199 | -bignat_sub
|
|
| 200 | - :: MutableWordArray# RealWorld
|
|
| 201 | - -> WordArray#
|
|
| 202 | - -> WordArray#
|
|
| 203 | - -> State# RealWorld
|
|
| 204 | - -> (# State# RealWorld, Bool# #)
|
|
| 205 | -bignat_sub mwa wa wb
|
|
| 206 | - = mwaCompareOpBool mwa
|
|
| 207 | - (\m -> Other.bignat_sub m wa wb)
|
|
| 208 | - (\m -> Native.bignat_sub m wa wb)
|
|
| 209 | - |
|
| 210 | -bignat_sub_word
|
|
| 211 | - :: MutableWordArray# RealWorld
|
|
| 212 | - -> WordArray#
|
|
| 213 | - -> Word#
|
|
| 214 | - -> State# RealWorld
|
|
| 215 | - -> (# State# RealWorld, Bool# #)
|
|
| 216 | -bignat_sub_word mwa wa b
|
|
| 217 | - = mwaCompareOpBool mwa
|
|
| 218 | - (\m -> Other.bignat_sub_word m wa b)
|
|
| 219 | - (\m -> Native.bignat_sub_word m wa b)
|
|
| 220 | - |
|
| 221 | -bignat_mul
|
|
| 222 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 223 | - -> WordArray#
|
|
| 224 | - -> WordArray#
|
|
| 225 | - -> State# RealWorld
|
|
| 226 | - -> State# RealWorld
|
|
| 227 | -bignat_mul mwa wa wb
|
|
| 228 | - = mwaCompareOp mwa
|
|
| 229 | - (\m -> Other.bignat_mul m wa wb)
|
|
| 230 | - (\m -> Native.bignat_mul m wa wb)
|
|
| 231 | - |
|
| 232 | -bignat_popcount :: WordArray# -> Word#
|
|
| 233 | -bignat_popcount wa =
|
|
| 234 | - let
|
|
| 235 | - gr = Other.bignat_popcount wa
|
|
| 236 | - nr = Native.bignat_popcount wa
|
|
| 237 | - in case gr `eqWord#` nr of
|
|
| 238 | - 0# -> 1## `quotWord#` 0##
|
|
| 239 | - _ -> gr
|
|
| 240 | - |
|
| 241 | -bignat_shiftl
|
|
| 242 | - :: MutableWordArray# RealWorld
|
|
| 243 | - -> WordArray#
|
|
| 244 | - -> Word#
|
|
| 245 | - -> State# RealWorld
|
|
| 246 | - -> State# RealWorld
|
|
| 247 | -bignat_shiftl mwa wa n
|
|
| 248 | - = mwaCompareOp mwa
|
|
| 249 | - (\m -> Other.bignat_shiftl m wa n)
|
|
| 250 | - (\m -> Native.bignat_shiftl m wa n)
|
|
| 251 | - |
|
| 252 | -bignat_shiftr
|
|
| 253 | - :: MutableWordArray# RealWorld
|
|
| 254 | - -> WordArray#
|
|
| 255 | - -> Word#
|
|
| 256 | - -> State# RealWorld
|
|
| 257 | - -> State# RealWorld
|
|
| 258 | -bignat_shiftr mwa wa n
|
|
| 259 | - = mwaCompareOp mwa
|
|
| 260 | - (\m -> Other.bignat_shiftr m wa n)
|
|
| 261 | - (\m -> Native.bignat_shiftr m wa n)
|
|
| 262 | - |
|
| 263 | -bignat_shiftr_neg
|
|
| 264 | - :: MutableWordArray# RealWorld
|
|
| 265 | - -> WordArray#
|
|
| 266 | - -> Word#
|
|
| 267 | - -> State# RealWorld
|
|
| 268 | - -> State# RealWorld
|
|
| 269 | -bignat_shiftr_neg mwa wa n
|
|
| 270 | - = mwaCompareOp mwa
|
|
| 271 | - (\m -> Other.bignat_shiftr_neg m wa n)
|
|
| 272 | - (\m -> Native.bignat_shiftr_neg m wa n)
|
|
| 273 | - |
|
| 274 | -bignat_or
|
|
| 275 | - :: MutableWordArray# RealWorld
|
|
| 276 | - -> WordArray#
|
|
| 277 | - -> WordArray#
|
|
| 278 | - -> State# RealWorld
|
|
| 279 | - -> State# RealWorld
|
|
| 280 | -bignat_or mwa wa wb
|
|
| 281 | - = mwaCompareOp mwa
|
|
| 282 | - (\m -> Other.bignat_or m wa wb)
|
|
| 283 | - (\m -> Native.bignat_or m wa wb)
|
|
| 284 | - |
|
| 285 | -bignat_xor
|
|
| 286 | - :: MutableWordArray# RealWorld
|
|
| 287 | - -> WordArray#
|
|
| 288 | - -> WordArray#
|
|
| 289 | - -> State# RealWorld
|
|
| 290 | - -> State# RealWorld
|
|
| 291 | -bignat_xor mwa wa wb
|
|
| 292 | - = mwaCompareOp mwa
|
|
| 293 | - (\m -> Other.bignat_xor m wa wb)
|
|
| 294 | - (\m -> Native.bignat_xor m wa wb)
|
|
| 295 | - |
|
| 296 | -bignat_and
|
|
| 297 | - :: MutableWordArray# RealWorld
|
|
| 298 | - -> WordArray#
|
|
| 299 | - -> WordArray#
|
|
| 300 | - -> State# RealWorld
|
|
| 301 | - -> State# RealWorld
|
|
| 302 | -bignat_and mwa wa wb
|
|
| 303 | - = mwaCompareOp mwa
|
|
| 304 | - (\m -> Other.bignat_and m wa wb)
|
|
| 305 | - (\m -> Native.bignat_and m wa wb)
|
|
| 306 | - |
|
| 307 | -bignat_and_not
|
|
| 308 | - :: MutableWordArray# RealWorld
|
|
| 309 | - -> WordArray#
|
|
| 310 | - -> WordArray#
|
|
| 311 | - -> State# RealWorld
|
|
| 312 | - -> State# RealWorld
|
|
| 313 | -bignat_and_not mwa wa wb
|
|
| 314 | - = mwaCompareOp mwa
|
|
| 315 | - (\m -> Other.bignat_and_not m wa wb)
|
|
| 316 | - (\m -> Native.bignat_and_not m wa wb)
|
|
| 317 | - |
|
| 318 | -bignat_quotrem
|
|
| 319 | - :: MutableWordArray# RealWorld
|
|
| 320 | - -> MutableWordArray# RealWorld
|
|
| 321 | - -> WordArray#
|
|
| 322 | - -> WordArray#
|
|
| 323 | - -> State# RealWorld
|
|
| 324 | - -> State# RealWorld
|
|
| 325 | -bignat_quotrem mwq mwr wa wb
|
|
| 326 | - = mwaCompareOp2 mwq mwr
|
|
| 327 | - (\m1 m2 -> Other.bignat_quotrem m1 m2 wa wb)
|
|
| 328 | - (\m1 m2 -> Native.bignat_quotrem m1 m2 wa wb)
|
|
| 329 | - |
|
| 330 | -bignat_quot
|
|
| 331 | - :: MutableWordArray# RealWorld
|
|
| 332 | - -> WordArray#
|
|
| 333 | - -> WordArray#
|
|
| 334 | - -> State# RealWorld
|
|
| 335 | - -> State# RealWorld
|
|
| 336 | -bignat_quot mwq wa wb
|
|
| 337 | - = mwaCompareOp mwq
|
|
| 338 | - (\m -> Other.bignat_quot m wa wb)
|
|
| 339 | - (\m -> Native.bignat_quot m wa wb)
|
|
| 340 | - |
|
| 341 | -bignat_rem
|
|
| 342 | - :: MutableWordArray# RealWorld
|
|
| 343 | - -> WordArray#
|
|
| 344 | - -> WordArray#
|
|
| 345 | - -> State# RealWorld
|
|
| 346 | - -> State# RealWorld
|
|
| 347 | -bignat_rem mwr wa wb
|
|
| 348 | - = mwaCompareOp mwr
|
|
| 349 | - (\m -> Other.bignat_rem m wa wb)
|
|
| 350 | - (\m -> Native.bignat_rem m wa wb)
|
|
| 351 | - |
|
| 352 | -bignat_quotrem_word
|
|
| 353 | - :: MutableWordArray# RealWorld
|
|
| 354 | - -> WordArray#
|
|
| 355 | - -> Word#
|
|
| 356 | - -> State# RealWorld
|
|
| 357 | - -> (# State# RealWorld, Word# #)
|
|
| 358 | -bignat_quotrem_word mwq wa b
|
|
| 359 | - = mwaCompareOpWord mwq
|
|
| 360 | - (\m -> Other.bignat_quotrem_word m wa b)
|
|
| 361 | - (\m -> Native.bignat_quotrem_word m wa b)
|
|
| 362 | - |
|
| 363 | -bignat_quot_word
|
|
| 364 | - :: MutableWordArray# RealWorld
|
|
| 365 | - -> WordArray#
|
|
| 366 | - -> Word#
|
|
| 367 | - -> State# RealWorld
|
|
| 368 | - -> State# RealWorld
|
|
| 369 | -bignat_quot_word mwq wa b
|
|
| 370 | - = mwaCompareOp mwq
|
|
| 371 | - (\m -> Other.bignat_quot_word m wa b)
|
|
| 372 | - (\m -> Native.bignat_quot_word m wa b)
|
|
| 373 | - |
|
| 374 | -bignat_rem_word
|
|
| 375 | - :: WordArray#
|
|
| 376 | - -> Word#
|
|
| 377 | - -> Word#
|
|
| 378 | -bignat_rem_word wa b =
|
|
| 379 | - let
|
|
| 380 | - gr = Other.bignat_rem_word wa b
|
|
| 381 | - nr = Native.bignat_rem_word wa b
|
|
| 382 | - in case gr `eqWord#` nr of
|
|
| 383 | - 1# -> gr
|
|
| 384 | - _ -> unexpectedValue_Word# (# #)
|
|
| 385 | - |
|
| 386 | -bignat_gcd
|
|
| 387 | - :: MutableWordArray# RealWorld
|
|
| 388 | - -> WordArray#
|
|
| 389 | - -> WordArray#
|
|
| 390 | - -> State# RealWorld
|
|
| 391 | - -> State# RealWorld
|
|
| 392 | -bignat_gcd mwr wa wb
|
|
| 393 | - = mwaCompareOp mwr
|
|
| 394 | - (\m -> Other.bignat_gcd m wa wb)
|
|
| 395 | - (\m -> Native.bignat_gcd m wa wb)
|
|
| 396 | - |
|
| 397 | -bignat_gcd_word
|
|
| 398 | - :: WordArray#
|
|
| 399 | - -> Word#
|
|
| 400 | - -> Word#
|
|
| 401 | -bignat_gcd_word wa b =
|
|
| 402 | - let
|
|
| 403 | - gr = Other.bignat_gcd_word wa b
|
|
| 404 | - nr = Native.bignat_gcd_word wa b
|
|
| 405 | - in case gr `eqWord#` nr of
|
|
| 406 | - 1# -> gr
|
|
| 407 | - _ -> unexpectedValue_Word# (# #)
|
|
| 408 | - |
|
| 409 | -bignat_gcd_word_word
|
|
| 410 | - :: Word#
|
|
| 411 | - -> Word#
|
|
| 412 | - -> Word#
|
|
| 413 | -bignat_gcd_word_word a b =
|
|
| 414 | - let
|
|
| 415 | - gr = Other.bignat_gcd_word_word a b
|
|
| 416 | - nr = Native.bignat_gcd_word_word a b
|
|
| 417 | - in case gr `eqWord#` nr of
|
|
| 418 | - 1# -> gr
|
|
| 419 | - _ -> unexpectedValue_Word# (# #)
|
|
| 420 | - |
|
| 421 | -bignat_encode_double :: WordArray# -> Int# -> Double#
|
|
| 422 | -bignat_encode_double a e =
|
|
| 423 | - let
|
|
| 424 | - gr = Other.bignat_encode_double a e
|
|
| 425 | - nr = Native.bignat_encode_double a e
|
|
| 426 | - in case gr ==## nr of
|
|
| 427 | - 1# -> gr
|
|
| 428 | - _ -> case unexpectedValue of
|
|
| 429 | - !_ -> 0.0##
|
|
| 430 | - -- see Note [ghc-bignum exceptions] in GHC.Num.Primitives
|
|
| 431 | - |
|
| 432 | -bignat_powmod_word :: WordArray# -> WordArray# -> Word# -> Word#
|
|
| 433 | -bignat_powmod_word b e m =
|
|
| 434 | - let
|
|
| 435 | - gr = Other.bignat_powmod_word b e m
|
|
| 436 | - nr = Native.bignat_powmod_word b e m
|
|
| 437 | - in case gr `eqWord#` nr of
|
|
| 438 | - 1# -> gr
|
|
| 439 | - _ -> unexpectedValue_Word# (# #)
|
|
| 440 | - |
|
| 441 | -bignat_powmod
|
|
| 442 | - :: MutableWordArray# RealWorld
|
|
| 443 | - -> WordArray#
|
|
| 444 | - -> WordArray#
|
|
| 445 | - -> WordArray#
|
|
| 446 | - -> State# RealWorld
|
|
| 447 | - -> State# RealWorld
|
|
| 448 | -bignat_powmod r b e m
|
|
| 449 | - = mwaCompareOp r
|
|
| 450 | - (\r' -> Other.bignat_powmod r' b e m)
|
|
| 451 | - (\r' -> Native.bignat_powmod r' b e m)
|
|
| 452 | - |
|
| 453 | -bignat_powmod_words
|
|
| 454 | - :: Word#
|
|
| 455 | - -> Word#
|
|
| 456 | - -> Word#
|
|
| 457 | - -> Word#
|
|
| 458 | -bignat_powmod_words b e m =
|
|
| 459 | - let
|
|
| 460 | - gr = Other.bignat_powmod_words b e m
|
|
| 461 | - nr = Native.bignat_powmod_words b e m
|
|
| 462 | - in case gr `eqWord#` nr of
|
|
| 463 | - 1# -> gr
|
|
| 464 | - _ -> unexpectedValue_Word# (# #)
|
|
| 465 | - |
|
| 466 | -integer_gcde
|
|
| 467 | - :: Integer
|
|
| 468 | - -> Integer
|
|
| 469 | - -> (# Integer, Integer, Integer #)
|
|
| 470 | -integer_gcde a b =
|
|
| 471 | - let
|
|
| 472 | - !(# g0,x0,y0 #) = Other.integer_gcde a b
|
|
| 473 | - !(# g1,x1,y1 #) = Native.integer_gcde a b
|
|
| 474 | - in if isTrue# (integerEq# x0 x1
|
|
| 475 | - &&# integerEq# y0 y1
|
|
| 476 | - &&# integerEq# g0 g1)
|
|
| 477 | - then (# g0, x0, y0 #)
|
|
| 478 | - else case unexpectedValue of
|
|
| 479 | - !_ -> (# integerZero, integerZero, integerZero #)
|
|
| 480 | - |
|
| 481 | -integer_recip_mod
|
|
| 482 | - :: Integer
|
|
| 483 | - -> Natural
|
|
| 484 | - -> (# Natural | () #)
|
|
| 485 | -integer_recip_mod x m =
|
|
| 486 | - let
|
|
| 487 | - !r0 = Other.integer_recip_mod x m
|
|
| 488 | - !r1 = Native.integer_recip_mod x m
|
|
| 489 | - in case (# r0, r1 #) of
|
|
| 490 | - (# (# | () #), (# | () #) #) -> r0
|
|
| 491 | - (# (# y0 | #), (# y1 | #) #)
|
|
| 492 | - | isTrue# (naturalEq# y0 y1) -> r0
|
|
| 493 | - _ -> case unexpectedValue of
|
|
| 494 | - !_ -> (# | () #)
|
|
| 495 | - |
|
| 496 | -integer_powmod
|
|
| 497 | - :: Integer
|
|
| 498 | - -> Natural
|
|
| 499 | - -> Natural
|
|
| 500 | - -> Natural
|
|
| 501 | -integer_powmod b e m =
|
|
| 502 | - let
|
|
| 503 | - !r0 = Other.integer_powmod b e m
|
|
| 504 | - !r1 = Native.integer_powmod b e m
|
|
| 505 | - in if isTrue# (naturalEq# r0 r1)
|
|
| 506 | - then r0
|
|
| 507 | - else case unexpectedValue of
|
|
| 508 | - !_ -> naturalZero |
| 1 | -{-# LANGUAGE NoImplicitPrelude #-}
|
|
| 2 | -{-# LANGUAGE BangPatterns #-}
|
|
| 3 | -{-# LANGUAGE GHCForeignImportPrim #-}
|
|
| 4 | -{-# LANGUAGE MagicHash #-}
|
|
| 5 | -{-# LANGUAGE UnboxedTuples #-}
|
|
| 6 | -{-# LANGUAGE UnliftedFFITypes #-}
|
|
| 7 | -{-# LANGUAGE NegativeLiterals #-}
|
|
| 8 | -{-# LANGUAGE ForeignFunctionInterface #-}
|
|
| 9 | - |
|
| 10 | --- | External BigNat backend that directly call FFI operations.
|
|
| 11 | ---
|
|
| 12 | --- This backend can be useful for specific compilers such as GHCJS or Asterius
|
|
| 13 | --- that replace bignat foreign calls with calls to the native platform bignat
|
|
| 14 | --- library (e.g. JavaScript's BigInt). You can also link an extra object
|
|
| 15 | --- providing the implementation.
|
|
| 16 | -module GHC.Internal.Bignum.Backend.FFI where
|
|
| 17 | - |
|
| 18 | -import GHC.Internal.Prim
|
|
| 19 | -import GHC.Internal.Types
|
|
| 20 | -import GHC.Internal.Bignum.WordArray
|
|
| 21 | -import GHC.Internal.Bignum.Primitives
|
|
| 22 | -import qualified GHC.Internal.Bignum.Backend.Native as Native
|
|
| 23 | -import {-# SOURCE #-} GHC.Internal.Bignum.Natural
|
|
| 24 | -import {-# SOURCE #-} GHC.Internal.Bignum.Integer
|
|
| 25 | - |
|
| 26 | --- See W1 of Note [Tracking dependencies on primitives] in GHC.Internal.Base
|
|
| 27 | --- (This module uses the empty tuple () and string literals.)
|
|
| 28 | -import GHC.Internal.Tuple ()
|
|
| 29 | -import GHC.Internal.CString ()
|
|
| 30 | - |
|
| 31 | -default ()
|
|
| 32 | - |
|
| 33 | --- | ghc-bignum backend name
|
|
| 34 | -backendName :: [Char]
|
|
| 35 | -backendName = "ffi"
|
|
| 36 | - |
|
| 37 | --- | Compare two non-zero BigNat of the same length
|
|
| 38 | ---
|
|
| 39 | --- Return:
|
|
| 40 | --- < 0 ==> LT
|
|
| 41 | --- == 0 ==> EQ
|
|
| 42 | --- > 0 ==> GT
|
|
| 43 | -bignat_compare
|
|
| 44 | - :: WordArray#
|
|
| 45 | - -> WordArray#
|
|
| 46 | - -> Int#
|
|
| 47 | -bignat_compare = ghc_bignat_compare
|
|
| 48 | - |
|
| 49 | -foreign import ccall unsafe ghc_bignat_compare
|
|
| 50 | - :: WordArray#
|
|
| 51 | - -> WordArray#
|
|
| 52 | - -> Int#
|
|
| 53 | - |
|
| 54 | --- | Add two non-zero BigNat
|
|
| 55 | ---
|
|
| 56 | --- Result is to be stored in the MutableWordArray#.
|
|
| 57 | --- The latter has size: max (size a, size b) + 1
|
|
| 58 | ---
|
|
| 59 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 60 | --- removed by the caller if it is not already done by the backend.
|
|
| 61 | -bignat_add
|
|
| 62 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 63 | - -> WordArray#
|
|
| 64 | - -> WordArray#
|
|
| 65 | - -> State# RealWorld
|
|
| 66 | - -> State# RealWorld
|
|
| 67 | -bignat_add mwa wa wb s
|
|
| 68 | - = ioVoid (ghc_bignat_add mwa wa wb) s
|
|
| 69 | - |
|
| 70 | -foreign import ccall unsafe ghc_bignat_add
|
|
| 71 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 72 | - -> WordArray#
|
|
| 73 | - -> WordArray#
|
|
| 74 | - -> IO ()
|
|
| 75 | - |
|
| 76 | --- | Add a non-zero BigNat and a non-zero Word#
|
|
| 77 | ---
|
|
| 78 | --- Result is to be stored in the MutableWordArray#.
|
|
| 79 | --- The latter has size: size a + 1
|
|
| 80 | ---
|
|
| 81 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 82 | --- removed by the caller if it is not already done by the backend.
|
|
| 83 | -bignat_add_word
|
|
| 84 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 85 | - -> WordArray#
|
|
| 86 | - -> Word#
|
|
| 87 | - -> State# RealWorld
|
|
| 88 | - -> State# RealWorld
|
|
| 89 | -bignat_add_word mwa wa b s =
|
|
| 90 | - ioVoid (ghc_bignat_add_word mwa wa b) s
|
|
| 91 | - |
|
| 92 | -foreign import ccall unsafe ghc_bignat_add_word
|
|
| 93 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 94 | - -> WordArray#
|
|
| 95 | - -> Word#
|
|
| 96 | - -> IO ()
|
|
| 97 | - |
|
| 98 | --- | Multiply a non-zero BigNat and a non-zero Word#
|
|
| 99 | ---
|
|
| 100 | --- Result is to be stored in the MutableWordArray#.
|
|
| 101 | --- The latter has size: size a + 1
|
|
| 102 | ---
|
|
| 103 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 104 | --- removed by the caller if it is not already done by the backend.
|
|
| 105 | -bignat_mul_word
|
|
| 106 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 107 | - -> WordArray#
|
|
| 108 | - -> Word#
|
|
| 109 | - -> State# RealWorld
|
|
| 110 | - -> State# RealWorld
|
|
| 111 | -bignat_mul_word mwa wa b s =
|
|
| 112 | - ioVoid (ghc_bignat_mul_word mwa wa b) s
|
|
| 113 | - |
|
| 114 | -foreign import ccall unsafe ghc_bignat_mul_word
|
|
| 115 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 116 | - -> WordArray#
|
|
| 117 | - -> Word#
|
|
| 118 | - -> IO ()
|
|
| 119 | - |
|
| 120 | --- | Sub two non-zero BigNat
|
|
| 121 | ---
|
|
| 122 | --- Result is to be stored in the MutableWordArray#.
|
|
| 123 | --- The latter has size: size a
|
|
| 124 | ---
|
|
| 125 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 126 | --- not already done by the backend.
|
|
| 127 | ---
|
|
| 128 | --- Return False# to indicate underflow.
|
|
| 129 | -bignat_sub
|
|
| 130 | - :: MutableWordArray# RealWorld
|
|
| 131 | - -> WordArray#
|
|
| 132 | - -> WordArray#
|
|
| 133 | - -> State# RealWorld
|
|
| 134 | - -> (# State# RealWorld, Bool# #)
|
|
| 135 | -bignat_sub mwa wa wb s = ioBool (ghc_bignat_sub mwa wa wb) s
|
|
| 136 | - |
|
| 137 | -foreign import ccall unsafe ghc_bignat_sub
|
|
| 138 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 139 | - -> WordArray#
|
|
| 140 | - -> WordArray#
|
|
| 141 | - -> IO Bool
|
|
| 142 | - |
|
| 143 | --- | Sub a non-zero word from a non-zero BigNat
|
|
| 144 | ---
|
|
| 145 | --- Result is to be stored in the MutableWordArray#.
|
|
| 146 | --- The latter has size: size a
|
|
| 147 | ---
|
|
| 148 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 149 | --- not already done by the backend.
|
|
| 150 | ---
|
|
| 151 | --- Return False# to indicate underflow.
|
|
| 152 | -bignat_sub_word
|
|
| 153 | - :: MutableWordArray# RealWorld
|
|
| 154 | - -> WordArray#
|
|
| 155 | - -> Word#
|
|
| 156 | - -> State# RealWorld
|
|
| 157 | - -> (# State# RealWorld, Bool# #)
|
|
| 158 | -bignat_sub_word mwa wa b s = ioBool (ghc_bignat_sub_word mwa wa b) s
|
|
| 159 | - |
|
| 160 | -foreign import ccall unsafe ghc_bignat_sub_word
|
|
| 161 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 162 | - -> WordArray#
|
|
| 163 | - -> Word#
|
|
| 164 | - -> IO Bool
|
|
| 165 | - |
|
| 166 | --- | Multiply two non-zero BigNat
|
|
| 167 | ---
|
|
| 168 | --- Result is to be stored in the MutableWordArray#.
|
|
| 169 | --- The latter has size: size a+size b
|
|
| 170 | ---
|
|
| 171 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 172 | --- removed by the caller if it is not already done by the backend.
|
|
| 173 | -bignat_mul
|
|
| 174 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 175 | - -> WordArray#
|
|
| 176 | - -> WordArray#
|
|
| 177 | - -> State# RealWorld
|
|
| 178 | - -> State# RealWorld
|
|
| 179 | -bignat_mul mwa wa wb s = ioVoid (ghc_bignat_mul mwa wa wb) s
|
|
| 180 | - |
|
| 181 | -foreign import ccall unsafe ghc_bignat_mul
|
|
| 182 | - :: MutableWordArray# RealWorld -- ^ Result
|
|
| 183 | - -> WordArray#
|
|
| 184 | - -> WordArray#
|
|
| 185 | - -> IO ()
|
|
| 186 | - |
|
| 187 | --- | PopCount of a non-zero BigNat
|
|
| 188 | -bignat_popcount :: WordArray# -> Word#
|
|
| 189 | -bignat_popcount = ghc_bignat_popcount
|
|
| 190 | - |
|
| 191 | -foreign import ccall unsafe ghc_bignat_popcount
|
|
| 192 | - :: WordArray#
|
|
| 193 | - -> Word#
|
|
| 194 | - |
|
| 195 | --- | Left-shift a non-zero BigNat by a non-zero amount of bits
|
|
| 196 | ---
|
|
| 197 | --- Result is to be stored in the MutableWordArray#.
|
|
| 198 | --- The latter has size: size a + required new limbs
|
|
| 199 | ---
|
|
| 200 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 201 | --- removed by the caller if it is not already done by the backend.
|
|
| 202 | -bignat_shiftl
|
|
| 203 | - :: MutableWordArray# RealWorld
|
|
| 204 | - -> WordArray#
|
|
| 205 | - -> Word#
|
|
| 206 | - -> State# RealWorld
|
|
| 207 | - -> State# RealWorld
|
|
| 208 | -bignat_shiftl mwa wa n s = ioVoid (ghc_bignat_shiftl mwa wa n) s
|
|
| 209 | - |
|
| 210 | -foreign import ccall unsafe ghc_bignat_shiftl
|
|
| 211 | - :: MutableWordArray# RealWorld
|
|
| 212 | - -> WordArray#
|
|
| 213 | - -> Word#
|
|
| 214 | - -> IO ()
|
|
| 215 | - |
|
| 216 | --- | Right-shift a non-zero BigNat by a non-zero amount of bits
|
|
| 217 | ---
|
|
| 218 | --- Result is to be stored in the MutableWordArray#.
|
|
| 219 | --- The latter has size: required limbs
|
|
| 220 | ---
|
|
| 221 | --- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 222 | --- removed by the caller if it is not already done by the backend.
|
|
| 223 | -bignat_shiftr
|
|
| 224 | - :: MutableWordArray# RealWorld
|
|
| 225 | - -> WordArray#
|
|
| 226 | - -> Word#
|
|
| 227 | - -> State# RealWorld
|
|
| 228 | - -> State# RealWorld
|
|
| 229 | -bignat_shiftr mwa wa n s = ioVoid (ghc_bignat_shiftr mwa wa n) s
|
|
| 230 | - |
|
| 231 | -foreign import ccall unsafe ghc_bignat_shiftr
|
|
| 232 | - :: MutableWordArray# RealWorld
|
|
| 233 | - -> WordArray#
|
|
| 234 | - -> Word#
|
|
| 235 | - -> IO ()
|
|
| 236 | - |
|
| 237 | --- | Right-shift a non-zero BigNat by a non-zero amount of bits by first
|
|
| 238 | --- converting it into its two's complement representation and then again after
|
|
| 239 | --- the arithmetic shift.
|
|
| 240 | ---
|
|
| 241 | --- Result is to be stored in the MutableWordArray#.
|
|
| 242 | --- The latter has size: required limbs
|
|
| 243 | ---
|
|
| 244 | --- The potential 0 most-significant Words (i.e. the potential carry) will be
|
|
| 245 | --- removed by the caller if it is not already done by the backend.
|
|
| 246 | -bignat_shiftr_neg
|
|
| 247 | - :: MutableWordArray# RealWorld
|
|
| 248 | - -> WordArray#
|
|
| 249 | - -> Word#
|
|
| 250 | - -> State# RealWorld
|
|
| 251 | - -> State# RealWorld
|
|
| 252 | -bignat_shiftr_neg mwa wa n s = ioVoid (ghc_bignat_shiftr_neg mwa wa n) s
|
|
| 253 | - |
|
| 254 | -foreign import ccall unsafe ghc_bignat_shiftr_neg
|
|
| 255 | - :: MutableWordArray# RealWorld
|
|
| 256 | - -> WordArray#
|
|
| 257 | - -> Word#
|
|
| 258 | - -> IO ()
|
|
| 259 | - |
|
| 260 | - |
|
| 261 | --- | OR two non-zero BigNat
|
|
| 262 | ---
|
|
| 263 | --- Result is to be stored in the MutableWordArray#.
|
|
| 264 | --- The latter has size: max (size a, size b)
|
|
| 265 | -bignat_or
|
|
| 266 | - :: MutableWordArray# RealWorld
|
|
| 267 | - -> WordArray#
|
|
| 268 | - -> WordArray#
|
|
| 269 | - -> State# RealWorld
|
|
| 270 | - -> State# RealWorld
|
|
| 271 | -{-# INLINE bignat_or #-}
|
|
| 272 | -bignat_or mwa wa wb s = ioVoid (ghc_bignat_or mwa wa wb) s
|
|
| 273 | - |
|
| 274 | -foreign import ccall unsafe ghc_bignat_or
|
|
| 275 | - :: MutableWordArray# RealWorld
|
|
| 276 | - -> WordArray#
|
|
| 277 | - -> WordArray#
|
|
| 278 | - -> IO ()
|
|
| 279 | - |
|
| 280 | --- | XOR two non-zero BigNat
|
|
| 281 | ---
|
|
| 282 | --- Result is to be stored in the MutableWordArray#.
|
|
| 283 | --- The latter has size: max (size a, size b)
|
|
| 284 | ---
|
|
| 285 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 286 | --- not already done by the backend.
|
|
| 287 | -bignat_xor
|
|
| 288 | - :: MutableWordArray# RealWorld
|
|
| 289 | - -> WordArray#
|
|
| 290 | - -> WordArray#
|
|
| 291 | - -> State# RealWorld
|
|
| 292 | - -> State# RealWorld
|
|
| 293 | -{-# INLINE bignat_xor #-}
|
|
| 294 | -bignat_xor mwa wa wb s = ioVoid (ghc_bignat_xor mwa wa wb) s
|
|
| 295 | - |
|
| 296 | -foreign import ccall unsafe ghc_bignat_xor
|
|
| 297 | - :: MutableWordArray# RealWorld
|
|
| 298 | - -> WordArray#
|
|
| 299 | - -> WordArray#
|
|
| 300 | - -> IO ()
|
|
| 301 | - |
|
| 302 | --- | AND two non-zero BigNat
|
|
| 303 | ---
|
|
| 304 | --- Result is to be stored in the MutableWordArray#.
|
|
| 305 | --- The latter has size: min (size a, size b)
|
|
| 306 | ---
|
|
| 307 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 308 | --- not already done by the backend.
|
|
| 309 | -bignat_and
|
|
| 310 | - :: MutableWordArray# RealWorld
|
|
| 311 | - -> WordArray#
|
|
| 312 | - -> WordArray#
|
|
| 313 | - -> State# RealWorld
|
|
| 314 | - -> State# RealWorld
|
|
| 315 | -{-# INLINE bignat_and #-}
|
|
| 316 | -bignat_and mwa wa wb s = ioVoid (ghc_bignat_and mwa wa wb) s
|
|
| 317 | - |
|
| 318 | -foreign import ccall unsafe ghc_bignat_and
|
|
| 319 | - :: MutableWordArray# RealWorld
|
|
| 320 | - -> WordArray#
|
|
| 321 | - -> WordArray#
|
|
| 322 | - -> IO ()
|
|
| 323 | - |
|
| 324 | --- | ANDNOT two non-zero BigNat
|
|
| 325 | ---
|
|
| 326 | --- Result is to be stored in the MutableWordArray#.
|
|
| 327 | --- The latter has size: size a
|
|
| 328 | ---
|
|
| 329 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 330 | --- not already done by the backend.
|
|
| 331 | -bignat_and_not
|
|
| 332 | - :: MutableWordArray# RealWorld
|
|
| 333 | - -> WordArray#
|
|
| 334 | - -> WordArray#
|
|
| 335 | - -> State# RealWorld
|
|
| 336 | - -> State# RealWorld
|
|
| 337 | -{-# INLINE bignat_and_not #-}
|
|
| 338 | -bignat_and_not mwa wa wb s = ioVoid (ghc_bignat_and_not mwa wa wb) s
|
|
| 339 | - |
|
| 340 | -foreign import ccall unsafe ghc_bignat_and_not
|
|
| 341 | - :: MutableWordArray# RealWorld
|
|
| 342 | - -> WordArray#
|
|
| 343 | - -> WordArray#
|
|
| 344 | - -> IO ()
|
|
| 345 | - |
|
| 346 | --- | QuotRem of two non-zero BigNat
|
|
| 347 | ---
|
|
| 348 | --- Result quotient and remainder are to be stored in the MutableWordArray#.
|
|
| 349 | --- The first one (quotient) has size: size(A)-size(B)+1
|
|
| 350 | --- The second one (remainder) has size: size(b)
|
|
| 351 | ---
|
|
| 352 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 353 | --- not already done by the backend.
|
|
| 354 | -bignat_quotrem
|
|
| 355 | - :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 356 | - -> MutableWordArray# RealWorld -- ^ Remainder
|
|
| 357 | - -> WordArray#
|
|
| 358 | - -> WordArray#
|
|
| 359 | - -> State# RealWorld
|
|
| 360 | - -> State# RealWorld
|
|
| 361 | -bignat_quotrem mwq mwr wa wb s =
|
|
| 362 | - ioVoid (ghc_bignat_quotrem mwq mwr wa wb) s
|
|
| 363 | - |
|
| 364 | -foreign import ccall unsafe ghc_bignat_quotrem
|
|
| 365 | - :: MutableWordArray# RealWorld
|
|
| 366 | - -> MutableWordArray# RealWorld
|
|
| 367 | - -> WordArray#
|
|
| 368 | - -> WordArray#
|
|
| 369 | - -> IO ()
|
|
| 370 | - |
|
| 371 | --- | Quotient of two non-zero BigNat
|
|
| 372 | ---
|
|
| 373 | --- Result quotient is to be stored in the MutableWordArray#.
|
|
| 374 | --- The latter has size: size(A)-size(B)+1
|
|
| 375 | ---
|
|
| 376 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 377 | --- not already done by the backend.
|
|
| 378 | -bignat_quot
|
|
| 379 | - :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 380 | - -> WordArray#
|
|
| 381 | - -> WordArray#
|
|
| 382 | - -> State# RealWorld
|
|
| 383 | - -> State# RealWorld
|
|
| 384 | -bignat_quot mwq wa wb s =
|
|
| 385 | - ioVoid (ghc_bignat_quot mwq wa wb) s
|
|
| 386 | - |
|
| 387 | -foreign import ccall unsafe ghc_bignat_quot
|
|
| 388 | - :: MutableWordArray# RealWorld
|
|
| 389 | - -> WordArray#
|
|
| 390 | - -> WordArray#
|
|
| 391 | - -> IO ()
|
|
| 392 | - |
|
| 393 | --- | Remainder of two non-zero BigNat
|
|
| 394 | ---
|
|
| 395 | --- Result remainder is to be stored in the MutableWordArray#.
|
|
| 396 | --- The latter has size: size(B)
|
|
| 397 | ---
|
|
| 398 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 399 | --- not already done by the backend.
|
|
| 400 | -bignat_rem
|
|
| 401 | - :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 402 | - -> WordArray#
|
|
| 403 | - -> WordArray#
|
|
| 404 | - -> State# RealWorld
|
|
| 405 | - -> State# RealWorld
|
|
| 406 | -bignat_rem mwr wa wb s =
|
|
| 407 | - ioVoid (ghc_bignat_rem mwr wa wb) s
|
|
| 408 | - |
|
| 409 | -foreign import ccall unsafe ghc_bignat_rem
|
|
| 410 | - :: MutableWordArray# RealWorld
|
|
| 411 | - -> WordArray#
|
|
| 412 | - -> WordArray#
|
|
| 413 | - -> IO ()
|
|
| 414 | - |
|
| 415 | --- | QuotRem of a non-zero BigNat and a non-zero Word
|
|
| 416 | ---
|
|
| 417 | --- Result quotient is to be stored in the MutableWordArray#.
|
|
| 418 | --- The latter has size: size(A)
|
|
| 419 | ---
|
|
| 420 | --- The remainder is returned.
|
|
| 421 | ---
|
|
| 422 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 423 | --- not already done by the backend.
|
|
| 424 | -bignat_quotrem_word
|
|
| 425 | - :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 426 | - -> WordArray#
|
|
| 427 | - -> Word#
|
|
| 428 | - -> State# RealWorld
|
|
| 429 | - -> (# State# RealWorld, Word# #)
|
|
| 430 | -bignat_quotrem_word mwq wa b s =
|
|
| 431 | - ioWord# (ghc_bignat_quotrem_word mwq wa b) s
|
|
| 432 | - |
|
| 433 | -foreign import ccall unsafe ghc_bignat_quotrem_word
|
|
| 434 | - :: MutableWordArray# RealWorld
|
|
| 435 | - -> WordArray#
|
|
| 436 | - -> Word#
|
|
| 437 | - -> IO Word
|
|
| 438 | - |
|
| 439 | --- | Quot of a non-zero BigNat and a non-zero Word
|
|
| 440 | ---
|
|
| 441 | --- Result quotient is to be stored in the MutableWordArray#.
|
|
| 442 | --- The latter has size: size(A)
|
|
| 443 | ---
|
|
| 444 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 445 | --- not already done by the backend.
|
|
| 446 | -bignat_quot_word
|
|
| 447 | - :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 448 | - -> WordArray#
|
|
| 449 | - -> Word#
|
|
| 450 | - -> State# RealWorld
|
|
| 451 | - -> State# RealWorld
|
|
| 452 | -bignat_quot_word mwq wa b s =
|
|
| 453 | - ioVoid (ghc_bignat_quot_word mwq wa b) s
|
|
| 454 | - |
|
| 455 | -foreign import ccall unsafe ghc_bignat_quot_word
|
|
| 456 | - :: MutableWordArray# RealWorld
|
|
| 457 | - -> WordArray#
|
|
| 458 | - -> Word#
|
|
| 459 | - -> IO ()
|
|
| 460 | - |
|
| 461 | --- | Remainder of a non-zero BigNat and a non-zero Word
|
|
| 462 | ---
|
|
| 463 | --- The remainder is returned.
|
|
| 464 | -bignat_rem_word
|
|
| 465 | - :: WordArray#
|
|
| 466 | - -> Word#
|
|
| 467 | - -> Word#
|
|
| 468 | -bignat_rem_word = ghc_bignat_rem_word
|
|
| 469 | - |
|
| 470 | -foreign import ccall unsafe ghc_bignat_rem_word
|
|
| 471 | - :: WordArray#
|
|
| 472 | - -> Word#
|
|
| 473 | - -> Word#
|
|
| 474 | - |
|
| 475 | - |
|
| 476 | --- | Greatest common divisor (GCD) of two non-zero and non-one BigNat
|
|
| 477 | ---
|
|
| 478 | --- Result GCD is to be stored in the MutableWordArray#.
|
|
| 479 | --- The latter has size: size(B)
|
|
| 480 | --- The first WordArray# is greater than the second WordArray#.
|
|
| 481 | ---
|
|
| 482 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 483 | --- not already done by the backend.
|
|
| 484 | -bignat_gcd
|
|
| 485 | - :: MutableWordArray# RealWorld
|
|
| 486 | - -> WordArray#
|
|
| 487 | - -> WordArray#
|
|
| 488 | - -> State# RealWorld
|
|
| 489 | - -> State# RealWorld
|
|
| 490 | -bignat_gcd mwr wa wb s =
|
|
| 491 | - ioVoid (ghc_bignat_gcd mwr wa wb) s
|
|
| 492 | - |
|
| 493 | -foreign import ccall unsafe ghc_bignat_gcd
|
|
| 494 | - :: MutableWordArray# RealWorld
|
|
| 495 | - -> WordArray#
|
|
| 496 | - -> WordArray#
|
|
| 497 | - -> IO ()
|
|
| 498 | - |
|
| 499 | --- | Greatest common divisor (GCD) of a non-zero/non-one BigNat and a
|
|
| 500 | --- non-zero/non-one Word#
|
|
| 501 | ---
|
|
| 502 | --- Result GCD is returned
|
|
| 503 | -bignat_gcd_word
|
|
| 504 | - :: WordArray#
|
|
| 505 | - -> Word#
|
|
| 506 | - -> Word#
|
|
| 507 | -bignat_gcd_word = ghc_bignat_gcd_word
|
|
| 508 | - |
|
| 509 | -foreign import ccall unsafe ghc_bignat_gcd_word
|
|
| 510 | - :: WordArray#
|
|
| 511 | - -> Word#
|
|
| 512 | - -> Word#
|
|
| 513 | - |
|
| 514 | --- | Greatest common divisor (GCD) of two Word#
|
|
| 515 | ---
|
|
| 516 | --- Result GCD is returned
|
|
| 517 | -bignat_gcd_word_word
|
|
| 518 | - :: Word#
|
|
| 519 | - -> Word#
|
|
| 520 | - -> Word#
|
|
| 521 | -bignat_gcd_word_word = ghc_bignat_gcd_word_word
|
|
| 522 | - |
|
| 523 | -foreign import ccall unsafe ghc_bignat_gcd_word_word
|
|
| 524 | - :: Word#
|
|
| 525 | - -> Word#
|
|
| 526 | - -> Word#
|
|
| 527 | - |
|
| 528 | --- | Encode (# BigNat mantissa, Int# exponent #) into a Double#
|
|
| 529 | -bignat_encode_double :: WordArray# -> Int# -> Double#
|
|
| 530 | -bignat_encode_double = ghc_bignat_encode_double
|
|
| 531 | - |
|
| 532 | -foreign import ccall unsafe ghc_bignat_encode_double
|
|
| 533 | - :: WordArray#
|
|
| 534 | - -> Int#
|
|
| 535 | - -> Double#
|
|
| 536 | - |
|
| 537 | --- | \"@'bignat_powmod_word' /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 538 | --- exponent @/e/@ modulo @/m/@.
|
|
| 539 | ---
|
|
| 540 | --- b > 1
|
|
| 541 | --- e > 0
|
|
| 542 | --- m > 1
|
|
| 543 | -bignat_powmod_word :: WordArray# -> WordArray# -> Word# -> Word#
|
|
| 544 | -bignat_powmod_word = ghc_bignat_powmod_word
|
|
| 545 | - |
|
| 546 | -foreign import ccall unsafe ghc_bignat_powmod_word
|
|
| 547 | - :: WordArray# -> WordArray# -> Word# -> Word#
|
|
| 548 | - |
|
| 549 | --- | \"@'bignat_powmod' r /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 550 | --- exponent @/e/@ modulo @/m/@.
|
|
| 551 | ---
|
|
| 552 | --- b > 1
|
|
| 553 | --- e > 0
|
|
| 554 | --- m > 1
|
|
| 555 | ---
|
|
| 556 | --- Result is to be stored in the MutableWordArray# (which size is equal to the
|
|
| 557 | --- one of m).
|
|
| 558 | ---
|
|
| 559 | --- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 560 | --- not already done by the backend.
|
|
| 561 | -bignat_powmod
|
|
| 562 | - :: MutableWordArray# RealWorld
|
|
| 563 | - -> WordArray#
|
|
| 564 | - -> WordArray#
|
|
| 565 | - -> WordArray#
|
|
| 566 | - -> State# RealWorld
|
|
| 567 | - -> State# RealWorld
|
|
| 568 | -bignat_powmod r b e m s =
|
|
| 569 | - ioVoid (ghc_bignat_powmod r b e m) s
|
|
| 570 | - |
|
| 571 | -foreign import ccall unsafe ghc_bignat_powmod
|
|
| 572 | - :: MutableWordArray# RealWorld
|
|
| 573 | - -> WordArray#
|
|
| 574 | - -> WordArray#
|
|
| 575 | - -> WordArray#
|
|
| 576 | - -> IO ()
|
|
| 577 | - |
|
| 578 | --- | \"@'bignat_powmod' /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 579 | --- exponent @/e/@ modulo @/m/@.
|
|
| 580 | ---
|
|
| 581 | --- b > 1
|
|
| 582 | --- e > 0
|
|
| 583 | --- m > 1
|
|
| 584 | -bignat_powmod_words
|
|
| 585 | - :: Word#
|
|
| 586 | - -> Word#
|
|
| 587 | - -> Word#
|
|
| 588 | - -> Word#
|
|
| 589 | -bignat_powmod_words = ghc_bignat_powmod_words
|
|
| 590 | - |
|
| 591 | -foreign import ccall unsafe ghc_bignat_powmod_words
|
|
| 592 | - :: Word# -> Word# -> Word# -> Word#
|
|
| 593 | - |
|
| 594 | - |
|
| 595 | --- | Return extended GCD of two non-zero integers.
|
|
| 596 | ---
|
|
| 597 | --- I.e. integer_gcde a b returns (g,x,y) so that ax + by = g
|
|
| 598 | ---
|
|
| 599 | --- Input: a and b are non zero.
|
|
| 600 | --- Output: g must be > 0
|
|
| 601 | ---
|
|
| 602 | -integer_gcde
|
|
| 603 | - :: Integer
|
|
| 604 | - -> Integer
|
|
| 605 | - -> (# Integer, Integer, Integer #)
|
|
| 606 | -integer_gcde = Native.integer_gcde
|
|
| 607 | - -- for now we use Native's implementation. If some FFI backend user needs a
|
|
| 608 | - -- specific implementation, we'll need to determine a prototype to pass and
|
|
| 609 | - -- return BigNat signs and sizes via FFI.
|
|
| 610 | - |
|
| 611 | - |
|
| 612 | --- | Computes the modular inverse of two non-zero integers.
|
|
| 613 | ---
|
|
| 614 | --- I.e. y = integer_recip_mod x m
|
|
| 615 | --- = x^(-1) `mod` m
|
|
| 616 | ---
|
|
| 617 | --- with 0 < y < abs m
|
|
| 618 | -integer_recip_mod
|
|
| 619 | - :: Integer
|
|
| 620 | - -> Natural
|
|
| 621 | - -> (# Natural | () #)
|
|
| 622 | -integer_recip_mod = Native.integer_recip_mod
|
|
| 623 | - -- for now we use Native's implementation. If some FFI backend user needs a
|
|
| 624 | - -- specific implementation, we'll need to determine a prototype to pass and
|
|
| 625 | - -- return BigNat signs and sizes via FFI.
|
|
| 626 | - |
|
| 627 | --- | Computes the modular exponentiation.
|
|
| 628 | ---
|
|
| 629 | --- I.e. y = integer_powmod b e m
|
|
| 630 | --- = b^e `mod` m
|
|
| 631 | ---
|
|
| 632 | --- with 0 <= y < abs m
|
|
| 633 | -integer_powmod
|
|
| 634 | - :: Integer
|
|
| 635 | - -> Natural
|
|
| 636 | - -> Natural
|
|
| 637 | - -> Natural
|
|
| 638 | -integer_powmod = Native.integer_powmod
|
|
| 639 | - -- for now we use Native's implementation. If some FFI backend user needs a
|
|
| 640 | - -- specific implementation, we'll need to determine a prototype to pass and
|
|
| 641 | - -- return BigNat signs and sizes via FFI. |
| ... | ... | @@ -14,7 +14,7 @@ module GHC.Internal.Bignum.Backend.Native where |
| 14 | 14 | #include "MachDeps.h"
|
| 15 | 15 | #include "WordSize.h"
|
| 16 | 16 | |
| 17 | -#if defined(BIGNUM_NATIVE) || defined(BIGNUM_CHECK) || defined(BIGNUM_FFI)
|
|
| 17 | +#if defined(BIGNUM_NATIVE)
|
|
| 18 | 18 | import {-# SOURCE #-} GHC.Internal.Bignum.BigNat
|
| 19 | 19 | import {-# SOURCE #-} GHC.Internal.Bignum.Natural
|
| 20 | 20 | import {-# SOURCE #-} GHC.Internal.Bignum.Integer
|
| ... | ... | @@ -50,6 +50,12 @@ count_words_bits_int :: Word# -> (# Int#, Int# #) |
| 50 | 50 | count_words_bits_int n = case count_words_bits n of
|
| 51 | 51 | (# nw, nb #) -> (# word2Int# nw, word2Int# nb #)
|
| 52 | 52 | |
| 53 | +-- | Compare two non-zero BigNat of the same length
|
|
| 54 | +--
|
|
| 55 | +-- Return:
|
|
| 56 | +-- < 0 ==> LT
|
|
| 57 | +-- == 0 ==> EQ
|
|
| 58 | +-- > 0 ==> GT
|
|
| 53 | 59 | bignat_compare :: WordArray# -> WordArray# -> Int#
|
| 54 | 60 | bignat_compare wa wb = go (sz -# 1#)
|
| 55 | 61 | where
|
| ... | ... | @@ -62,6 +68,13 @@ bignat_compare wa wb = go (sz -# 1#) |
| 62 | 68 | | isTrue# (a `gtWord#` b) -> 1#
|
| 63 | 69 | | True -> -1#
|
| 64 | 70 | |
| 71 | +-- | Add two non-zero BigNat
|
|
| 72 | +--
|
|
| 73 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 74 | +-- The latter has size: max (size a, size b) + 1
|
|
| 75 | +--
|
|
| 76 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 77 | +-- removed by the caller if it is not already done by the backend.
|
|
| 65 | 78 | bignat_add
|
| 66 | 79 | :: MutableWordArray# s -- ^ Result
|
| 67 | 80 | -> WordArray#
|
| ... | ... | @@ -120,6 +133,13 @@ bignat_add mwa wa wb = addABc 0# 0## |
| 120 | 133 | in case mwaWrite# mwa i r s of
|
| 121 | 134 | s' -> addAoBc wab (i +# 1#) carry' s'
|
| 122 | 135 | |
| 136 | +-- | Add a non-zero BigNat and a non-zero Word#
|
|
| 137 | +--
|
|
| 138 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 139 | +-- The latter has size: size a + 1
|
|
| 140 | +--
|
|
| 141 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 142 | +-- removed by the caller if it is not already done by the backend.
|
|
| 123 | 143 | bignat_add_word
|
| 124 | 144 | :: MutableWordArray# RealWorld -- ^ Result
|
| 125 | 145 | -> WordArray#
|
| ... | ... | @@ -128,6 +148,15 @@ bignat_add_word |
| 128 | 148 | -> State# RealWorld
|
| 129 | 149 | bignat_add_word mwa wa b s = mwaInitArrayPlusWord mwa wa b s
|
| 130 | 150 | |
| 151 | +-- | Sub a non-zero word from a non-zero BigNat
|
|
| 152 | +--
|
|
| 153 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 154 | +-- The latter has size: size a
|
|
| 155 | +--
|
|
| 156 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 157 | +-- not already done by the backend.
|
|
| 158 | +--
|
|
| 159 | +-- Return False# to indicate underflow.
|
|
| 131 | 160 | bignat_sub_word
|
| 132 | 161 | :: MutableWordArray# RealWorld
|
| 133 | 162 | -> WordArray#
|
| ... | ... | @@ -154,6 +183,13 @@ bignat_sub_word mwa wa b = go b 0# |
| 154 | 183 | (# l , c #) -> case mwaWrite# mwa i l s of
|
| 155 | 184 | s1 -> go (int2Word# c) (i +# 1#) s1
|
| 156 | 185 | |
| 186 | +-- | Multiply a non-zero BigNat and a non-zero Word#
|
|
| 187 | +--
|
|
| 188 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 189 | +-- The latter has size: size a + 1
|
|
| 190 | +--
|
|
| 191 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 192 | +-- removed by the caller if it is not already done by the backend.
|
|
| 157 | 193 | bignat_mul_word
|
| 158 | 194 | :: MutableWordArray# RealWorld -- ^ Result
|
| 159 | 195 | -> WordArray#
|
| ... | ... | @@ -173,6 +209,13 @@ bignat_mul_word mwa wa b = go 0# 0## |
| 173 | 209 | s' -> go (i +# 1#) carry' s'
|
| 174 | 210 | |
| 175 | 211 | |
| 212 | +-- | Multiply two non-zero BigNat
|
|
| 213 | +--
|
|
| 214 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 215 | +-- The latter has size: size a+size b
|
|
| 216 | +--
|
|
| 217 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 218 | +-- removed by the caller if it is not already done by the backend.
|
|
| 176 | 219 | bignat_mul
|
| 177 | 220 | :: MutableWordArray# RealWorld -- ^ Result
|
| 178 | 221 | -> WordArray#
|
| ... | ... | @@ -214,6 +257,15 @@ bignat_mul mwa wa wb s1 = |
| 214 | 257 | bi -> case mul mwa wa bi i ctzA 0## s of
|
| 215 | 258 | s' -> mulEachB (i +# 1#) s'
|
| 216 | 259 | |
| 260 | +-- | Sub two non-zero BigNat
|
|
| 261 | +--
|
|
| 262 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 263 | +-- The latter has size: size a
|
|
| 264 | +--
|
|
| 265 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 266 | +-- not already done by the backend.
|
|
| 267 | +--
|
|
| 268 | +-- Return False# to indicate underflow.
|
|
| 217 | 269 | bignat_sub
|
| 218 | 270 | :: MutableWordArray# RealWorld
|
| 219 | 271 | -> WordArray#
|
| ... | ... | @@ -227,6 +279,7 @@ bignat_sub mwa wa wb s = |
| 227 | 279 | case mwaArrayCopy# mwa 0# wa 0# (wordArraySize# wa) s of
|
| 228 | 280 | s' -> mwaSubInplaceArray mwa 0# wb s'
|
| 229 | 281 | |
| 282 | +-- | PopCount of a non-zero BigNat
|
|
| 230 | 283 | bignat_popcount :: WordArray# -> Word#
|
| 231 | 284 | bignat_popcount wa = go 0# 0##
|
| 232 | 285 | where
|
| ... | ... | @@ -235,6 +288,13 @@ bignat_popcount wa = go 0# 0## |
| 235 | 288 | | isTrue# (i ==# sz) = c
|
| 236 | 289 | | True = go (i +# 1#) (c `plusWord#` popCnt# (indexWordArray# wa i))
|
| 237 | 290 | |
| 291 | +-- | Left-shift a non-zero BigNat by a non-zero amount of bits
|
|
| 292 | +--
|
|
| 293 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 294 | +-- The latter has size: size a + required new limbs
|
|
| 295 | +--
|
|
| 296 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 297 | +-- removed by the caller if it is not already done by the backend.
|
|
| 238 | 298 | bignat_shiftl
|
| 239 | 299 | :: MutableWordArray# s
|
| 240 | 300 | -> WordArray#
|
| ... | ... | @@ -267,6 +327,13 @@ bignat_shiftl mwa wa n s1 = |
| 267 | 327 | s' -> mwaBitShift (i +# 1#) c' s'
|
| 268 | 328 | |
| 269 | 329 | |
| 330 | +-- | Right-shift a non-zero BigNat by a non-zero amount of bits
|
|
| 331 | +--
|
|
| 332 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 333 | +-- The latter has size: required limbs
|
|
| 334 | +--
|
|
| 335 | +-- The potential 0 most-significant Word (i.e. the potential carry) will be
|
|
| 336 | +-- removed by the caller if it is not already done by the backend.
|
|
| 270 | 337 | bignat_shiftr
|
| 271 | 338 | :: MutableWordArray# s
|
| 272 | 339 | -> WordArray#
|
| ... | ... | @@ -293,6 +360,15 @@ bignat_shiftr mwa wa n s1 |
| 293 | 360 | in case mwaWrite# mwa i v s of
|
| 294 | 361 | s' -> mwaBitShift (i -# 1#) c' s'
|
| 295 | 362 | |
| 363 | +-- | Right-shift a non-zero BigNat by a non-zero amount of bits by first
|
|
| 364 | +-- converting it into its two's complement representation and then again after
|
|
| 365 | +-- the arithmetic shift.
|
|
| 366 | +--
|
|
| 367 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 368 | +-- The latter has size: required limbs
|
|
| 369 | +--
|
|
| 370 | +-- The potential 0 most-significant Words (i.e. the potential carry) will be
|
|
| 371 | +-- removed by the caller if it is not already done by the backend.
|
|
| 296 | 372 | bignat_shiftr_neg
|
| 297 | 373 | :: MutableWordArray# s
|
| 298 | 374 | -> WordArray#
|
| ... | ... | @@ -329,6 +405,10 @@ bignat_shiftr_neg mwa wa n s1 |
| 329 | 405 | in go 0#
|
| 330 | 406 | |
| 331 | 407 | |
| 408 | +-- | OR two non-zero BigNat
|
|
| 409 | +--
|
|
| 410 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 411 | +-- The latter has size: max (size a, size b)
|
|
| 332 | 412 | bignat_or
|
| 333 | 413 | :: MutableWordArray# RealWorld -- ^ Result
|
| 334 | 414 | -> WordArray#
|
| ... | ... | @@ -346,6 +426,13 @@ bignat_or mwa wa wb s1 |
| 346 | 426 | case mwaInitArrayBinOp mwa wx wy or# s of
|
| 347 | 427 | s' -> mwaArrayCopy# mwa ny wx ny (nx -# ny) s'
|
| 348 | 428 | |
| 429 | +-- | XOR two non-zero BigNat
|
|
| 430 | +--
|
|
| 431 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 432 | +-- The latter has size: max (size a, size b)
|
|
| 433 | +--
|
|
| 434 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 435 | +-- not already done by the backend.
|
|
| 349 | 436 | bignat_xor
|
| 350 | 437 | :: MutableWordArray# RealWorld -- ^ Result
|
| 351 | 438 | -> WordArray#
|
| ... | ... | @@ -363,6 +450,13 @@ bignat_xor mwa wa wb s1 |
| 363 | 450 | case mwaInitArrayBinOp mwa wx wy xor# s of
|
| 364 | 451 | s' -> mwaArrayCopy# mwa ny wx ny (nx -# ny) s'
|
| 365 | 452 | |
| 453 | +-- | AND two non-zero BigNat
|
|
| 454 | +--
|
|
| 455 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 456 | +-- The latter has size: min (size a, size b)
|
|
| 457 | +--
|
|
| 458 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 459 | +-- not already done by the backend.
|
|
| 366 | 460 | bignat_and
|
| 367 | 461 | :: MutableWordArray# RealWorld -- ^ Result
|
| 368 | 462 | -> WordArray#
|
| ... | ... | @@ -371,6 +465,13 @@ bignat_and |
| 371 | 465 | -> State# RealWorld
|
| 372 | 466 | bignat_and mwa wa wb s = mwaInitArrayBinOp mwa wa wb and# s
|
| 373 | 467 | |
| 468 | +-- | ANDNOT two non-zero BigNat
|
|
| 469 | +--
|
|
| 470 | +-- Result is to be stored in the MutableWordArray#.
|
|
| 471 | +-- The latter has size: size a
|
|
| 472 | +--
|
|
| 473 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 474 | +-- not already done by the backend.
|
|
| 374 | 475 | bignat_and_not
|
| 375 | 476 | :: MutableWordArray# RealWorld -- ^ Result
|
| 376 | 477 | -> WordArray#
|
| ... | ... | @@ -384,9 +485,17 @@ bignat_and_not mwa wa wb s = |
| 384 | 485 | !szA = wordArraySize# wa
|
| 385 | 486 | !szB = wordArraySize# wb
|
| 386 | 487 | |
| 488 | +-- | QuotRem of two non-zero BigNat
|
|
| 489 | +--
|
|
| 490 | +-- Result quotient and remainder are to be stored in the MutableWordArray#.
|
|
| 491 | +-- The first one (quotient) has size: size(A)-size(B)+1
|
|
| 492 | +-- The second one (remainder) has size: size(b)
|
|
| 493 | +--
|
|
| 494 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 495 | +-- not already done by the backend.
|
|
| 387 | 496 | bignat_quotrem
|
| 388 | - :: MutableWordArray# s
|
|
| 389 | - -> MutableWordArray# s
|
|
| 497 | + :: MutableWordArray# s -- ^ Quotient
|
|
| 498 | + -> MutableWordArray# s -- ^ Remainder
|
|
| 390 | 499 | -> WordArray#
|
| 391 | 500 | -> WordArray#
|
| 392 | 501 | -> State# s
|
| ... | ... | @@ -434,8 +543,15 @@ bignat_quotrem mwq mwr uwa uwb s0 = |
| 434 | 543 | |
| 435 | 544 | |
| 436 | 545 | |
| 546 | +-- | Quotient of two non-zero BigNat
|
|
| 547 | +--
|
|
| 548 | +-- Result quotient is to be stored in the MutableWordArray#.
|
|
| 549 | +-- The latter has size: size(A)-size(B)+1
|
|
| 550 | +--
|
|
| 551 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 552 | +-- not already done by the backend.
|
|
| 437 | 553 | bignat_quot
|
| 438 | - :: MutableWordArray# RealWorld
|
|
| 554 | + :: MutableWordArray# RealWorld -- ^ Quotient
|
|
| 439 | 555 | -> WordArray#
|
| 440 | 556 | -> WordArray#
|
| 441 | 557 | -> State# RealWorld
|
| ... | ... | @@ -445,8 +561,15 @@ bignat_quot mwq wa wb s = |
| 445 | 561 | case newWordArray# (wordArraySize# wb) s of
|
| 446 | 562 | (# s, mwr #) -> bignat_quotrem mwq mwr wa wb s
|
| 447 | 563 | |
| 564 | +-- | Remainder of two non-zero BigNat
|
|
| 565 | +--
|
|
| 566 | +-- Result remainder is to be stored in the MutableWordArray#.
|
|
| 567 | +-- The latter has size: size(B)
|
|
| 568 | +--
|
|
| 569 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 570 | +-- not already done by the backend.
|
|
| 448 | 571 | bignat_rem
|
| 449 | - :: MutableWordArray# RealWorld
|
|
| 572 | + :: MutableWordArray# RealWorld -- ^ Remainder
|
|
| 450 | 573 | -> WordArray#
|
| 451 | 574 | -> WordArray#
|
| 452 | 575 | -> State# RealWorld
|
| ... | ... | @@ -577,6 +700,15 @@ bignat_quotrem_normalized mwq mwa b s0 = |
| 577 | 700 | | True -> loop (m -# 1#) s2
|
| 578 | 701 | }}
|
| 579 | 702 | |
| 703 | +-- | QuotRem of a non-zero BigNat and a non-zero Word
|
|
| 704 | +--
|
|
| 705 | +-- Result quotient is to be stored in the MutableWordArray#.
|
|
| 706 | +-- The latter has size: size(A)
|
|
| 707 | +--
|
|
| 708 | +-- The remainder is returned.
|
|
| 709 | +--
|
|
| 710 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 711 | +-- not already done by the backend.
|
|
| 580 | 712 | bignat_quotrem_word
|
| 581 | 713 | :: MutableWordArray# s -- ^ Quotient
|
| 582 | 714 | -> WordArray#
|
| ... | ... | @@ -595,6 +727,13 @@ bignat_quotrem_word mwq wa b s = go (sz -# 1#) 0## s |
| 595 | 727 | in case mwaWrite# mwq i q s of
|
| 596 | 728 | s' -> go (i -# 1#) r' s'
|
| 597 | 729 | |
| 730 | +-- | Quot of a non-zero BigNat and a non-zero Word
|
|
| 731 | +--
|
|
| 732 | +-- Result quotient is to be stored in the MutableWordArray#.
|
|
| 733 | +-- The latter has size: size(A)
|
|
| 734 | +--
|
|
| 735 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 736 | +-- not already done by the backend.
|
|
| 598 | 737 | bignat_quot_word
|
| 599 | 738 | :: MutableWordArray# s -- ^ Quotient
|
| 600 | 739 | -> WordArray#
|
| ... | ... | @@ -613,6 +752,9 @@ bignat_quot_word mwq wa b s = go (sz -# 1#) 0## s |
| 613 | 752 | in case mwaWrite# mwq i q s of
|
| 614 | 753 | s' -> go (i -# 1#) r' s'
|
| 615 | 754 | |
| 755 | +-- | Remainder of a non-zero BigNat and a non-zero Word
|
|
| 756 | +--
|
|
| 757 | +-- The remainder is returned.
|
|
| 616 | 758 | bignat_rem_word
|
| 617 | 759 | :: WordArray#
|
| 618 | 760 | -> Word#
|
| ... | ... | @@ -629,6 +771,14 @@ bignat_rem_word wa b = go (sz -# 1#) 0## |
| 629 | 771 | in go (i -# 1#) r'
|
| 630 | 772 | |
| 631 | 773 | |
| 774 | +-- | Greatest common divisor (GCD) of two non-zero and non-one BigNat
|
|
| 775 | +--
|
|
| 776 | +-- Result GCD is to be stored in the MutableWordArray#.
|
|
| 777 | +-- The latter has size: size(B)
|
|
| 778 | +-- The first WordArray# is greater than the second WordArray#.
|
|
| 779 | +--
|
|
| 780 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 781 | +-- not already done by the backend.
|
|
| 632 | 782 | bignat_gcd
|
| 633 | 783 | :: MutableWordArray# s
|
| 634 | 784 | -> WordArray#
|
| ... | ... | @@ -647,13 +797,21 @@ bignat_gcd mwr = go |
| 647 | 797 | !wmin' = bigNatRem wmax wmin
|
| 648 | 798 | in go wmax' wmin' s
|
| 649 | 799 | |
| 800 | +-- | Greatest common divisor (GCD) of a non-zero/non-one BigNat and a
|
|
| 801 | +-- non-zero/non-one Word#
|
|
| 802 | +--
|
|
| 803 | +-- Result GCD is returned
|
|
| 650 | 804 | bignat_gcd_word
|
| 651 | 805 | :: WordArray#
|
| 652 | 806 | -> Word#
|
| 653 | 807 | -> Word#
|
| 654 | 808 | bignat_gcd_word a b = bignat_gcd_word_word b (bigNatRemWord# a b)
|
| 655 | 809 | |
| 656 | --- | This operation doesn't really belongs here, but GMP's one is much faster
|
|
| 810 | +-- | Greatest common divisor (GCD) of two Word#
|
|
| 811 | +--
|
|
| 812 | +-- Result GCD is returned.
|
|
| 813 | +--
|
|
| 814 | +-- This operation doesn't really belongs here, but GMP's one is much faster
|
|
| 657 | 815 | -- than this simple implementation (basic Euclid algorithm).
|
| 658 | 816 | --
|
| 659 | 817 | -- Ideally we should make an implementation as fast as GMP's one and put it into
|
| ... | ... | @@ -665,6 +823,7 @@ bignat_gcd_word_word |
| 665 | 823 | bignat_gcd_word_word a 0## = a
|
| 666 | 824 | bignat_gcd_word_word a b = bignat_gcd_word_word b (a `remWord#` b)
|
| 667 | 825 | |
| 826 | +-- | Encode (# BigNat mantissa, Int# exponent #) into a Double#
|
|
| 668 | 827 | bignat_encode_double :: WordArray# -> Int# -> Double#
|
| 669 | 828 | bignat_encode_double wa e0 = go 0.0## e0 0#
|
| 670 | 829 | where
|
| ... | ... | @@ -676,6 +835,12 @@ bignat_encode_double wa e0 = go 0.0## e0 0# |
| 676 | 835 | (e +# WORD_SIZE_IN_BITS#) -- FIXME: we assume that e doesn't overflow...
|
| 677 | 836 | (i +# 1#)
|
| 678 | 837 | |
| 838 | +-- | \"@'bignat_powmod_word' /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 839 | +-- exponent @/e/@ modulo @/m/@.
|
|
| 840 | +--
|
|
| 841 | +-- b > 1
|
|
| 842 | +-- e > 0
|
|
| 843 | +-- m > 1
|
|
| 679 | 844 | bignat_powmod_word :: WordArray# -> WordArray# -> Word# -> Word#
|
| 680 | 845 | bignat_powmod_word b0 e0 m = go (naturalFromBigNat# b0) (naturalFromBigNat# e0) (naturalFromWord# 1##)
|
| 681 | 846 | where
|
| ... | ... | @@ -693,6 +858,18 @@ bignat_powmod_word b0 e0 m = go (naturalFromBigNat# b0) (naturalFromBigNat# e0) |
| 693 | 858 | m' = naturalFromWord# m
|
| 694 | 859 | e' = e `naturalShiftR#` 1## -- slightly faster than "e `div` 2"
|
| 695 | 860 | |
| 861 | +-- | \"@'bignat_powmod' r /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 862 | +-- exponent @/e/@ modulo @/m/@.
|
|
| 863 | +--
|
|
| 864 | +-- b > 1
|
|
| 865 | +-- e > 0
|
|
| 866 | +-- m > 1
|
|
| 867 | +--
|
|
| 868 | +-- Result is to be stored in the MutableWordArray# (which size is equal to the
|
|
| 869 | +-- one of m).
|
|
| 870 | +--
|
|
| 871 | +-- The potential 0 most-significant Words will be removed by the caller if it is
|
|
| 872 | +-- not already done by the backend.
|
|
| 696 | 873 | bignat_powmod
|
| 697 | 874 | :: MutableWordArray# RealWorld
|
| 698 | 875 | -> WordArray#
|
| ... | ... | @@ -720,6 +897,12 @@ bignat_powmod r b0 e0 m s = mwaInitCopyShrink# r r' s |
| 720 | 897 | m' = naturalFromBigNat# m
|
| 721 | 898 | e' = e `naturalShiftR#` 1## -- slightly faster than "e `div` 2"
|
| 722 | 899 | |
| 900 | +-- | \"@'bignat_powmod' /b/ /e/ /m/@\" computes base @/b/@ raised to
|
|
| 901 | +-- exponent @/e/@ modulo @/m/@.
|
|
| 902 | +--
|
|
| 903 | +-- b > 1
|
|
| 904 | +-- e > 0
|
|
| 905 | +-- m > 1
|
|
| 723 | 906 | bignat_powmod_words
|
| 724 | 907 | :: Word#
|
| 725 | 908 | -> Word#
|
| ... | ... | @@ -731,6 +914,13 @@ bignat_powmod_words b e m = |
| 731 | 914 | m
|
| 732 | 915 | |
| 733 | 916 | |
| 917 | +-- | Return extended GCD of two non-zero integers.
|
|
| 918 | +--
|
|
| 919 | +-- I.e. integer_gcde a b returns (g,x,y) so that ax + by = g
|
|
| 920 | +--
|
|
| 921 | +-- Input: a and b are non zero.
|
|
| 922 | +-- Output: g must be > 0
|
|
| 923 | +--
|
|
| 734 | 924 | integer_gcde
|
| 735 | 925 | :: Integer
|
| 736 | 926 | -> Integer
|
| ... | ... | @@ -748,6 +938,12 @@ integer_gcde a b = f (# a,integerOne,integerZero #) (# b,integerZero,integerOne |
| 748 | 938 | !(# q, r #) -> f new (# r , old_s `integerSub` (q `integerMul` s)
|
| 749 | 939 | , old_t `integerSub` (q `integerMul` t) #)
|
| 750 | 940 | |
| 941 | +-- | Computes the modular inverse of two non-zero integers.
|
|
| 942 | +--
|
|
| 943 | +-- I.e. y = integer_recip_mod x m
|
|
| 944 | +-- = x^(-1) `mod` m
|
|
| 945 | +--
|
|
| 946 | +-- with 0 < y < abs m
|
|
| 751 | 947 | integer_recip_mod
|
| 752 | 948 | :: Integer
|
| 753 | 949 | -> Natural
|
| ... | ... | @@ -763,6 +959,12 @@ integer_recip_mod x m = |
| 763 | 959 | -- a `mod` m > 0 because m > 0
|
| 764 | 960 | | True -> (# | () #)
|
| 765 | 961 | |
| 962 | +-- | Computes the modular exponentiation.
|
|
| 963 | +--
|
|
| 964 | +-- I.e. y = integer_powmod b e m
|
|
| 965 | +-- = b^e `mod` m
|
|
| 966 | +--
|
|
| 967 | +-- with 0 <= y < abs m
|
|
| 766 | 968 | integer_powmod
|
| 767 | 969 | :: Integer
|
| 768 | 970 | -> Natural
|
| 1 | -{-# LANGUAGE CPP #-}
|
|
| 2 | -{-# LANGUAGE NoImplicitPrelude #-}
|
|
| 3 | - |
|
| 4 | --- | Selected backend
|
|
| 5 | ---
|
|
| 6 | --- We need this module in addition to GHC.Internal.Bignum.Backend to avoid module loops with
|
|
| 7 | --- Check backend.
|
|
| 8 | -module GHC.Internal.Bignum.Backend.Selected
|
|
| 9 | - ( module Backend
|
|
| 10 | - )
|
|
| 11 | -where
|
|
| 12 | - |
|
| 13 | -#if defined(BIGNUM_NATIVE)
|
|
| 14 | -import GHC.Internal.Bignum.Backend.Native as Backend
|
|
| 15 | - |
|
| 16 | -#elif defined(BIGNUM_FFI)
|
|
| 17 | -import GHC.Internal.Bignum.Backend.FFI as Backend
|
|
| 18 | - |
|
| 19 | -#elif defined(BIGNUM_GMP)
|
|
| 20 | -import GHC.Internal.Bignum.Backend.GMP as Backend
|
|
| 21 | - |
|
| 22 | -#else
|
|
| 23 | -#error Undefined BigNum backend. Use a flag to select it (e.g. gmp, native, ffi)`
|
|
| 24 | -#endif |