-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBasic.hs
More file actions
130 lines (106 loc) · 4.01 KB
/
Basic.hs
File metadata and controls
130 lines (106 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
module Basic (hOut, Term(..), Element(..)) where
import Data.List
import Control.Applicative
data Element = Element { symbol :: String, index :: Int } deriving (Eq, Ord)
data Term = Term Int Element Element deriving (Eq, Ord)
data Prime = Prime Int Int
instance Show Element where
show (Element x n) = x ++ show n
instance Show Term where
show (Term n e1 e2) = show n ++ " " ++ show e1 ++ show e2
instance Show Prime where
show (Prime m k) = "2^" ++ show m ++ " - " ++ show k
-- # Parameters
--p25519 = Prime 521 1
--limbs = take 17 $ repeat 31
--p25519 = Prime 127 1
--limbs = [26,25,26,25,25]
--limbs = [26,26,26,26,26]
p25519 :: Prime
p25519 = Prime 255 19
limbs :: [Int]
limbs = [26,25,26,25,26,25,26,25,26,25]
--limbs = take 9 $ cycle [29,28,28]
--limbs = [27,25,26,25,26,25,26,25,25,25]
--limbs = [24,23,23,23,23,24,23,23,23,23,23]
--limbs = take 10 $ cycle [27,24]
nLimbs :: Int
nLimbs = length limbs
radix :: [Int]
radix = map sum (inits $ cycle limbs)
--printParameters = do
-- putStrLn $ "Prime: " ++ show p25519
-- putStrLn $ "Size: " ++ show nLimbs ++ ", " ++ show (sum limbs)
-- putStrLn $ "Limbs: " ++ show limbs
-- putStrLn $ "Radix: " ++ show (take (2 * nLimbs) radix)
-- print checkRadix
-- * We want a "good" limb representation (deifintion of "good"??)
-- A Wrong check => if n = 10, then in limbs[], for any k <= 5, sum of first(?) k subsequent elements
-- must >= any k subsequent elements that come after at any position
-- (it's better to minimize their difference)
-- For example, [26,25,26,25,26,25,26,25,26,25]
-- ^^^^^^^^ ^^^^^^^^
-- sum of FIRST 3 >= sum of any 3 subsequent
--checkRadix = all (\(a,b) -> radix !! a + radix !! b >= radix !! (a+b)) [(a,b) | a <- [0..nLimbs-1], b <- [0..nLimbs-1]]
-- # Radix Operations
mulElements :: Element -> Element -> Term
mulElements x y = Term (2 ^ n) x y
where
base = radix !! index x + radix !! index y
n = base - last (takeWhile (<= base) radix)
-- a good limb representation is one where
-- n == base - radix !! (index x + index y)
wrapAround :: Term -> Term
wrapAround (Term _ x y) = Term n' x y
where
base = radix !! index x + radix !! index y - m -- a bad limb representation would have base < 0
n = base - last (takeWhile (<= base) radix)
n' = k * 2 ^ n
Prime m k = p25519
-- # Polynomial Multiplication
add :: [[Term]] -> [[Term]] -> [[Term]] -- can be more general [[a]]
add (x:xs) (y:ys) = (x ++ y) : add xs ys
add xs@(_:_) _ = xs
add _ ys@(_:_) = ys
add _ _ = []
multiply :: [Element] -> [Element] -> [[Term]]
multiply (x:xs) ys'@(y:ys) =
[mulElements x y] : add (multiply [x] ys) (multiply xs ys')
multiply _ _ = []
-- This assumes a good limb representation
reduce :: [[Term]] -> [[Term]]
reduce xs = add p $ map wrapAround <$> q
where
(p, q) = splitAt nLimbs xs
mulreduce :: [Element] -> [Element] -> [[Term]]
mulreduce x y = reduce $ multiply x y
-- # Testing
f, g :: [Element]
f = map (Element "f") [0..nLimbs-1]
g = map (Element "g") [0..nLimbs-1]
hOut :: [[Term]]
hOut = mulreduce f g
--main :: IO()
--main = do
-- printParameters
-- putStrLn "\n===== Input ====="
-- putStrLn $ "f = " ++ show f
-- putStrLn $ "g = " ++ show g
-- let h = multiply f g
-- putStrLn "\n===== Multiplication ====="
-- mapM_ print h
-- putStrLn "\n===== Reduction ====="
-- let h' = reduce h
-- mapM_ print h'
-- putStrLn "\n===== LaTeX Output ====="
-- putStrLn $ printLatex h'
-- # Latex Pretty Printer
--printLatex :: [[Term]] -> String
--printLatex xs = "\\begin{alignat}{" ++ show (n + 1) ++ "}\n" ++ intercalate "\\\\\n" (zipWith printLatex' xs [0..]) ++ "\n\\end{alignat}"
--printLatex' :: [Term] -> Int -> String
--printLatex' xs n = "h_{" ++ show n ++ "} &= & " ++ intercalate "+& & " (map helper xs)
-- where
-- helper' (Element x n) = x ++ "_{" ++ show n ++ "}"
-- helper (Term n e1 e2)
-- | n == 1 = helper' e1 ++ helper' e2
-- | otherwise = show n ++ " " ++ helper' e1 ++ helper' e2