Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
d603477f
by David Eichmann at 2026-05-29T13:17:12-04:00
-
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
-
ad79d02c
by David Eichmann at 2026-05-30T07:28:13-04:00
-
c80f15fa
by Matthew Pickering at 2026-05-30T07:28:16-04:00
29 changed files:
- + changelog.d/hadrian-system-cxx-std-lib-25303
- + 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/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.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
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
- rts/win32/libHSghc-internal.def.in
Changes:
| 1 | +section: packaging
|
|
| 2 | +synopsis: Fix Hadrian rules for system-cxx-std-lib package dependency
|
|
| 3 | +issues: #25303
|
|
| 4 | +mrs: !16013
|
|
| 5 | +description: {
|
|
| 6 | + Hadrian's handling of the `system-cxx-std-lib` virtual package has been
|
|
| 7 | + fixed and made more uniform.
|
|
| 8 | + |
|
| 9 | + Previously, `text` had an ad-hoc rule outside of `configurePackage` to
|
|
| 10 | + declare a dependency on `system-cxx-std-lib`, the dependency was not
|
|
| 11 | + discovered from cabal files, and the package database was not recached after
|
|
| 12 | + the `.conf` file was generated.
|
|
| 13 | + |
|
| 14 | + The dependency is now read from cabal files via a new
|
|
| 15 | + `dependsOnSystemCxxStdLib` field in `PackageData`, and the `.conf` file
|
|
| 16 | + is needed inside `configurePackage` alongside all other package
|
|
| 17 | + dependencies, consistent with how every other package is handled.
|
|
| 18 | + |
|
| 19 | + `shakeVersion` has been bumped to ensure existing build databases are
|
|
| 20 | + invalidated when upgrading, preventing binary deserialisation errors due to
|
|
| 21 | + the changed `PackageData` type.
|
|
| 22 | +} |
| 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,
|
| ... | ... | @@ -81,10 +81,11 @@ parsePackageData pkg = do |
| 81 | 81 | sorted = sort [ C.unPackageName p | C.Dependency p _ _ <- allDeps ]
|
| 82 | 82 | deps = nubOrd sorted \\ [name]
|
| 83 | 83 | depPkgs = mapMaybe findPackageByName deps
|
| 84 | + cxxStdLib = elem "system-cxx-std-lib" deps
|
|
| 84 | 85 | return $ PackageData name version
|
| 85 | 86 | (C.fromShortText (C.synopsis pd))
|
| 86 | 87 | (C.fromShortText (C.description pd))
|
| 87 | - depPkgs gpd
|
|
| 88 | + depPkgs cxxStdLib gpd
|
|
| 88 | 89 | where
|
| 89 | 90 | -- Collect an overapproximation of dependencies by ignoring conditionals
|
| 90 | 91 | collectDeps :: Maybe (C.CondTree v [C.Dependency] a) -> [C.Dependency]
|
| ... | ... | @@ -138,7 +139,9 @@ configurePackage :: Context -> Action () |
| 138 | 139 | configurePackage context@Context {..} = do
|
| 139 | 140 | putProgressInfo $ "| Configure package " ++ quote (pkgName package)
|
| 140 | 141 | gpd <- pkgGenericDescription package
|
| 141 | - depPkgs <- packageDependencies <$> readPackageData package
|
|
| 142 | + pd <- readPackageData package
|
|
| 143 | + let depPkgs = packageDependencies pd
|
|
| 144 | + needSystemCxxStdLib = dependsOnSystemCxxStdLib pd
|
|
| 142 | 145 | |
| 143 | 146 | -- Stage packages are those we have in this stage.
|
| 144 | 147 | stagePkgs <- stagePackages stage
|
| ... | ... | @@ -157,7 +160,12 @@ configurePackage context@Context {..} = do |
| 157 | 160 | -- We'll need those packages in our package database.
|
| 158 | 161 | deps <- sequence [ pkgConfFile (context { package = pkg, iplace = forceBaseAfterGhcInternal pkg })
|
| 159 | 162 | | pkg <- depPkgs, pkg `elem` stagePkgs ]
|
| 160 | - need $ extraPreConfigureDeps ++ deps
|
|
| 163 | + -- system-cxx-std-lib is magic.. it doesn't have a cabal file or source code, so we have
|
|
| 164 | + -- to treat it specially as `pkgConfFile` uses `readPackageData` to compute the version.
|
|
| 165 | + systemCxxStdLib <- sequence [ systemCxxStdLibConfPath (PackageDbLoc stage iplace) | needSystemCxxStdLib ]
|
|
| 166 | + need $ extraPreConfigureDeps
|
|
| 167 | + ++ deps
|
|
| 168 | + ++ systemCxxStdLib
|
|
| 161 | 169 | |
| 162 | 170 | -- Figure out what hooks we need.
|
| 163 | 171 | let configureFile = replaceFileName (pkgCabalFile package) "configure"
|
| ... | ... | @@ -30,6 +30,7 @@ data PackageData = PackageData |
| 30 | 30 | , synopsis :: String
|
| 31 | 31 | , description :: String
|
| 32 | 32 | , packageDependencies :: [Package]
|
| 33 | + , dependsOnSystemCxxStdLib :: Bool
|
|
| 33 | 34 | , genericPackageDescription :: GenericPackageDescription
|
| 34 | 35 | } deriving (Eq, Generic, Show)
|
| 35 | 36 |
| ... | ... | @@ -63,7 +63,13 @@ main = do |
| 63 | 63 | shakeColor <- shouldUseColor
|
| 64 | 64 | let options :: ShakeOptions
|
| 65 | 65 | options = shakeOptions
|
| 66 | - { shakeChange = ChangeModtimeAndDigest
|
|
| 66 | + { -- Bump shakeVersion whenever a type stored in the Shake oracle
|
|
| 67 | + -- changes its Binary representation (e.g. fields added/removed
|
|
| 68 | + -- from PackageData or other oracle value types). This forces
|
|
| 69 | + -- Shake to wipe the stale database instead of crashing on
|
|
| 70 | + -- deserialisation.
|
|
| 71 | + shakeVersion = "2"
|
|
| 72 | + , shakeChange = ChangeModtimeAndDigest
|
|
| 67 | 73 | , shakeFiles = buildRoot -/- Base.shakeFilesDir
|
| 68 | 74 | , shakeProgress = Progress.hadrianProgress cwd
|
| 69 | 75 | , shakeRebuild = rebuild
|
| ... | ... | @@ -242,9 +242,6 @@ copyRules = do |
| 242 | 242 | prefix -/- "html/**" <~ return "utils/haddock/haddock-api/resources"
|
| 243 | 243 | prefix -/- "latex/**" <~ return "utils/haddock/haddock-api/resources"
|
| 244 | 244 | |
| 245 | - forM_ [Inplace, Final] $ \iplace ->
|
|
| 246 | - root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
|
|
| 247 | - copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
|
|
| 248 | 245 | |
| 249 | 246 | generateRules :: Rules ()
|
| 250 | 247 | generateRules = do
|
| ... | ... | @@ -390,7 +387,6 @@ templateRules = do |
| 390 | 387 | , interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1
|
| 391 | 388 | , interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2
|
| 392 | 389 | ]
|
| 393 | - templateRule "rts/win32/libHSghc-internal.def" projectVersion
|
|
| 394 | 390 | templateRule "docs/index.html" $ packageUnitIds Stage1
|
| 395 | 391 | templateRule "docs/users_guide/ghc_config.py" $ mconcat
|
| 396 | 392 | [ projectVersion
|
| ... | ... | @@ -9,6 +9,7 @@ import GHC.Toolchain.Target (Target(tgtArchOs)) |
| 9 | 9 | |
| 10 | 10 | import Base
|
| 11 | 11 | import Context
|
| 12 | +import qualified Data.List as List
|
|
| 12 | 13 | import Expression hiding (way, package, stage)
|
| 13 | 14 | import Oracles.ModuleFiles
|
| 14 | 15 | import Packages
|
| ... | ... | @@ -20,6 +21,7 @@ import Utilities |
| 20 | 21 | import Data.Time.Clock
|
| 21 | 22 | import Rules.Generate (generatedDependencies)
|
| 22 | 23 | import Oracles.Flag
|
| 24 | +import Way.Type (wayToUnits)
|
|
| 23 | 25 | |
| 24 | 26 | |
| 25 | 27 | -- * Library 'Rules'
|
| ... | ... | @@ -203,13 +205,32 @@ extraObjects context |
| 203 | 205 | |
| 204 | 206 | | package context == rts = do
|
| 205 | 207 | target <- interpretInContext context getStagedTarget
|
| 206 | - builddir <- buildPath context
|
|
| 207 | - return [ builddir -/- "libHSghc-internal.dll.a"
|
|
| 208 | - | archOS_OS (tgtArchOs target) == OSMinGW32
|
|
| 209 | - , Dynamic `wayUnit` way context ]
|
|
| 208 | + if not (archOS_OS (tgtArchOs target) == OSMinGW32
|
|
| 209 | + && Dynamic `wayUnit` way context)
|
|
| 210 | + then return []
|
|
| 211 | + else do
|
|
| 212 | + -- Find the ghc-internal library file name. Note that the
|
|
| 213 | + -- ghc-internal's .dll.a file is placed in the RTS build dir and not
|
|
| 214 | + -- the ghc-internal build dir as we only use it when building the
|
|
| 215 | + -- RTS and not other libraries.
|
|
| 216 | + ghcInternalDllName <- takeFileName <$> pkgLibraryFile Context {
|
|
| 217 | + stage = stage context,
|
|
| 218 | + way = rtsWayToLibraryWay (way context),
|
|
| 219 | + iplace = iplace context,
|
|
| 220 | + package = ghcInternal
|
|
| 221 | + }
|
|
| 222 | + |
|
| 223 | + builddir <- buildPath context
|
|
| 224 | + return [ builddir -/- ghcInternalDllName <> ".a"]
|
|
| 210 | 225 | |
| 211 | 226 | | otherwise = return []
|
| 212 | 227 | |
| 228 | +-- | The rts is compiled in many different ways, but libraries are only built in
|
|
| 229 | +-- (non)Dynamic and (non)Profiled ways. This function converts the rts way into
|
|
| 230 | +-- compatible library way.
|
|
| 231 | +rtsWayToLibraryWay :: Way -> Way
|
|
| 232 | +rtsWayToLibraryWay = wayFromUnits . List.intersect [Dynamic, Profiling] . wayToUnits
|
|
| 233 | + |
|
| 213 | 234 | -- | Return all the object files to be put into the library we're building for
|
| 214 | 235 | -- the given 'Context'.
|
| 215 | 236 | libraryObjects :: Context -> Action [FilePath]
|
| ... | ... | @@ -6,7 +6,6 @@ module Rules.Register ( |
| 6 | 6 | |
| 7 | 7 | import Base
|
| 8 | 8 | import Context
|
| 9 | -import Flavour
|
|
| 10 | 9 | import Oracles.Setting
|
| 11 | 10 | import Hadrian.BuildPath
|
| 12 | 11 | import Hadrian.Expression
|
| ... | ... | @@ -48,14 +47,6 @@ configurePackageRules = do |
| 48 | 47 | isGmp <- (== "gmp") <$> interpretInContext ctx getBignumBackend
|
| 49 | 48 | when isGmp $
|
| 50 | 49 | need [buildP -/- "include/ghc-gmp.h"]
|
| 51 | - when (pkg == text) $ do
|
|
| 52 | - simdutf <- textWithSIMDUTF <$> flavour
|
|
| 53 | - when simdutf $ do
|
|
| 54 | - -- This is required, otherwise you get Error: hadrian:
|
|
| 55 | - -- Encountered missing or private dependencies:
|
|
| 56 | - -- system-cxx-std-lib ==1.0
|
|
| 57 | - cxxStdLib <- systemCxxStdLibConfPath $ PackageDbLoc stage Inplace
|
|
| 58 | - need [cxxStdLib]
|
|
| 59 | 50 | Cabal.configurePackage ctx
|
| 60 | 51 | |
| 61 | 52 | root -/- "**/autogen/cabal_macros.h" %> \out -> do
|
| ... | ... | @@ -105,6 +96,12 @@ registerPackageRules rs stage iplace = do |
| 105 | 96 | target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
|
| 106 | 97 | writeFileLines stamp []
|
| 107 | 98 | |
| 99 | + -- Special rule for registering system-cxx-std-lib
|
|
| 100 | + root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
|
|
| 101 | + copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
|
|
| 102 | + buildWithResources rs $
|
|
| 103 | + target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
|
|
| 104 | + |
|
| 108 | 105 | -- Register a package.
|
| 109 | 106 | root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- "*.conf" %> \conf -> do
|
| 110 | 107 | historyDisable
|
| ... | ... | @@ -13,11 +13,19 @@ rtsRules = priority 3 $ do |
| 13 | 13 | -- to be linked into the rts dll.
|
| 14 | 14 | forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do
|
| 15 | 15 | let buildPath = root -/- buildDir (rtsContext stage)
|
| 16 | - buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib
|
|
| 16 | + buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef
|
|
| 17 | + buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib
|
|
| 18 | + |
|
| 19 | +buildGhcInternalImportDef :: FilePath -> Action ()
|
|
| 20 | +buildGhcInternalImportDef target = do
|
|
| 21 | + templateIn <- readFile' "rts/win32/libHSghc-internal.def.in"
|
|
| 22 | + let dllName = takeFileName target -<.> "dll"
|
|
| 23 | + templateOut = replace "@GhcInternalDll@" dllName templateIn
|
|
| 24 | + writeFile' target templateOut
|
|
| 17 | 25 | |
| 18 | 26 | buildGhcInternalImportLib :: FilePath -> Action ()
|
| 19 | 27 | buildGhcInternalImportLib target = do
|
| 20 | - let input = "rts/win32/libHSghc-internal.def"
|
|
| 28 | + let input = dropExtensions target <.> "def" -- the .def file
|
|
| 21 | 29 | output = target -- the .dll.a import lib
|
| 22 | 30 | need [input]
|
| 23 | 31 | runBuilder Dlltool ["-d", input, "-l", output] [input] [output] |
| ... | ... | @@ -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 |
| ... | ... | @@ -549,6 +549,8 @@ allocGroupOnNode (uint32_t node, W_ n) |
| 549 | 549 | ln++;
|
| 550 | 550 | }
|
| 551 | 551 | |
| 552 | + // If no free blocks exist then allocate a new megablock and keep just a
|
|
| 553 | + // chunk of it.
|
|
| 552 | 554 | if (ln == NUM_FREE_LISTS) {
|
| 553 | 555 | #if 0 /* useful for debugging fragmentation */
|
| 554 | 556 | if ((W_)mblocks_allocated * BLOCKS_PER_MBLOCK * BLOCK_SIZE_W
|
| ... | ... | @@ -1020,6 +1022,9 @@ freeGroup(bdescr *p) |
| 1020 | 1022 | }
|
| 1021 | 1023 | |
| 1022 | 1024 | // coalesce backwards
|
| 1025 | + // Note that p is not a megablock/megagroup, so there are still live blocks on
|
|
| 1026 | + // this megablock. Hence we can't coalesce backwards past the first block
|
|
| 1027 | + // descriptor of this megablock.
|
|
| 1023 | 1028 | if (p != FIRST_BDESCR(MBLOCK_ROUND_DOWN(p)))
|
| 1024 | 1029 | {
|
| 1025 | 1030 | bdescr *prev;
|
| ... | ... | @@ -95,6 +95,10 @@ typedef struct free_list { |
| 95 | 95 | } free_list;
|
| 96 | 96 | |
| 97 | 97 | static free_list *free_list_head;
|
| 98 | + |
|
| 99 | +// The address in `mblock_address_space` just after the highest MBlock. This
|
|
| 100 | +// will be the address of the next new MBlock committed when the free list is
|
|
| 101 | +// empty.
|
|
| 98 | 102 | static W_ mblock_high_watermark;
|
| 99 | 103 | /*
|
| 100 | 104 | * it is quite important that these are in the same cache line as they
|
| ... | ... | @@ -103,22 +107,47 @@ static W_ mblock_high_watermark; |
| 103 | 107 | */
|
| 104 | 108 | struct mblock_address_range mblock_address_space = { 0, 0, {} };
|
| 105 | 109 | |
| 110 | +// Search for the first committed MBlock at or after startingAt.
|
|
| 111 | +//
|
|
| 112 | +// start_iter [in/out]: The free_list or a subset of it. Must contain all
|
|
| 113 | +// entries for MBlocks at or after startingAt. On return this is set to the
|
|
| 114 | +// free_list entry just after the returned MBlock. If no MBlock was found, This
|
|
| 115 | +// is set to NULL (the search will have reached the end of the free list).
|
|
| 116 | +//
|
|
| 117 | +// startingAt [in]: address from which to start searching. This must be to the
|
|
| 118 | +// start of an MBlock.
|
|
| 119 | +//
|
|
| 120 | +// return: The address of the committed MBlock. NULL if no committed MBLock was
|
|
| 121 | +// found.
|
|
| 122 | +//
|
|
| 106 | 123 | static void *getAllocatedMBlock(free_list **start_iter, W_ startingAt)
|
| 107 | 124 | {
|
| 125 | + // We simultaneously traverse the free list and the mblock_address_space.
|
|
| 108 | 126 | free_list *iter;
|
| 109 | 127 | W_ p = startingAt;
|
| 110 | 128 | |
| 111 | 129 | for (iter = *start_iter; iter != NULL; iter = iter->next)
|
| 112 | 130 | {
|
| 131 | + // The current free MBlock, `iter`, is past the current MBlock, `p`.
|
|
| 132 | + // This means that `p` is committed (if it was free, then we would have
|
|
| 133 | + // found it on the free list). Stop searching.
|
|
| 113 | 134 | if (p < iter->address)
|
| 114 | 135 | break;
|
| 115 | 136 | |
| 137 | + // Note that if `p > iter->address`, then we don't bump `p`. This just
|
|
| 138 | + // means we are skipping entries in the free list that correspond to
|
|
| 139 | + // MBlocks before `startingAt`.
|
|
| 116 | 140 | if (p == iter->address)
|
| 141 | + // Move to the next MBlock. The MBlock may be committed,
|
|
| 142 | + // uncommitted, or even past mblock_high_watermark.
|
|
| 117 | 143 | p += iter->size;
|
| 118 | 144 | }
|
| 119 | 145 | |
| 146 | + // Output current free list entry.
|
|
| 120 | 147 | *start_iter = iter;
|
| 121 | 148 | |
| 149 | + // If we reached mblock_high_watermark, then we didn't find any committed
|
|
| 150 | + // MBlocks.
|
|
| 122 | 151 | if (p >= mblock_high_watermark)
|
| 123 | 152 | return NULL;
|
| 124 | 153 | |
| ... | ... | @@ -152,6 +181,11 @@ void * getNextMBlock(void **state STG_UNUSED, void *mblock) |
| 152 | 181 | return getAllocatedMBlock(casted_state, (W_)mblock + MBLOCK_SIZE);
|
| 153 | 182 | }
|
| 154 | 183 | |
| 184 | +// Used to implement getCommittedMBlocks. Search the free list for n contiguous
|
|
| 185 | +// free MBlocks, and commit those MBlocks, updating the free_list. Returns the
|
|
| 186 | +// address of the start of those MBlocks. Returns NULL if no n contiguous
|
|
| 187 | +// MBlocks were found in the free list. Unlike getFreshMBlocks, this doesn't
|
|
| 188 | +// attempt to allocate new MBlocks past mblock_high_watermark.
|
|
| 155 | 189 | static void *getReusableMBlocks(uint32_t n)
|
| 156 | 190 | {
|
| 157 | 191 | struct free_list *iter;
|
| ... | ... | @@ -163,7 +197,10 @@ static void *getReusableMBlocks(uint32_t n) |
| 163 | 197 | if (iter->size < size)
|
| 164 | 198 | continue;
|
| 165 | 199 | |
| 200 | + // We've found a large enough group of MBlocks.
|
|
| 166 | 201 | addr = (void*)iter->address;
|
| 202 | + |
|
| 203 | + // Update the free list.
|
|
| 167 | 204 | iter->address += size;
|
| 168 | 205 | iter->size -= size;
|
| 169 | 206 | if (iter->size == 0) {
|
| ... | ... | @@ -190,6 +227,9 @@ static void *getReusableMBlocks(uint32_t n) |
| 190 | 227 | return NULL;
|
| 191 | 228 | }
|
| 192 | 229 | |
| 230 | +// Used to implement getCommittedMBlocks. Commit n new MBlocks starting at
|
|
| 231 | +// mblock_high_watermark. May exit with an out of memory error if we've passed
|
|
| 232 | +// mblock_address_space.end (this is unlikely).
|
|
| 193 | 233 | static void *getFreshMBlocks(uint32_t n)
|
| 194 | 234 | {
|
| 195 | 235 | W_ size = MBLOCK_SIZE * (W_)n;
|
| ... | ... | @@ -207,6 +247,8 @@ static void *getFreshMBlocks(uint32_t n) |
| 207 | 247 | return addr;
|
| 208 | 248 | }
|
| 209 | 249 | |
| 250 | +// Commit n new MBlocks. Tries to reuse freed MBlocks, else commits new
|
|
| 251 | +// MBlock(s) at mblock_high_watermark.
|
|
| 210 | 252 | static void *getCommittedMBlocks(uint32_t n)
|
| 211 | 253 | {
|
| 212 | 254 | void *p;
|
| ... | ... | @@ -220,6 +262,11 @@ static void *getCommittedMBlocks(uint32_t n) |
| 220 | 262 | return p;
|
| 221 | 263 | }
|
| 222 | 264 | |
| 265 | +// Decommit n contiguous MBlocks starting at the given address.
|
|
| 266 | +//
|
|
| 267 | +// addr [in]: address of the start of the n MBlocks (in mblock_address_space).
|
|
| 268 | +//
|
|
| 269 | +// n [in]: number of contiguous MBlocks to decommit.
|
|
| 223 | 270 | static void decommitMBlocks(char *addr, uint32_t n)
|
| 224 | 271 | {
|
| 225 | 272 | struct free_list *iter, *prev;
|
| ... | ... | @@ -228,17 +275,24 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 228 | 275 | |
| 229 | 276 | osDecommitMemory(addr, size);
|
| 230 | 277 | |
| 278 | + // Update the free list.
|
|
| 231 | 279 | prev = NULL;
|
| 232 | 280 | for (iter = free_list_head; iter != NULL; iter = iter->next)
|
| 233 | 281 | {
|
| 234 | 282 | prev = iter;
|
| 235 | 283 | |
| 284 | + // iter is still entirely behind and not contiguous with the MBlocks so
|
|
| 285 | + // continue traversing free_list.
|
|
| 236 | 286 | if (iter->address + iter->size < address)
|
| 237 | 287 | continue;
|
| 238 | 288 | |
| 289 | + // The MBlocks are after and contiguous to iter. Simply modify the
|
|
| 290 | + // current entry to include n more MBlocks and possibly coalesce.
|
|
| 239 | 291 | if (iter->address + iter->size == address) {
|
| 240 | 292 | iter->size += size;
|
| 241 | 293 | |
| 294 | + // If the current free_list entry now reaches mblock_high_watermark,
|
|
| 295 | + // remove the entry and decrement mblock_high_watermark.
|
|
| 242 | 296 | if (address + size == mblock_high_watermark) {
|
| 243 | 297 | mblock_high_watermark -= iter->size;
|
| 244 | 298 | if (iter->prev) {
|
| ... | ... | @@ -251,6 +305,8 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 251 | 305 | return;
|
| 252 | 306 | }
|
| 253 | 307 | |
| 308 | + // If the current free_list entry now reaches the next free_list
|
|
| 309 | + // entry, coalesce them.
|
|
| 254 | 310 | if (iter->next &&
|
| 255 | 311 | iter->next->address == iter->address + iter->size) {
|
| 256 | 312 | struct free_list *next;
|
| ... | ... | @@ -269,6 +325,8 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 269 | 325 | stgFree(next);
|
| 270 | 326 | }
|
| 271 | 327 | return;
|
| 328 | + |
|
| 329 | + // The MBlocks are before and contiguous to iter.
|
|
| 272 | 330 | } else if (address + size == iter->address) {
|
| 273 | 331 | iter->address = address;
|
| 274 | 332 | iter->size += size;
|
| ... | ... | @@ -280,6 +338,9 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 280 | 338 | ASSERT(iter->prev->address + iter->prev->size < iter->address);
|
| 281 | 339 | }
|
| 282 | 340 | return;
|
| 341 | + |
|
| 342 | + // The MBlocks are before and not contiguous to iter. Insert a new entry
|
|
| 343 | + // just before iter.
|
|
| 283 | 344 | } else {
|
| 284 | 345 | struct free_list *new_iter;
|
| 285 | 346 | |
| ... | ... | @@ -311,6 +372,7 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 311 | 372 | if (address + size == mblock_high_watermark) {
|
| 312 | 373 | mblock_high_watermark -= size;
|
| 313 | 374 | } else {
|
| 375 | + // Add a new entry to the end of the free list.
|
|
| 314 | 376 | struct free_list *new_iter;
|
| 315 | 377 | |
| 316 | 378 | new_iter = stgMallocBytes(sizeof(struct free_list), "freeMBlocks");
|
| 1 | -LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll
|
|
| 1 | +LIBRARY @GhcInternalDll@
|
|
| 2 | 2 | |
| 3 | 3 | EXPORTS
|
| 4 | 4 | init_ghc_hs_iface |