-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ChineseRemainderS functions #71
Conversation
This proposed patch adds two new functions to this module; chineseRemainders/chineseRemainders2 (note the trailing S). These are the equivalent of the existing chineseRemainder/chineseRemainder2 functions, except: 1. They use the recently introduced SomeMod type both for its parameters and its results. 2. As a consequence they handle single-point congruence classes constructed with SomeMod's InfMod constructor. 3. They will return a solution for non-pairwise co-prime moduli, if one exists.
import Math.NumberTheory.Moduli.Class | ||
import Math.NumberTheory.Primes.Factorisation (factorise) | ||
|
||
-- [Unsure where to put these. Does arithmoi keep QuickCheck tests in separate documents? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, put tests into https://github.com/CarlEdman/arithmoi/blob/patch-1/test-suite/Math/NumberTheory/Moduli/ChineseTests.hs
You can continue editing files in https://github.com/CarlEdman/arithmoi/blob/patch-1 branch, changes will appear here automatically.
It is possible, but clumsy, because there is no type level division available. Things may change, if https://ghc.haskell.org/trac/ghc/ticket/13652 get implemented. Once I have implemented GCD on type level, but it is too slow for any practical purposes. {-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Proxy
import GHC.TypeLits
type family Cmp123 (o :: Ordering) (x :: Nat) (y :: Nat) (z :: Nat) :: Nat where
Cmp123 LT x y z = x
Cmp123 EQ x y z = y
Cmp123 GT x y z = z
type family GCD (x :: Nat) (y :: Nat) :: Nat where
GCD 0 x = x
GCD x 0 = x
GCD x y = Cmp123 (CmpNat x y) (GCD x (y - x)) x (GCD (x - y) y)
test :: Proxy (GCD 372 48) -> Proxy 12
test = id |
Sorry, I missed an important detail: the signature must contain {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeNats.Compat
import Math.NumberTheory.Moduli.Class
chineseRemainders2'
:: (KnownNat m, KnownNat n, KnownNat (m * n))
=> Mod m -> Mod n -> Maybe (Mod (m * n))
chineseRemainders2' x y = undefined |
Well, I'd better try it myself before giving wrong advices. The problem with the signature above is that in a context like someChineseRemainders' :: SomeMod -> SomeMod -> SomeMod
someChineseRemainders'
(SomeMod x) (SomeMod y)
= (SomeMod x) (SomeMod y) = SomeMod (fromMaybe undefined $ chineseRemainders2' x y) we have This is exactly a use case for {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
import Data.Maybe
import GHC.TypeNats.Compat
import Math.NumberTheory.Moduli.Class
chineseRemainders2'
:: (KnownNat m, KnownNat n, KnownNat (m * n))
=> Mod m -> Mod n -> Maybe (Mod (m * n))
chineseRemainders2' x y = undefined x y
someChineseRemainders2'
:: SomeMod -> SomeMod -> SomeMod
someChineseRemainders2'
(SomeMod x) (SomeMod y) = SomeMod (fromMaybe undefined $ chineseRemainders2' x y) |
@CarlEdman feel free to poke me, if there are difficulties (especially technical) of any kind. I am afraid that my comments above appeared to be too frightening. |
@Bodigrim No need for fear! Your comments are much appreciated. My tardiness is related to other time pressures, rather than anything you said. |
Cool. I did not mean to put pressure on you; sorry, if it sounded this way. |
BTW there is a simpler solution to http://hackage.haskell.org/package/constraints-0.9.1/docs/Data-Constraint-Nat.html#v:timesNat |
The complete snippet with {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
import Data.Maybe
import GHC.TypeNats.Compat
import Math.NumberTheory.Moduli.Class
import Data.Constraint
import Data.Constraint.Nat (timesNat)
chineseRemainders2'
:: (KnownNat m, KnownNat n)
=> Mod m -> Mod n -> Maybe (Mod (m * n))
chineseRemainders2' x y = undefined x y
someChineseRemainders2'
:: SomeMod -> SomeMod -> SomeMod
someChineseRemainders2'
(SomeMod (x :: Mod m)) (SomeMod (y :: Mod n)) = case timesNat @m @n of
Sub Dict -> SomeMod (fromMaybe undefined $ chineseRemainders2' x y) |
Type-level division landed into base-4.11, shipped with GHC 8.4: https://downloads.haskell.org/~ghc/master/libraries/base/base/GHC-TypeNats.html#t:Div |
@CarlEdman thanks for valuable ideas! I reworked your code in a1d86d8, avoiding factorisation. Unfortunately and despite all discussion above, having a function with known moduli on type level is next to useless. chineseCoprimeMod :: (KnownNat m1, KnownNat m2) => Mod m1 -> Mod m2 -> Maybe (Mod (m1 * m2)) The problem is that even if inside :set -XDataKinds -XTypeApplications
import Data.Constraint
import Data.Constraint.Nat (timesNat)
print $ case timesNat @2 @3 of
Sub Dict -> fmap SomeMod (chineseCoprimeMod (1 :: Mod 2) (2 :: Mod 3)) It does not look worth a trouble, so I decided to remove such functions from API. |
This proposed patch adds two new functions to this module; chineseRemainders/chineseRemainders2 (note the trailing S). These are the equivalent of the existing chineseRemainder/chineseRemainder2 functions, except: