jacobi symbol
This commit is contained in:
@@ -25,3 +25,36 @@ factorOutTwos n = go n 0
|
||||
go x s
|
||||
| even x = go (x `div` 2) (s + 1)
|
||||
| otherwise = (x, s)
|
||||
|
||||
-- jacobi symbol (a/n)
|
||||
-- (a/n) in {-1, 0, 1}
|
||||
jacobi :: Integer -> Integer -> Integer
|
||||
jacobi a n
|
||||
| n <= 0 = error "jacobi: n must be positive"
|
||||
| even n = error "jacobi: n must be odd"
|
||||
| a `mod` n == 0 = 0
|
||||
| otherwise = go (a `mod` n) n 1
|
||||
where
|
||||
go :: Integer -> Integer -> Integer -> Integer
|
||||
go 0 _ _ = 0
|
||||
go 1 _ s = s
|
||||
go x m s =
|
||||
let (xOdd, e) = factorOutTwos x
|
||||
s' = if even e then s else s * jacobi2 m
|
||||
in
|
||||
if xOdd == 1
|
||||
then s'
|
||||
else
|
||||
let s'' = if (xOdd `mod` 4 == 3) && (m `mod` 4 == 3) then -s' else s'
|
||||
xNext = m `mod` xOdd
|
||||
in go xNext xOdd s''
|
||||
|
||||
-- Jacobi(2, m), helper function
|
||||
jacobi2 :: Integer -> Integer
|
||||
jacobi2 m =
|
||||
case m `mod` 8 of
|
||||
1 -> 1
|
||||
7 -> 1
|
||||
3 -> -1
|
||||
5 -> -1
|
||||
_ -> error "jacobi2: unexpected (m mod 8) for odd m"
|
||||
|
||||
Reference in New Issue
Block a user