annotate tommath.tex @ 190:d8254fc979e9 libtommath-orig LTM_0.35

Initial import of libtommath 0.35
author Matt Johnston <matt@ucc.asn.au>
date Fri, 06 May 2005 08:59:30 +0000
parents d29b64170cf0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1 \documentclass[b5paper]{book}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2 \usepackage{hyperref}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3 \usepackage{makeidx}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4 \usepackage{amssymb}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5 \usepackage{color}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6 \usepackage{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7 \usepackage{graphicx}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8 \usepackage{layout}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9 \def\union{\cup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10 \def\intersect{\cap}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
11 \def\getsrandom{\stackrel{\rm R}{\gets}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
12 \def\cross{\times}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
13 \def\cat{\hspace{0.5em} \| \hspace{0.5em}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
14 \def\catn{$\|$}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
15 \def\divides{\hspace{0.3em} | \hspace{0.3em}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
16 \def\nequiv{\not\equiv}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
17 \def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
18 \def\lcm{{\rm lcm}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
19 \def\gcd{{\rm gcd}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
20 \def\log{{\rm log}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
21 \def\ord{{\rm ord}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
22 \def\abs{{\mathit abs}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
23 \def\rep{{\mathit rep}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
24 \def\mod{{\mathit\ mod\ }}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
25 \renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
26 \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
27 \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
28 \def\Or{{\rm\ or\ }}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
29 \def\And{{\rm\ and\ }}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
30 \def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
31 \def\implies{\Rightarrow}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
32 \def\undefined{{\rm ``undefined"}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
33 \def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
34 \let\oldphi\phi
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
35 \def\phi{\varphi}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
36 \def\Pr{{\rm Pr}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
37 \newcommand{\str}[1]{{\mathbf{#1}}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
38 \def\F{{\mathbb F}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
39 \def\N{{\mathbb N}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
40 \def\Z{{\mathbb Z}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
41 \def\R{{\mathbb R}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
42 \def\C{{\mathbb C}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
43 \def\Q{{\mathbb Q}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
44 \definecolor{DGray}{gray}{0.5}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
45 \newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
46 \def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
47 \def\gap{\vspace{0.5ex}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
48 \makeindex
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49 \begin{document}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 \frontmatter
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51 \pagestyle{empty}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
52 \title{Multi--Precision Math}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
53 \author{\mbox{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
54 %\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
55 \begin{tabular}{c}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 Tom St Denis \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57 Algonquin College \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
59 Mads Rasmussen \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60 Open Communications Security \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62 Greg Rose \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 QUALCOMM Australia \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
65 %\end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
66 }
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
67 }
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
68 \maketitle
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
69 This text has been placed in the public domain. This text corresponds to the v0.35 release of the
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70 LibTomMath project.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
71
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
73 Tom St Denis
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
74 111 Banning Rd
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
75 Ottawa, Ontario
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76 K2L 1C3
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77 Canada
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
78
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
79 Phone: 1-613-836-3160
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
80 Email: [email protected]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
81 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
82
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
83 This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
84 {\em book} macro package and the Perl {\em booker} package.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
85
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
86 \tableofcontents
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
87 \listoffigures
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
88 \chapter*{Prefaces}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
89 When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
90 They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.''
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
91 Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
92 perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
93 others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
94 back to society in the form of tools and knowledge that can help others in their endeavours.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
95
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
96 I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
97 code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
98 explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
99 itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
100 of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
101 from relatively straightforward algebra and I hope that this book can be a valuable learning asset.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
102
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
103 This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
104 of kind people donating their time, resources and kind words to help support my work. Writing a text of significant
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
105 length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
106 comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
107 were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
108 continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
109
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
110 To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
111 honour your kind gestures with this project.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
112
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
113 Open Source. Open Academia. Open Minds.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
114
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
115 \begin{flushright} Tom St Denis \end{flushright}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
116
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
117 \newpage
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
118 I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
119 contribute to educate others facing the problem of having to handle big number mathematical calculations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
120
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
121 This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
122 how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
123 the layout and language used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
124
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
125 I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
126 practical aspects of cryptography.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
127
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
128 Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
129 great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
130 multiple precision calculations is often very important since we deal with outdated machine architecture where modular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
131 reductions, for example, become painfully slow.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
132
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
133 This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
134 themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
135
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
136 \begin{flushright}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
137 Mads Rasmussen
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
138
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
139 S\~{a}o Paulo - SP
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
140
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
141 Brazil
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
142 \end{flushright}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
143
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
144 \newpage
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
145 It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
146 Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
147 really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
148
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
149 At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
150 sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
151 contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
152 Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
153
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
154 When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
155 and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
156 friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
157 and I'm pleased to be involved with it.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
158
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
159 \begin{flushright}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
160 Greg Rose, Sydney, Australia, June 2003.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
161 \end{flushright}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
162
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
163 \mainmatter
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
164 \pagestyle{headings}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
165 \chapter{Introduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
166 \section{Multiple Precision Arithmetic}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
167
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
168 \subsection{What is Multiple Precision Arithmetic?}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
169 When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
170 raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
171 reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
172 Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
173 precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
174 of algorithms can be designed to accomodate them.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
175
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
176 By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
177 the decimal system with fixed precision $6 \cdot 7 = 2$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
178
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
179 Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
180 schools to manually add, subtract, multiply and divide.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
181
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
182 \subsection{The Need for Multiple Precision Arithmetic}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
183 The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
184 of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
185 integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
186 typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
187 Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
188
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
189 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
190 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
191 \begin{tabular}{|r|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
192 \hline \textbf{Data Type} & \textbf{Range} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
193 \hline char & $-128 \ldots 127$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
194 \hline short & $-32768 \ldots 32767$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
195 \hline long & $-2147483648 \ldots 2147483647$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
196 \hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
197 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
198 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
199 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
200 \caption{Typical Data Types for the C Programming Language}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
201 \label{fig:ISOC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
202 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
203
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
204 The largest data type guaranteed to be provided by the ISO C programming
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
205 language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
206 see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
207 insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
208 trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
209 rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
210 extending the range of representable integers while using single precision data types.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
211
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
212 Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
213 primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
214 various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
215 major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
216 deployment of efficient algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
217
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
218 However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
219 Another auxiliary use of multiple precision integers is high precision floating point data types.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
220 The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
221 Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
222 floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
223 (\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
224 a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
225 scientific applications must minimize the total output error over long calculations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
226
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
227 Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$).
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
228 In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
229
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
230 \subsection{Benefits of Multiple Precision Arithmetic}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
231 \index{precision}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
232 The benefit of multiple precision representations over single or fixed precision representations is that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
233 no precision is lost while representing the result of an operation which requires excess precision. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
234 the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
235 precision algorithm would augment the precision of the destination to accomodate the result while a single precision system
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
236 would truncate excess bits to maintain a fixed level of precision.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
237
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
238 It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
239 curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
240 size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
241 integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
242 processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
243 normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
244
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
245 Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
246 overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
247 platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
248 inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
249 without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
250 be written and tested once.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
251
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
252 \section{Purpose of This Text}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
253 The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
254 That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
255 elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
256 give considerably detailed explanations of the theoretical aspects of algorithms and often very little information
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
257 regarding the practical implementation aspects.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
258
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
259 In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
260 example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
261 algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
262 the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
263 as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
264 discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
265
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
266 Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
267 and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
268 any form of useful performance in non-trivial applications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
269
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
270 To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
271 package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.org}} package is used
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
272 to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
273 tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
274 discusses a very large portion of the inner workings of the library.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
275
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
276 The algorithms that are presented will always include at least one ``pseudo-code'' description followed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
277 by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
278 algorithm in other programming languages as the reader sees fit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
279
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
280 This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
281 the reader how the algorithms fit together as well as where to start on various taskings.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
282
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
283 \section{Discussion and Notation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
284 \subsection{Notation}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
285 A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
286 the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
287 of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
288 $1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
289
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
290 \index{mp\_int}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
291 The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
292 as auxilary data required to manipulate the data. These additional members are discussed further in section
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
293 \ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
294 synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
295 are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
296 member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
297 evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
298 $a.length = 5$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
299
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
300 For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
301 to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
302 a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
303 mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
304 algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
305 precision algorithm to solve the same problem.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
306
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
307 \subsection{Precision Notation}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
308 The variable $\beta$ represents the radix of a single digit of a multiple precision integer and
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
309 must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
310 the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
311 $0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
312 carry. Since all modern computers are binary, it is assumed that $q$ is two.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
313
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
314 \index{mp\_digit} \index{mp\_word}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
315 Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
316 a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
317 several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
318 For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
319 the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
320 variable it is assumed that all single precision variables are promoted to double precision during the evaluation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
321 Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
322 precision data type.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
323
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
324 For example, if $\beta = 10^2$ a single precision data type may represent a value in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
325 range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
326 $a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
327 as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
328 In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
329 in a single precision data type and as a result $c \ne \hat c$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
330
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
331 \subsection{Algorithm Inputs and Outputs}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
332 Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
333 as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
334 distinction is important as scalars are often used as array indicies and various other counters.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
335
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
336 \subsection{Mathematical Expressions}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
337 The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
338 itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
339 rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
340 the $/$ division symbol is used the intention is to perform an integer division with truncation. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
341 $5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
342 fraction a real value division is implied, for example ${5 \over 2} = 2.5$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
343
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
344 The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
345 of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
346
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
347 \subsection{Work Effort}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
348 \index{big-Oh}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
349 To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
350 single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
351 That is a single precision addition, multiplication and division are assumed to take the same time to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
352 complete. While this is generally not true in practice, it will simplify the discussions considerably.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
353
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
354 Some algorithms have slight advantages over others which is why some constants will not be removed in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
355 the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
356 baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
357 would both be said to be equivalent to $O(n^2)$. However,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
358 in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
359 result small constant factors in the work effort will make an observable difference in algorithm efficiency.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
360
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
361 All of the algorithms presented in this text have a polynomial time work level. That is, of the form
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
362 $O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
363 various optimizations will help pay off in the long run.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
364
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
365 \section{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
366 Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
367 the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
368 provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
369 chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
370 subject material.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
371
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
372 That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
373 are encouraged to verify they can answer the problems correctly before moving on.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
374
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
375 Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
376 the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
377 exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
378 scoring system used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
379
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
380 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
381 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
382 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
383 \begin{tabular}{|c|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
384 \hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
385 & minutes to solve. Usually does not involve much computer time \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
386 & to solve. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
387 \hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
388 & time usage. Usually requires a program to be written to \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
389 & solve the problem. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
390 \hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
391 & of work. Usually involves trivial research and development of \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
392 & new theory from the perspective of a student. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
393 \hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
394 & of work and research, the solution to which will demonstrate \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
395 & a higher mastery of the subject matter. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
396 \hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
397 & novice to solve. Solutions to these problems will demonstrate a \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
398 & complete mastery of the given subject. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
399 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
400 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
401 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
402 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
403 \caption{Exercise Scoring System}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
404 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
405
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
406 Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
407 devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
408 are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
409 two levels are essentially entry level questions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
410
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
411 Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
412 fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
413 involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
414 answer these questions will feel comfortable with the concepts behind the topic at hand.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
415
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
416 Problems at the fourth level are meant to be similar to those of the level three questions except they will require
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
417 additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
418 the exact details of the answer until a subsequent chapter.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
419
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
420 Problems at the fifth level are meant to be the hardest
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
421 problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
422 mastery of the subject matter at hand.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
423
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
424 Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
425 is encouraged to answer the follow-up problems and try to draw the relevance of problems.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
426
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
427 \section{Introduction to LibTomMath}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
428
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
429 \subsection{What is LibTomMath?}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
430 LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
431 is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
432 any given platform.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
433
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
434 The library has been successfully tested under numerous operating systems including Unix\footnote{All of these
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
435 trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
436 as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
437 as public key cryptosystems and still maintain a relatively small footprint.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
438
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
439 \subsection{Goals of LibTomMath}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
440
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
441 Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
442 even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
443 library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
444 processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
445 exponentiation and Montgomery reduction have been provided to make the library more efficient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
446
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
447 Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
448 (\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
449 algorithms automatically without the developer's specific attention. One such example is the generic multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
450 algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
451 based on the magnitude of the inputs and the configuration of the library.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
452
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
453 Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
454 be source compatible with another popular library which makes it more attractive for developers to use. In this case the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
455 MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
456 in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
457 passing conventions, it has been written from scratch by Tom St Denis.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
458
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
459 The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
460 library exists which can be used to teach computer science students how to perform fast and reliable multiple precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
461 integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
462
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
463 \section{Choice of LibTomMath}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
464 LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
465 for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
466 \cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
467 reasons that will be explained in the following sub-sections.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
468
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
469 \subsection{Code Base}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
470 The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
471 segments of code littered throughout the source. This clean and uncluttered approach to the library means that a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
472 developer can more readily discern the true intent of a given section of source code without trying to keep track of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
473 what conditional code will be used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
474
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
475 The code base of LibTomMath is well organized. Each function is in its own separate source code file
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
476 which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
477 file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
478 very hard. GMP has many conditional code segments which also hinder tracing.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
479
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
480 When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
481 which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
482 $50$KiB) but LibTomMath is also much faster and more complete than MPI.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
483
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
484 \subsection{API Simplicity}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
485 LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
486 with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
487 functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
488 which is an extremely valuable benefit for the student and developer alike.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
489
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
490 The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
491 illegible short hand. LibTomMath does not share this characteristic.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
492
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
493 The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
494 are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
495 effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
496 undersireable in many situations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
497
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
498 \subsection{Optimizations}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
499 While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
500 feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
501 and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
502 of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
503 only had Barrett and Montgomery modular reduction algorithms.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
504
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
505 LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
506 exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
507 slower than the best libraries such as GMP and OpenSSL by only a small factor.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
508
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
509 \subsection{Portability and Stability}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
510 LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
511 (\textit{GCC}). This means that without changes the library will build without configuration or setting up any
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
512 variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
513 MPI has recently stopped working on his library and LIP has long since been discontinued.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
514
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
515 GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
516 development and are very stable across a variety of platforms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
517
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
518 \subsection{Choice}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
519 LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
520 the case study of this text. Various source files from the LibTomMath project will be included within the text. However,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
521 the reader is encouraged to download their own copy of the library to actually be able to work with the library.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
522
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
523 \chapter{Getting Started}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
524 \section{Library Basics}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
525 The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
526 a problem along with allowable solution parameters should be identified and analyzed. In this particular case the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
527 inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
528 as portable source code that is reasonably efficient across several different computer platforms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
529
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
530 After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
531 That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
532 before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
533 By building outwards from a base foundation instead of using a parallel design methodology the resulting project is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
534 highly modular. Being highly modular is a desirable property of any project as it often means the resulting product
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
535 has a small footprint and updates are easy to perform.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
536
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
537 Usually when I start a project I will begin with the header files. I define the data types I think I will need and
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
538 prototype the initial functions that are not dependent on other functions (within the library). After I
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
539 implement these base functions I prototype more dependent functions and implement them. The process repeats until
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
540 I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
541 mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
542 why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
543 dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
544 mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
545 for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
546
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
547 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
548 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
549 \includegraphics{pics/design_process.ps}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
550 \caption{Design Flow of the First Few Original LibTomMath Functions.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
551 \label{pic:design_process}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
552 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
553 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
554
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
555 Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
556 the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
557
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
558 It only makes sense to begin the text with the preliminary data types and support algorithms required as well.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
559 This chapter discusses the core algorithms of the library which are the dependents for every other algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
560
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
561 \section{What is a Multiple Precision Integer?}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
562 Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
563 be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
564 to use fixed precision data types to create and manipulate multiple precision integers which may represent values
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
565 that are very large.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
566
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
567 As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
568 the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
569 (\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
570 column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
571 multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
572 precision computer words with the exception that a different radix is used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
573
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
574 What most people probably do not think about explicitly are the various other attributes that describe a multiple precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
575 integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
576 that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
577 its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
578 arithmetic. The third property is how many digits placeholders are available to hold the integer.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
579
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
580 The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
581 if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
582 Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
583 will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
584 integer or mp\_int for short.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
585
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
586 \subsection{The mp\_int Structure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
587 \label{sec:MPINT}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
588 The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
589 any such data type but it does provide for making composite data types known as structures. The following is the structure definition
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
590 used within LibTomMath.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
591
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
592 \index{mp\_int}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
593 \begin{figure}[here]
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
594 \begin{center}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
595 \begin{small}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
596 %\begin{verbatim}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
597 \begin{tabular}{|l|}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
598 \hline
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
599 typedef struct \{ \\
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
600 \hspace{3mm}int used, alloc, sign;\\
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
601 \hspace{3mm}mp\_digit *dp;\\
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
602 \} \textbf{mp\_int}; \\
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
603 \hline
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
604 \end{tabular}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
605 %\end{verbatim}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
606 \end{small}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
607 \caption{The mp\_int Structure}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
608 \label{fig:mpint}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
609 \end{center}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
610 \end{figure}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
611
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
612 The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
613
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
614 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
615 \item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
616 a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
617
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
618 \item The \textbf{alloc} parameter denotes how
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
619 many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
620 of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
621 array to accommodate the precision of the result.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
622
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
623 \item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
624 precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
625 significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
626 first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
627 if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
628 it would represent the integer $a + b\beta + c\beta^2 + \ldots$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
629
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
630 \index{MP\_ZPOS} \index{MP\_NEG}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
631 \item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
632 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
633
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
634 \subsubsection{Valid mp\_int Structures}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
635 Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
636 The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy().
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
637
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
638 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
639 \item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
640 array of digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
641 \item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
642 \item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
643 leading zero digits in the most significant positions must be trimmed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
644 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
645 \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
646 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
647 \item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
648 this represents the mp\_int value of zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
649 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
650
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
651 \section{Argument Passing}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
652 A convention of argument passing must be adopted early on in the development of any library. Making the function
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
653 prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
654 In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
655 structures. That means that the source (input) operands are placed on the left and the destination (output) on the right.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
656 Consider the following examples.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
657
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
658 \begin{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
659 mp_mul(&a, &b, &c); /* c = a * b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
660 mp_add(&a, &b, &a); /* a = a + b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
661 mp_sqr(&a, &b); /* b = a * a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
662 \end{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
663
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
664 The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
665 functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
666
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
667 Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
668 of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
669 truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
670 adopted.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
671
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
672 Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
673 destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
674 feature to implement since it allows the calling functions to cut down on the number of variables it must maintain.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
675 However, to implement this feature specific care has to be given to ensure the destination is not modified before the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
676 source is fully read.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
677
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
678 \section{Return Values}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
679 A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
680 to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
681 developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
682 fault by dereferencing memory not owned by the application.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
683
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
684 In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
685 instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
686 will it check pointers for validity. Any function that can cause a runtime error will return an error code as an
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
687 \textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
688
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
689 \index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
690 \begin{figure}[here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
691 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
692 \begin{tabular}{|l|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
693 \hline \textbf{Value} & \textbf{Meaning} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
694 \hline \textbf{MP\_OKAY} & The function was successful \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
695 \hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
696 \hline \textbf{MP\_MEM} & The function ran out of heap memory \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
697 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
698 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
699 \end{center}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
700 \caption{LibTomMath Error Codes}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
701 \label{fig:errcodes}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
702 \end{figure}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
703
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
704 When an error is detected within a function it should free any memory it allocated, often during the initialization of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
705 temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
706 function was called. Error checking with this style of API is fairly simple.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
707
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
708 \begin{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
709 int err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
710 if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
711 printf("Error: %s\n", mp_error_to_string(err));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
712 exit(EXIT_FAILURE);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
713 }
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
714 \end{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
715
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
716 The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
717 and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
718
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
719 \section{Initialization and Clearing}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
720 The logical starting point when actually writing multiple precision integer functions is the initialization and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
721 clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
722
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
723 Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
724 the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
725 the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
726 would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
727 and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
728 memory and become unmanageable.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
729
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
730 If the memory for the digits has been successfully allocated then the rest of the members of the structure must
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
731 be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
732 to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
733
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
734 \subsection{Initializing an mp\_int}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
735 An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
736 structure are set to valid values. The mp\_init algorithm will perform such an action.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
737
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
738 \index{mp\_init}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
739 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
740 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
741 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
742 \hline Algorithm \textbf{mp\_init}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
743 \textbf{Input}. An mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
744 \textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
745 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
746 1. Allocate memory for \textbf{MP\_PREC} digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
747 2. If the allocation failed return(\textit{MP\_MEM}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
748 3. for $n$ from $0$ to $MP\_PREC - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
749 \hspace{3mm}3.1 $a_n \leftarrow 0$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
750 4. $a.sign \leftarrow MP\_ZPOS$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
751 5. $a.used \leftarrow 0$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
752 6. $a.alloc \leftarrow MP\_PREC$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
753 7. Return(\textit{MP\_OKAY})\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
754 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
755 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
756 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
757 \caption{Algorithm mp\_init}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
758 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
759
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
760 \textbf{Algorithm mp\_init.}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
761 The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
762 manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
763 a valid assumption if the input resides on the stack.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
764
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
765 Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
766 the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
767 name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
768 used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
769 precision number you'll be working with.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
770
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
771 Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
772 heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
773 memory and the number of heap operations will be trivial.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
774
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
775 Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
776 \textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
777 of the original condition of the input.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
778
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
779 \textbf{Remark.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
780 This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
781 when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
782 a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
783 iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
784 the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
785 decrementally.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
786
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
787 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
788 \hspace{-5.1mm}{\bf File}: bn\_mp\_init.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
789 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
790 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
791 016
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
792 017 /* init a new mp_int */
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
793 018 int mp_init (mp_int * a)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
794 019 \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
795 020 int i;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
796 021
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
797 022 /* allocate memory required and clear it */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
798 023 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
799 024 if (a->dp == NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
800 025 return MP_MEM;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
801 026 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
802 027
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
803 028 /* set the digits to zero */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
804 029 for (i = 0; i < MP_PREC; i++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
805 030 a->dp[i] = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
806 031 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
807 032
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
808 033 /* set the used to zero, allocated digits to the default precision
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
809 034 * and sign to positive */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
810 035 a->used = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
811 036 a->alloc = MP_PREC;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
812 037 a->sign = MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
813 038
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
814 039 return MP_OKAY;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
815 040 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
816 041 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
817 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
818 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
819
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
820 One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
821 is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
822 call to mp\_init() is used only to initialize the members of the structure to a known default state.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
823
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
824 Here we see (line 23) the memory allocation is performed first. This allows us to exit cleanly and quickly
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
825 if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
826 was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
827 but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
828 memory allocation routine.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
829
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
830 In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
831 accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
832 portable fashion you have to actually assign the value. The for loop (line 29) performs this required
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
833 operation.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
834
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
835 After the memory has been successfully initialized the remainder of the members are initialized
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
836 (lines 33 through 34) to their respective default states. At this point the algorithm has succeeded and
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
837 a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
838 mp\_int structure has been properly initialized and is safe to use with other functions within the library.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
839
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
840 \subsection{Clearing an mp\_int}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
841 When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
842 returned to the application's memory pool with the mp\_clear algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
843
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
844 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
845 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
846 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
847 \hline Algorithm \textbf{mp\_clear}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
848 \textbf{Input}. An mp\_int $a$ \\
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
849 \textbf{Output}. The memory for $a$ shall be deallocated. \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
850 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
851 1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
852 2. for $n$ from 0 to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
853 \hspace{3mm}2.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
854 3. Free the memory allocated for the digits of $a$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
855 4. $a.used \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
856 5. $a.alloc \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
857 6. $a.sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
858 7. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
859 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
860 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
861 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
862 \caption{Algorithm mp\_clear}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
863 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
864
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
865 \textbf{Algorithm mp\_clear.}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
866 This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
867 if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
868 is to free the allocated memory.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
869
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
870 The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
871 algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
872 digit pointer \textbf{dp} setting.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
873
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
874 Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
875 with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
876
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
877 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
878 \hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
879 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
880 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
881 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
882 017 /* clear one (frees) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
883 018 void
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
884 019 mp_clear (mp_int * a)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
885 020 \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
886 021 int i;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
887 022
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
888 023 /* only do anything if a hasn't been freed previously */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
889 024 if (a->dp != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
890 025 /* first zero the digits */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
891 026 for (i = 0; i < a->used; i++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
892 027 a->dp[i] = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
893 028 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
894 029
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
895 030 /* free ram */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
896 031 XFREE(a->dp);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
897 032
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
898 033 /* reset members to make debugging easier */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
899 034 a->dp = NULL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
900 035 a->alloc = a->used = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
901 036 a->sign = MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
902 037 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
903 038 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
904 039 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
905 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
906 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
907
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
908 The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line 24)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
909 checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
910 \textbf{NULL} in which case the if statement will evaluate to true.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
911
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
912 The digits of the mp\_int are cleared by the for loop (line 26) which assigns a zero to every digit. Similar to mp\_init()
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
913 the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
914
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
915 The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
916 a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
917 still has to be reset to \textbf{NULL} manually (line 34).
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
918
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
919 Now that the digits have been cleared and deallocated the other members are set to their final values (lines 35 and 36).
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
920
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
921 \section{Maintenance Algorithms}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
922
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
923 The previous sections describes how to initialize and clear an mp\_int structure. To further support operations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
924 that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
925 able to augment the precision of an mp\_int and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
926 initialize mp\_ints with differing initial conditions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
927
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
928 These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
929 algorithms such as addition, multiplication and modular exponentiation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
930
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
931 \subsection{Augmenting an mp\_int's Precision}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
932 When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
933 result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
934 is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
935 must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
936
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
937 \newpage\begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
938 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
939 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
940 \hline Algorithm \textbf{mp\_grow}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
941 \textbf{Input}. An mp\_int $a$ and an integer $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
942 \textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
943 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
944 1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
945 2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
946 3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
947 4. Re-allocate the array of digits $a$ to size $v$ \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
948 5. If the allocation failed then return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
949 6. for n from a.alloc to $v - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
950 \hspace{+3mm}6.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
951 7. $a.alloc \leftarrow v$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
952 8. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
953 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
954 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
955 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
956 \caption{Algorithm mp\_grow}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
957 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
958
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
959 \textbf{Algorithm mp\_grow.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
960 It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
961 prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
962
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
963 The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
964 This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
965
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
966 It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
967 akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
968 assumed to contain undefined values they are initially set to zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
969
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
970 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
971 \hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
972 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
973 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
974 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
975 017 /* grow as required */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
976 018 int mp_grow (mp_int * a, int size)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
977 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
978 020 int i;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
979 021 mp_digit *tmp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
980 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
981 023 /* if the alloc size is smaller alloc more ram */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
982 024 if (a->alloc < size) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
983 025 /* ensure there are always at least MP_PREC digits extra on top */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
984 026 size += (MP_PREC * 2) - (size % MP_PREC);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
985 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
986 028 /* reallocate the array a->dp
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
987 029 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
988 030 * We store the return in a temporary variable
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
989 031 * in case the operation failed we don't want
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
990 032 * to overwrite the dp member of a.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
991 033 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
992 034 tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
993 035 if (tmp == NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
994 036 /* reallocation failed but "a" is still valid [can be freed] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
995 037 return MP_MEM;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
996 038 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
997 039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
998 040 /* reallocation succeeded so set a->dp */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
999 041 a->dp = tmp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1000 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1001 043 /* zero excess digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1002 044 i = a->alloc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1003 045 a->alloc = size;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1004 046 for (; i < a->alloc; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1005 047 a->dp[i] = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1006 048 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1007 049 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1008 050 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1009 051 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1010 052 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1011 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1012 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1013
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1014 A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line 24) checks
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1015 if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1016 the function skips the re-allocation part thus saving time.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1017
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1018 When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1019 padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 26). The XREALLOC function is used
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1020 to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1021 function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1022 the re-allocation. All that is left is to clear the newly allocated digits and return.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1023
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1024 Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1025 an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1026 result in a memory leak if XREALLOC ever failed.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1028 \subsection{Initializing Variable Precision mp\_ints}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1029 Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1030 of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1031 will allocate \textit{at least} a specified number of digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1033 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1034 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1035 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1036 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1037 \hline Algorithm \textbf{mp\_init\_size}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1038 \textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1039 \textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1040 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1041 1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1042 2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1043 3. Allocate $v$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1044 4. for $n$ from $0$ to $v - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1045 \hspace{3mm}4.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1046 5. $a.sign \leftarrow MP\_ZPOS$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1047 6. $a.used \leftarrow 0$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1048 7. $a.alloc \leftarrow v$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1049 8. Return(\textit{MP\_OKAY})\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1050 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1051 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1052 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1053 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1054 \caption{Algorithm mp\_init\_size}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1055 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1057 \textbf{Algorithm mp\_init\_size.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1058 This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1059 digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1060 multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1061 allocations from becoming a bottleneck in the rest of the algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1062
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1063 Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1064 particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1065 correct no further memory re-allocations are required to work with the mp\_int.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1066
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1067 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1068 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1069 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1070 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1071 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1072 017 /* init an mp_init for a given size */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1073 018 int mp_init_size (mp_int * a, int size)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1074 019 \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1075 020 int x;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1076 021
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1077 022 /* pad size so there are always extra digits */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1078 023 size += (MP_PREC * 2) - (size % MP_PREC);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1079 024
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1080 025 /* alloc mem */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1081 026 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1082 027 if (a->dp == NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1083 028 return MP_MEM;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1084 029 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1085 030
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1086 031 /* set the members */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1087 032 a->used = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1088 033 a->alloc = size;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1089 034 a->sign = MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1090 035
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1091 036 /* zero the digits */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1092 037 for (x = 0; x < size; x++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1093 038 a->dp[x] = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1094 039 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1095 040
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1096 041 return MP_OKAY;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1097 042 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1098 043 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1099 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1100 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1101
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1102 The number of digits $b$ requested is padded (line 23) by first augmenting it to the next multiple of
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1103 \textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1104 mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1105 returned (line 28).
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1106
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1107 The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1108 \textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1109 to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 32, 33 and 34). If the function
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1110 returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1111 functions to work with.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1112
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1113 \subsection{Multiple Integer Initializations and Clearings}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1114 Occasionally a function will require a series of mp\_int data types to be made available simultaneously.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1115 The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1116 statement. It is essentially a shortcut to multiple initializations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1117
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1118 \newpage\begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1119 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1120 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1121 \hline Algorithm \textbf{mp\_init\_multi}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1122 \textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1123 \textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1124 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1125 1. for $n$ from 0 to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1126 \hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1127 \hspace{+3mm}1.2. If initialization failed then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1128 \hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1129 \hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1130 \hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1131 2. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1132 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1133 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1134 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1135 \caption{Algorithm mp\_init\_multi}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1136 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1137
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1138 \textbf{Algorithm mp\_init\_multi.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1139 The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1140 (\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1141 initialization which allows for quick recovery from runtime errors.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1142
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1143 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1144 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1145 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1146 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1147 016 #include <stdarg.h>
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1148 017
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1149 018 int mp_init_multi(mp_int *mp, ...)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1150 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1151 020 mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1152 021 int n = 0; /* Number of ok inits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1153 022 mp_int* cur_arg = mp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1154 023 va_list args;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1155 024
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1156 025 va_start(args, mp); /* init args to next argument from caller */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1157 026 while (cur_arg != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1158 027 if (mp_init(cur_arg) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1159 028 /* Oops - error! Back-track and mp_clear what we already
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1160 029 succeeded in init-ing, then return error.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1161 030 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1162 031 va_list clean_args;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1163 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1164 033 /* end the current list */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1165 034 va_end(args);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1166 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1167 036 /* now start cleaning up */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1168 037 cur_arg = mp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1169 038 va_start(clean_args, mp);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1170 039 while (n--) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1171 040 mp_clear(cur_arg);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1172 041 cur_arg = va_arg(clean_args, mp_int*);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1173 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1174 043 va_end(clean_args);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1175 044 res = MP_MEM;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1176 045 break;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1177 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1178 047 n++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1179 048 cur_arg = va_arg(args, mp_int*);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1180 049 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1181 050 va_end(args);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1182 051 return res; /* Assumed ok, if error flagged above. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1183 052 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1184 053
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1185 054 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1186 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1187 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1188
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1189 This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1190 structures in an actual C array they are simply passed as arguments to the function. This function makes use of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1191 ``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1192 appended on the right.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1193
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1194 The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1195 $n$ of succesfully initialized mp\_int structures is maintained (line 47) such that if a failure does occur,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1196 the algorithm can backtrack and free the previously initialized structures (lines 27 to 46).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1197
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1198
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1199 \subsection{Clamping Excess Digits}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1200 When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1201 the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1202 $j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1203 though, with no final carry into the last position. However, suppose the destination had to be first expanded
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1204 (\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1205 That would be a considerable waste of time since heap operations are relatively slow.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1206
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1207 The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1208 terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1209 there would be an excess high order zero digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1210
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1211 For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1212 will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1213 accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1214 low the representation is excessively large.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1215
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1216 The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1217 \textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1218 positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1219 \textbf{MP\_ZPOS}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1220
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1221 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1222 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1223 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1224 \hline Algorithm \textbf{mp\_clamp}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1225 \textbf{Input}. An mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1226 \textbf{Output}. Any excess leading zero digits of $a$ are removed \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1227 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1228 1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1229 \hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1230 2. if $a.used = 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1231 \hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1232 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1233 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1234 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1235 \caption{Algorithm mp\_clamp}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1236 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1237
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1238 \textbf{Algorithm mp\_clamp.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1239 As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1240 the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1241 when all of the digits are zero to ensure that the mp\_int is valid at all times.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1242
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1243 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1244 \hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1245 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1246 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1247 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1248 017 /* trim unused digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1249 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1250 019 * This is used to ensure that leading zero digits are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1251 020 * trimed and the leading "used" digit will be non-zero
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1252 021 * Typically very fast. Also fixes the sign if there
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1253 022 * are no more leading digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1254 023 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1255 024 void
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1256 025 mp_clamp (mp_int * a)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1257 026 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1258 027 /* decrease used while the most significant digit is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1259 028 * zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1260 029 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1261 030 while (a->used > 0 && a->dp[a->used - 1] == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1262 031 --(a->used);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1263 032 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1264 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1265 034 /* reset the sign flag if used == 0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1266 035 if (a->used == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1267 036 a->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1268 037 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1269 038 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1270 039 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1271 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1272 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1273
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1274 Note on line 27 how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1275 language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1276 important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1277 undesirable. The parenthesis on line 30 is used to make sure the \textbf{used} count is decremented and not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1278 the pointer ``a''.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1279
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1280 \section*{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1281 \begin{tabular}{cl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1282 $\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1283 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1284 $\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1285 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1286 $\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1287 & encryption when $\beta = 2^{28}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1288 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1289 $\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1290 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1291 $\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1292 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1293 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1294
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1295
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1296 %%%
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1297 % CHAPTER FOUR
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1298 %%%
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1299
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1300 \chapter{Basic Operations}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1301
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1302 \section{Introduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1303 In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1304 mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1305 level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1306 work before proceeding since these algorithms will be used almost intrinsically in the following chapters.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1307
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1308 The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1309 mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1310 represent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1311
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1312 \section{Assigning Values to mp\_int Structures}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1313 \subsection{Copying an mp\_int}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1314 Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1315 a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1316 value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1317
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1318 \newpage\begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1319 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1320 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1321 \hline Algorithm \textbf{mp\_copy}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1322 \textbf{Input}. An mp\_int $a$ and $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1323 \textbf{Output}. Store a copy of $a$ in $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1324 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1325 1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1326 2. for $n$ from 0 to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1327 \hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1328 3. for $n$ from $a.used$ to $b.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1329 \hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1330 4. $b.used \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1331 5. $b.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1332 6. return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1333 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1334 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1335 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1336 \caption{Algorithm mp\_copy}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1337 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1338
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1339 \textbf{Algorithm mp\_copy.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1340 This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1341 represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1342 mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1343
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1344 If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1345 algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1346 and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1347 $b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1348
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1349 \textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1350 text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1351 step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1352 limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1353 the error code itself. However, the C code presented will demonstrate all of the error handling logic required to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1354 implement the pseudo-code.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1355
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1356 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1357 \hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1358 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1359 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1360 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1361 017 /* copy, b = a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1362 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1363 019 mp_copy (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1364 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1365 021 int res, n;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1366 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1367 023 /* if dst == src do nothing */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1368 024 if (a == b) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1369 025 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1370 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1371 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1372 028 /* grow dest */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1373 029 if (b->alloc < a->used) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1374 030 if ((res = mp_grow (b, a->used)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1375 031 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1376 032 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1377 033 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1378 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1379 035 /* zero b and copy the parameters over */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1380 036 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1381 037 register mp_digit *tmpa, *tmpb;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1382 038
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1383 039 /* pointer aliases */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1384 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1385 041 /* source */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1386 042 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1387 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1388 044 /* destination */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1389 045 tmpb = b->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1390 046
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1391 047 /* copy all the digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1392 048 for (n = 0; n < a->used; n++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1393 049 *tmpb++ = *tmpa++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1394 050 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1395 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1396 052 /* clear high digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1397 053 for (; n < b->used; n++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1398 054 *tmpb++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1399 055 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1400 056 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1401 057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1402 058 /* copy used count and sign */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1403 059 b->used = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1404 060 b->sign = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1405 061 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1406 062 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1407 063 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1408 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1409 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1410
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1411 Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1412 mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1413 copying digits (line 24).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1414
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1415 The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1416 $a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 29 to 33). In order to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1417 simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1418 of the mp\_ints $a$ and $b$ respectively. These aliases (lines 42 and 45) allow the compiler to access the digits without first dereferencing the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1419 mp\_int pointers and then subsequently the pointer to the digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1420
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1421 After the aliases are established the digits from $a$ are copied into $b$ (lines 48 to 50) and then the excess
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1422 digits of $b$ are set to zero (lines 53 to 55). Both ``for'' loops make use of the pointer aliases and in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1423 fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1424 allows the alias to stay in a machine register fairly easy between the two loops.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1425
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1426 \textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1427 be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1428 number of pointer dereferencing operations required to access data. For example, a for loop may resemble
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1429
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1430 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1431 for (x = 0; x < 100; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1432 a->num[4]->dp[x] = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1433 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1434 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1435
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1436 This could be re-written using aliases as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1437
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1438 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1439 mp_digit *tmpa;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1440 a = a->num[4]->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1441 for (x = 0; x < 100; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1442 *a++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1443 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1444 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1445
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1446 In this case an alias is used to access the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1447 array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1448 as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1449
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1450 The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1451 may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1452 work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1453 aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1454 stands a better chance of being faster.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1455
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1456 The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1457 loop of the function mp\_copy() re-written to not use pointer aliases.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1458
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1459 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1460 /* copy all the digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1461 for (n = 0; n < a->used; n++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1462 b->dp[n] = a->dp[n];
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1463 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1464 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1465
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1466 Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1467 complicated as there are four variables within the statement instead of just two.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1468
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1469 \subsubsection{Nested Statements}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1470 Another commonly used technique in the source routines is that certain sections of code are nested. This is used in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1471 particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1472 will typically have three different phases. First the temporaries are initialized, then the columns calculated and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1473 finally the carries are propagated. In this example the middle column production phase will typically be nested as it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1474 uses temporary variables and aliases the most.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1475
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1476 The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1477 the various temporary variables required do not propagate into other sections of code.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1478
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1479
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1480 \subsection{Creating a Clone}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1481 Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1482 and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1483 useful within functions that need to modify an argument but do not wish to actually modify the original copy. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1484 mp\_init\_copy algorithm has been designed to help perform this task.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1485
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1486 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1487 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1488 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1489 \hline Algorithm \textbf{mp\_init\_copy}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1490 \textbf{Input}. An mp\_int $a$ and $b$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1491 \textbf{Output}. $a$ is initialized to be a copy of $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1492 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1493 1. Init $a$. (\textit{mp\_init}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1494 2. Copy $b$ to $a$. (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1495 3. Return the status of the copy operation. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1496 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1497 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1498 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1499 \caption{Algorithm mp\_init\_copy}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1500 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1501
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1502 \textbf{Algorithm mp\_init\_copy.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1503 This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1504 such this algorithm will perform two operations in one step.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1505
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1506 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1507 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1508 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1509 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1510 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1511 017 /* creates "a" then copies b into it */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1512 018 int mp_init_copy (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1513 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1514 020 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1515 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1516 022 if ((res = mp_init (a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1517 023 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1518 024 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1519 025 return mp_copy (b, a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1520 026 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1521 027 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1522 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1523 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1524
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1525 This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1526 \textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1527 and \textbf{a} will be left intact.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1528
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1529 \section{Zeroing an Integer}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1530 Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1531 perform this task.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1532
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1533 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1534 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1535 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1536 \hline Algorithm \textbf{mp\_zero}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1537 \textbf{Input}. An mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1538 \textbf{Output}. Zero the contents of $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1539 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1540 1. $a.used \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1541 2. $a.sign \leftarrow$ MP\_ZPOS \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1542 3. for $n$ from 0 to $a.alloc - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1543 \hspace{3mm}3.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1544 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1545 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1546 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1547 \caption{Algorithm mp\_zero}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1548 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1549
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1550 \textbf{Algorithm mp\_zero.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1551 This algorithm simply resets a mp\_int to the default state.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1552
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1553 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1554 \hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1555 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1556 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1557 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1558 017 /* set to zero */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1559 018 void mp_zero (mp_int * a)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1560 019 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1561 020 int n;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1562 021 mp_digit *tmp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1563 022
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1564 023 a->sign = MP_ZPOS;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1565 024 a->used = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1566 025
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1567 026 tmp = a->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1568 027 for (n = 0; n < a->alloc; n++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1569 028 *tmp++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1570 029 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1571 030 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1572 031 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1573 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1574 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1575
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1576 After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1577 \textbf{sign} variable is set to \textbf{MP\_ZPOS}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1578
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1579 \section{Sign Manipulation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1580 \subsection{Absolute Value}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1581 With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1582 the absolute value of an mp\_int.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1583
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1584 \begin{figure}[here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1585 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1586 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1587 \hline Algorithm \textbf{mp\_abs}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1588 \textbf{Input}. An mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1589 \textbf{Output}. Computes $b = \vert a \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1590 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1591 1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1592 2. If the copy failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1593 3. $b.sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1594 4. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1595 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1596 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1597 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1598 \caption{Algorithm mp\_abs}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1599 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1600
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1601 \textbf{Algorithm mp\_abs.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1602 This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1603 algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1604 for instance, the developer to pass the same mp\_int as the source and destination to this function without addition
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1605 logic to handle it.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1606
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1607 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1608 \hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1609 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1610 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1611 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1612 017 /* b = |a|
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1613 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1614 019 * Simple function copies the input and fixes the sign to positive
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1615 020 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1616 021 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1617 022 mp_abs (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1618 023 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1619 024 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1620 025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1621 026 /* copy a to b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1622 027 if (a != b) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1623 028 if ((res = mp_copy (a, b)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1624 029 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1625 030 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1626 031 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1627 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1628 033 /* force the sign of b to positive */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1629 034 b->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1630 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1631 036 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1632 037 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1633 038 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1634 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1635 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1636
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1637 This fairly trivial algorithm first eliminates non--required duplications (line 27) and then sets the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1638 \textbf{sign} flag to \textbf{MP\_ZPOS}.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1639
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1640 \subsection{Integer Negation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1641 With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1642 the negative of an mp\_int input.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1643
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1644 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1645 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1646 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1647 \hline Algorithm \textbf{mp\_neg}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1648 \textbf{Input}. An mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1649 \textbf{Output}. Computes $b = -a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1650 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1651 1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1652 2. If the copy failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1653 3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1654 4. If $a.sign = MP\_ZPOS$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1655 \hspace{3mm}4.1 $b.sign = MP\_NEG$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1656 5. else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1657 \hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1658 6. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1659 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1660 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1661 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1662 \caption{Algorithm mp\_neg}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1663 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1664
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1665 \textbf{Algorithm mp\_neg.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1666 This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1667 the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1668 $a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1669 zero as negative.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1670
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1671 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1672 \hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1673 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1674 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1675 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1676 017 /* b = -a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1677 018 int mp_neg (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1678 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1679 020 int res;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1680 021 if (a != b) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1681 022 if ((res = mp_copy (a, b)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1682 023 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1683 024 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1684 025 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1685 026
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1686 027 if (mp_iszero(b) != MP_YES) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1687 028 b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1688 029 \} else \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1689 030 b->sign = MP_ZPOS;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1690 031 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1691 032
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1692 033 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1693 034 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1694 035 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1695 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1696 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1697
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1698 Like mp\_abs() this function avoids non--required duplications (line 21) and then sets the sign. We
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1699 have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1700 than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1701
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1702 \section{Small Constants}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1703 \subsection{Setting Small Constants}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1704 Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1705
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1706 \newpage\begin{figure}[here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1707 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1708 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1709 \hline Algorithm \textbf{mp\_set}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1710 \textbf{Input}. An mp\_int $a$ and a digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1711 \textbf{Output}. Make $a$ equivalent to $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1712 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1713 1. Zero $a$ (\textit{mp\_zero}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1714 2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1715 3. $a.used \leftarrow \left \lbrace \begin{array}{ll}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1716 1 & \mbox{if }a_0 > 0 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1717 0 & \mbox{if }a_0 = 0
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1718 \end{array} \right .$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1719 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1720 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1721 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1722 \caption{Algorithm mp\_set}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1723 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1724
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1725 \textbf{Algorithm mp\_set.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1726 This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1727 single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1728
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1729 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1730 \hspace{-5.1mm}{\bf File}: bn\_mp\_set.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1731 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1732 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1733 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1734 017 /* set to a digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1735 018 void mp_set (mp_int * a, mp_digit b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1736 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1737 020 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1738 021 a->dp[0] = b & MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1739 022 a->used = (a->dp[0] != 0) ? 1 : 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1740 023 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1741 024 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1742 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1743 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1744
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1745 First we zero (line 20) the mp\_int to make sure that the other members are initialized for a
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1746 small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1747 is zero. Next we set the digit and reduce it modulo $\beta$ (line 21). After this step we have to
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1748 check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1749 to zero.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1750
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1751 We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1752 $2^k - 1$ will perform the same operation.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1753
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1754 One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1755 this function should take that into account. Only trivially small constants can be set using this function.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1756
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1757 \subsection{Setting Large Constants}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1758 To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1759 data type as input and will always treat it as a 32-bit integer.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1760
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1761 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1762 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1763 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1764 \hline Algorithm \textbf{mp\_set\_int}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1765 \textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1766 \textbf{Output}. Make $a$ equivalent to $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1767 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1768 1. Zero $a$ (\textit{mp\_zero}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1769 2. for $n$ from 0 to 7 do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1770 \hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1771 \hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1772 \hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1773 \hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1774 3. Clamp excess used digits (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1775 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1776 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1777 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1778 \caption{Algorithm mp\_set\_int}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1779 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1780
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1781 \textbf{Algorithm mp\_set\_int.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1782 The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1783 mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1784 next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1785 incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1786 zero digits used and the newly added four bits would be ignored.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1787
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1788 Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1789
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1790 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1791 \hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1792 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1793 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1794 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1795 017 /* set a 32-bit const */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1796 018 int mp_set_int (mp_int * a, unsigned long b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1797 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1798 020 int x, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1799 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1800 022 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1801 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1802 024 /* set four bits at a time */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1803 025 for (x = 0; x < 8; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1804 026 /* shift the number up four bits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1805 027 if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1806 028 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1807 029 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1808 030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1809 031 /* OR in the top four bits of the source */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1810 032 a->dp[0] |= (b >> 28) & 15;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1811 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1812 034 /* shift the source up to the next four bits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1813 035 b <<= 4;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1814 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1815 037 /* ensure that digits are not clamped off */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1816 038 a->used += 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1817 039 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1818 040 mp_clamp (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1819 041 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1820 042 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1821 043 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1822 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1823 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1824
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1825 This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1826 addition on line 38 ensures that the newly added in bits are added to the number of digits. While it may not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1827 seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 27
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1828 as well as the call to mp\_clamp() on line 40. Both functions will clamp excess leading digits which keeps
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1829 the number of used digits low.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1830
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1831 \section{Comparisons}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1832 \subsection{Unsigned Comparisions}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1833 Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1834 to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1835 to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1836 positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1837
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1838 The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1839 mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1840 signs are known to agree in advance.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1841
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1842 To facilitate working with the results of the comparison functions three constants are required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1843
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1844 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1845 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1846 \begin{tabular}{|r|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1847 \hline \textbf{Constant} & \textbf{Meaning} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1848 \hline \textbf{MP\_GT} & Greater Than \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1849 \hline \textbf{MP\_EQ} & Equal To \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1850 \hline \textbf{MP\_LT} & Less Than \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1851 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1852 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1853 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1854 \caption{Comparison Return Codes}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1855 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1856
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1857 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1858 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1859 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1860 \hline Algorithm \textbf{mp\_cmp\_mag}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1861 \textbf{Input}. Two mp\_ints $a$ and $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1862 \textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1863 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1864 1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1865 2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1866 3. for n from $a.used - 1$ to 0 do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1867 \hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1868 \hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1869 4. Return(\textit{MP\_EQ}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1870 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1871 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1872 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1873 \caption{Algorithm mp\_cmp\_mag}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1874 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1875
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1876 \textbf{Algorithm mp\_cmp\_mag.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1877 By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1878 \textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1879 Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1880 If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1881
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1882 By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1883 the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1884
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1885 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1886 \hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1887 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1888 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1889 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1890 017 /* compare maginitude of two ints (unsigned) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1891 018 int mp_cmp_mag (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1892 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1893 020 int n;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1894 021 mp_digit *tmpa, *tmpb;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1895 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1896 023 /* compare based on # of non-zero digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1897 024 if (a->used > b->used) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1898 025 return MP_GT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1899 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1900 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1901 028 if (a->used < b->used) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1902 029 return MP_LT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1903 030 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1904 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1905 032 /* alias for a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1906 033 tmpa = a->dp + (a->used - 1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1907 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1908 035 /* alias for b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1909 036 tmpb = b->dp + (a->used - 1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1910 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1911 038 /* compare based on digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1912 039 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1913 040 if (*tmpa > *tmpb) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1914 041 return MP_GT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1915 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1916 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1917 044 if (*tmpa < *tmpb) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1918 045 return MP_LT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1919 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1920 047 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1921 048 return MP_EQ;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1922 049 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1923 050 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1924 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1925 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1926
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1927 The two if statements (lines 24 and 28) compare the number of digits in the two inputs. These two are
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1928 performed before all of the digits are compared since it is a very cheap test to perform and can potentially save
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1929 considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1930 smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1931
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1932
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1933
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1934 \subsection{Signed Comparisons}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1935 Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1936 comparison a trivial signed comparison algorithm can be written.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1937
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1938 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1939 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1940 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1941 \hline Algorithm \textbf{mp\_cmp}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1942 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1943 \textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1944 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1945 1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1946 2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1947 3. if $a.sign = MP\_NEG$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1948 \hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1949 4 Otherwise \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1950 \hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1951 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1952 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1953 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1954 \caption{Algorithm mp\_cmp}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1955 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1956
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1957 \textbf{Algorithm mp\_cmp.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1958 The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1959 comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1960 three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1961 $\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1962
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1963 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1964 \hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1965 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1966 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1967 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1968 017 /* compare two ints (signed)*/
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1969 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1970 019 mp_cmp (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1971 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1972 021 /* compare based on sign */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1973 022 if (a->sign != b->sign) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1974 023 if (a->sign == MP_NEG) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1975 024 return MP_LT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1976 025 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1977 026 return MP_GT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1978 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1979 028 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1980 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1981 030 /* compare digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1982 031 if (a->sign == MP_NEG) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1983 032 /* if negative compare opposite direction */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1984 033 return mp_cmp_mag(b, a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1985 034 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1986 035 return mp_cmp_mag(a, b);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1987 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1988 037 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
1989 038 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1990 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1991 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1992
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1993 The two if statements (lines 22 and 23) perform the initial sign comparison. If the signs are not the equal then which ever
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1994 has the positive sign is larger. The inputs are compared (line 31) based on magnitudes. If the signs were both
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
1995 negative then the unsigned comparison is performed in the opposite direction (line 33). Otherwise, the signs are assumed to
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1996 be both positive and a forward direction unsigned comparison is performed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1997
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1998 \section*{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1999 \begin{tabular}{cl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2000 $\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2001 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2002 $\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2003 & of two random digits (of equal magnitude) before a difference is found. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2004 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2005 $\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2006 & on the observations made in the previous problem. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2007 &
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2008 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2009
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2010 \chapter{Basic Arithmetic}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2011 \section{Introduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2012 At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2013 established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2014 algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2015 that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2016 which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2017
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2018 All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2019 logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2020 number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2021 Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2022 For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2024 One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2025 from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2026 result is $110_2$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2028 \section{Addition and Subtraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2029 In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2030 $a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2031 As a result subtraction can be performed with a trivial series of logical operations and an addition.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2033 However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2034 sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2035 subtraction algorithms with the sign fixed up appropriately.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2037 The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2038 the integers respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2040 \subsection{Low Level Addition}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2041 An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2042 trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2043 Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2045 \newpage
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2046 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2047 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2048 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2049 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2050 \hline Algorithm \textbf{s\_mp\_add}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2051 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2052 \textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2053 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2054 1. if $a.used > b.used$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2055 \hspace{+3mm}1.1 $min \leftarrow b.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2056 \hspace{+3mm}1.2 $max \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2057 \hspace{+3mm}1.3 $x \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2058 2. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2059 \hspace{+3mm}2.1 $min \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2060 \hspace{+3mm}2.2 $max \leftarrow b.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2061 \hspace{+3mm}2.3 $x \leftarrow b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2062 3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2063 4. $oldused \leftarrow c.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2064 5. $c.used \leftarrow max + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2065 6. $u \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2066 7. for $n$ from $0$ to $min - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2067 \hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2068 \hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2069 \hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2070 8. if $min \ne max$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2071 \hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2072 \hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2073 \hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2074 \hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2075 9. $c_{max} \leftarrow u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2076 10. if $olduse > max$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2077 \hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2078 \hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2079 11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2080 12. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2081 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2082 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2083 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2084 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2085 \caption{Algorithm s\_mp\_add}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2086 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2087
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2088 \textbf{Algorithm s\_mp\_add.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2089 This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2090 Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2091 MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2092
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2093 The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2094 will simply add all of the smallest input to the largest input and store that first part of the result in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2095 destination. Then it will apply a simpler addition loop to excess digits of the larger input.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2096
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2097 The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2098 inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2099 same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2100 of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2101
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2102 At this point the first addition loop will go through as many digit positions that both inputs have. The carry
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2103 variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2104 one digit of the summand. First
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2105 two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2106 in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2107
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2108 Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2109 for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2110 and the carry to the destination.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2111
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2112 The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2113
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2114
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2115 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2116 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2117 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2118 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2119 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2120 017 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2121 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2122 019 s_mp_add (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2123 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2124 021 mp_int *x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2125 022 int olduse, res, min, max;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2126 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2127 024 /* find sizes, we let |a| <= |b| which means we have to sort
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2128 025 * them. "x" will point to the input with the most digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2129 026 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2130 027 if (a->used > b->used) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2131 028 min = b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2132 029 max = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2133 030 x = a;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2134 031 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2135 032 min = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2136 033 max = b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2137 034 x = b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2138 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2139 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2140 037 /* init result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2141 038 if (c->alloc < max + 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2142 039 if ((res = mp_grow (c, max + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2143 040 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2144 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2145 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2146 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2147 044 /* get old used digit count and set new one */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2148 045 olduse = c->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2149 046 c->used = max + 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2150 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2151 048 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2152 049 register mp_digit u, *tmpa, *tmpb, *tmpc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2153 050 register int i;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2154 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2155 052 /* alias for digit pointers */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2156 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2157 054 /* first input */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2158 055 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2159 056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2160 057 /* second input */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2161 058 tmpb = b->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2162 059
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2163 060 /* destination */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2164 061 tmpc = c->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2165 062
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2166 063 /* zero the carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2167 064 u = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2168 065 for (i = 0; i < min; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2169 066 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2170 067 *tmpc = *tmpa++ + *tmpb++ + u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2171 068
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2172 069 /* U = carry bit of T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2173 070 u = *tmpc >> ((mp_digit)DIGIT_BIT);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2174 071
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2175 072 /* take away carry bit from T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2176 073 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2177 074 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2178 075
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2179 076 /* now copy higher words if any, that is in A+B
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2180 077 * if A or B has more digits add those in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2181 078 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2182 079 if (min != max) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2183 080 for (; i < max; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2184 081 /* T[i] = X[i] + U */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2185 082 *tmpc = x->dp[i] + u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2186 083
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2187 084 /* U = carry bit of T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2188 085 u = *tmpc >> ((mp_digit)DIGIT_BIT);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2189 086
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2190 087 /* take away carry bit from T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2191 088 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2192 089 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2193 090 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2194 091
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2195 092 /* add carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2196 093 *tmpc++ = u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2197 094
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2198 095 /* clear digits above oldused */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2199 096 for (i = c->used; i < olduse; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2200 097 *tmpc++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2201 098 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2202 099 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2203 100
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2204 101 mp_clamp (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2205 102 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2206 103 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2207 104 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2208 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2209 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2210
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2211 We first sort (lines 27 to 35) the inputs based on magnitude and determine the $min$ and $max$ variables.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2212 Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2213 grow the destination (37 to 42) ensure that it can accomodate the result of the addition.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2214
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2215 Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2216 lines 55, 58 and 61 represent the two inputs and destination variables respectively. These aliases are used to ensure the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2217 compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2218
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2219 The initial carry $u$ will be cleared (line 64), note that $u$ is of type mp\_digit which ensures type
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2220 compatibility within the implementation. The initial addition (line 65 to 74) adds digits from
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2221 both inputs until the smallest input runs out of digits. Similarly the conditional addition loop
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2222 (line 80 to 90) adds the remaining digits from the larger of the two inputs. The addition is finished
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2223 with the final carry being stored in $tmpc$ (line 93). Note the ``++'' operator within the same expression.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2224 After line 93, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2225 for the next loop (line 96 to 99) which set any old upper digits to zero.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2226
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2227 \subsection{Low Level Subtraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2228 The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2229 unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2230 be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2231 This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2232
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2233
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2234 For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2235 the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2236 this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2237 mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2238
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2239 For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long''
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2240 data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2241
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2242 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2243 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2244 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2245 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2246 \hline Algorithm \textbf{s\_mp\_sub}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2247 \textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2248 \textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2249 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2250 1. $min \leftarrow b.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2251 2. $max \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2252 3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2253 4. $oldused \leftarrow c.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2254 5. $c.used \leftarrow max$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2255 6. $u \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2256 7. for $n$ from $0$ to $min - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2257 \hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2258 \hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2259 \hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2260 8. if $min < max$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2261 \hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2262 \hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2263 \hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2264 \hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2265 9. if $oldused > max$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2266 \hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2267 \hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2268 10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2269 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2270 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2271 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2272 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2273 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2274 \caption{Algorithm s\_mp\_sub}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2275 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2276
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2277 \textbf{Algorithm s\_mp\_sub.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2278 This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2279 passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2280 algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2281 of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2282
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2283 The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2284 set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2285 most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2286 set to the maximal count for the operation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2287
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2288 The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2289 subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2290 loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2291
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2292 For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2293 the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2294 third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2295 way to the most significant bit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2296
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2297 Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2298 significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2299 is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2300 carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2301
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2302 If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2303 10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2304
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2305 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2306 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2307 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2308 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2309 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2310 017 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2311 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2312 019 s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2313 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2314 021 int olduse, res, min, max;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2315 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2316 023 /* find sizes */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2317 024 min = b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2318 025 max = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2319 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2320 027 /* init result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2321 028 if (c->alloc < max) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2322 029 if ((res = mp_grow (c, max)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2323 030 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2324 031 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2325 032 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2326 033 olduse = c->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2327 034 c->used = max;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2328 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2329 036 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2330 037 register mp_digit u, *tmpa, *tmpb, *tmpc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2331 038 register int i;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2332 039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2333 040 /* alias for digit pointers */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2334 041 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2335 042 tmpb = b->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2336 043 tmpc = c->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2337 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2338 045 /* set carry to zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2339 046 u = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2340 047 for (i = 0; i < min; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2341 048 /* T[i] = A[i] - B[i] - U */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2342 049 *tmpc = *tmpa++ - *tmpb++ - u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2343 050
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2344 051 /* U = carry bit of T[i]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2345 052 * Note this saves performing an AND operation since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2346 053 * if a carry does occur it will propagate all the way to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2347 054 * MSB. As a result a single shift is enough to get the carry
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2348 055 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2349 056 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2350 057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2351 058 /* Clear carry from T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2352 059 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2353 060 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2354 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2355 062 /* now copy higher words if any, e.g. if A has more digits than B */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2356 063 for (; i < max; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2357 064 /* T[i] = A[i] - U */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2358 065 *tmpc = *tmpa++ - u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2359 066
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2360 067 /* U = carry bit of T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2361 068 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2362 069
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2363 070 /* Clear carry from T[i] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2364 071 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2365 072 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2366 073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2367 074 /* clear digits above used (since we may not have grown result above) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2368
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2369 075 for (i = c->used; i < olduse; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2370 076 *tmpc++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2371 077 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2372 078 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2373 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2374 080 mp_clamp (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2375 081 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2376 082 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2377 083
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2378 084 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2379 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2380 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2381
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2382 Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2383 (lines 24 and 25). In reality the $min$ and $max$ variables are only aliases and are only
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2384 used to make the source code easier to read. Again the pointer alias optimization is used
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2385 within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2386 (lines 41, 42 and 43) for $a$, $b$ and $c$ respectively.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2387
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2388 The first subtraction loop (lines 46 through 60) subtract digits from both inputs until the smaller of
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2389 the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward''
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2390 method of extracting the carry (line 56). The traditional method for extracting the carry would be to shift
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2391 by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2392 the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2393 extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2394 most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2395 optimization only works on twos compliment machines which is a safe assumption to make.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2396
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2397 If $a$ has a larger magnitude than $b$ an additional loop (lines 63 through 72) is required to propagate
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2398 the carry through $a$ and copy the result to $c$.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2399
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2400 \subsection{High Level Addition}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2401 Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2402 established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2403 types.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2404
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2405 Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2406 flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2407
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2408 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2409 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2410 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2411 \hline Algorithm \textbf{mp\_add}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2412 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2413 \textbf{Output}. The signed addition $c = a + b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2414 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2415 1. if $a.sign = b.sign$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2416 \hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2417 \hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2418 2. else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2419 \hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2420 \hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2421 \hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2422 \hspace{3mm}2.2 else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2423 \hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2424 \hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2425 3. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2426 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2427 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2428 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2429 \caption{Algorithm mp\_add}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2430 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2431
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2432 \textbf{Algorithm mp\_add.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2433 This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2434 either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2435 straightforward but restricted since subtraction can only produce positive results.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2436
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2437 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2438 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2439 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2440 \begin{tabular}{|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2441 \hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2442 \hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2443 \hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2444 \hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2445 \hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2446 \hline &&&&\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2447
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2448 \hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2449 \hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2450
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2451 \hline &&&&\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2452
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2453 \hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2454 \hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2455
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2456 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2457 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2458 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2459 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2460 \caption{Addition Guide Chart}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2461 \label{fig:AddChart}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2462 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2463
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2464 Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2465 specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2466 forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2467 follows how the implementation actually was achieved.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2468
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2469 Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2470 s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2471 to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2472
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2473 For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2474 produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2475 within algorithm s\_mp\_add will force $-0$ to become $0$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2476
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2477 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2478 \hspace{-5.1mm}{\bf File}: bn\_mp\_add.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2479 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2480 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2481 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2482 017 /* high level addition (handles signs) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2483 018 int mp_add (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2484 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2485 020 int sa, sb, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2486 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2487 022 /* get sign of both inputs */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2488 023 sa = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2489 024 sb = b->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2490 025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2491 026 /* handle two cases, not four */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2492 027 if (sa == sb) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2493 028 /* both positive or both negative */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2494 029 /* add their magnitudes, copy the sign */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2495 030 c->sign = sa;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2496 031 res = s_mp_add (a, b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2497 032 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2498 033 /* one positive, the other negative */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2499 034 /* subtract the one with the greater magnitude from */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2500 035 /* the one of the lesser magnitude. The result gets */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2501 036 /* the sign of the one with the greater magnitude. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2502 037 if (mp_cmp_mag (a, b) == MP_LT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2503 038 c->sign = sb;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2504 039 res = s_mp_sub (b, a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2505 040 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2506 041 c->sign = sa;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2507 042 res = s_mp_sub (a, b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2508 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2509 044 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2510 045 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2511 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2512 047
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2513 048 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2514 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2515 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2516
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2517 The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2518 is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2519 explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2520 level functions do so. Returning their return code is sufficient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2521
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2522 \subsection{High Level Subtraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2523 The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2524
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2525 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2526 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2527 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2528 \hline Algorithm \textbf{mp\_sub}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2529 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2530 \textbf{Output}. The signed subtraction $c = a - b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2531 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2532 1. if $a.sign \ne b.sign$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2533 \hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2534 \hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2535 2. else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2536 \hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2537 \hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2538 \hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2539 \hspace{3mm}2.2 else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2540 \hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2541 MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2542 MP\_NEG & \mbox{otherwise} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2543 \end{array} \right .$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2544 \hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2545 3. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2546 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2547 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2548 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2549 \caption{Algorithm mp\_sub}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2550 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2551
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2552 \textbf{Algorithm mp\_sub.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2553 This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2554 \cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2555 the operations required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2556
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2557 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2558 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2559 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2560 \begin{tabular}{|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2561 \hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2562 \hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2563 \hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2564 \hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2565 \hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2566 \hline &&&& \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2567 \hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2568 \hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2569 \hline &&&& \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2570 \hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2571 \hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2572 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2573 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2574 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2575 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2576 \caption{Subtraction Guide Chart}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2577 \label{fig:SubChart}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2578 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2579
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2580 Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2581 algorithm from producing $-a - -a = -0$ as a result.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2582
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2583 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2584 \hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2585 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2586 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2587 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2588 017 /* high level subtraction (handles signs) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2589 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2590 019 mp_sub (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2591 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2592 021 int sa, sb, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2593 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2594 023 sa = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2595 024 sb = b->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2596 025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2597 026 if (sa != sb) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2598 027 /* subtract a negative from a positive, OR */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2599 028 /* subtract a positive from a negative. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2600 029 /* In either case, ADD their magnitudes, */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2601 030 /* and use the sign of the first number. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2602 031 c->sign = sa;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2603 032 res = s_mp_add (a, b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2604 033 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2605 034 /* subtract a positive from a positive, OR */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2606 035 /* subtract a negative from a negative. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2607 036 /* First, take the difference between their */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2608 037 /* magnitudes, then... */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2609 038 if (mp_cmp_mag (a, b) != MP_LT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2610 039 /* Copy the sign from the first */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2611 040 c->sign = sa;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2612 041 /* The first has a larger or equal magnitude */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2613 042 res = s_mp_sub (a, b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2614 043 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2615 044 /* The result has the *opposite* sign from */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2616 045 /* the first number. */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2617 046 c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2618 047 /* The second has a larger magnitude */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2619 048 res = s_mp_sub (b, a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2620 049 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2621 050 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2622 051 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2623 052 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2624 053
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2625 054 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2626 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2627 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2628
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2629 Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2630 and forward it to the end of the function. On line 38 the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2631 ``greater than or equal to'' comparison.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2632
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2633 \section{Bit and Digit Shifting}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2634 It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2635 This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2636
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2637 In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2638 the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2639 are on radix-$\beta$ digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2640
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2641 \subsection{Multiplication by Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2642
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2643 In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2644 operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2645
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2646 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2647 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2648 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2649 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2650 \hline Algorithm \textbf{mp\_mul\_2}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2651 \textbf{Input}. One mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2652 \textbf{Output}. $b = 2a$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2653 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2654 1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2655 2. $oldused \leftarrow b.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2656 3. $b.used \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2657 4. $r \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2658 5. for $n$ from 0 to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2659 \hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2660 \hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2661 \hspace{3mm}5.3 $r \leftarrow rr$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2662 6. If $r \ne 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2663 \hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2664 \hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2665 7. If $b.used < oldused - 1$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2666 \hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2667 \hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2668 8. $b.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2669 9. Return(\textit{MP\_OKAY}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2670 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2671 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2672 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2673 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2674 \caption{Algorithm mp\_mul\_2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2675 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2676
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2677 \textbf{Algorithm mp\_mul\_2.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2678 This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2679 an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2680 it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2681
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2682 Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2683 is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2684
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2685 Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2686 are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2687 obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2688 the previous carry. Recall from section 4.1 that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2689 forwarding the carry to the next iteration.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2690
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2691 Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2692 Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2693
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2694 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2695 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2696 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2697 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2698 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2699 017 /* b = a*2 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2700 018 int mp_mul_2(mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2701 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2702 020 int x, res, oldused;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2703 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2704 022 /* grow to accomodate result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2705 023 if (b->alloc < a->used + 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2706 024 if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2707 025 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2708 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2709 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2710 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2711 029 oldused = b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2712 030 b->used = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2713 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2714 032 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2715 033 register mp_digit r, rr, *tmpa, *tmpb;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2716 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2717 035 /* alias for source */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2718 036 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2719 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2720 038 /* alias for dest */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2721 039 tmpb = b->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2722 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2723 041 /* carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2724 042 r = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2725 043 for (x = 0; x < a->used; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2726 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2727 045 /* get what will be the *next* carry bit from the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2728 046 * MSB of the current digit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2729 047 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2730 048 rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2731 049
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2732 050 /* now shift up this digit, add in the carry [from the previous] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2733 051 *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2734 052
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2735 053 /* copy the carry that would be from the source
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2736 054 * digit into the next iteration
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2737 055 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2738 056 r = rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2739 057 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2740 058
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2741 059 /* new leading digit? */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2742 060 if (r != 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2743 061 /* add a MSB which is always 1 at this point */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2744 062 *tmpb = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2745 063 ++(b->used);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2746 064 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2747 065
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2748 066 /* now zero any excess digits on the destination
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2749 067 * that we didn't write to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2750 068 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2751 069 tmpb = b->dp + b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2752 070 for (x = b->used; x < oldused; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2753 071 *tmpb++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2754 072 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2755 073 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2756 074 b->sign = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2757 075 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2758 076 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2759 077 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2760 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2761 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2762
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2763 This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2764 is the use of the logical shift operator on line 51 to perform a single precision doubling.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2765
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2766 \subsection{Division by Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2767 A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2768
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2769 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2770 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2771 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2772 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2773 \hline Algorithm \textbf{mp\_div\_2}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2774 \textbf{Input}. One mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2775 \textbf{Output}. $b = a/2$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2776 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2777 1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2778 2. If the reallocation failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2779 3. $oldused \leftarrow b.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2780 4. $b.used \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2781 5. $r \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2782 6. for $n$ from $b.used - 1$ to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2783 \hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2784 \hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2785 \hspace{3mm}6.3 $r \leftarrow rr$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2786 7. If $b.used < oldused - 1$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2787 \hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2788 \hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2789 8. $b.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2790 9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2791 10. Return(\textit{MP\_OKAY}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2792 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2793 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2794 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2795 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2796 \caption{Algorithm mp\_div\_2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2797 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2798
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2799 \textbf{Algorithm mp\_div\_2.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2800 This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2801 core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2802 could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2803 reading past the end of the array of digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2804
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2805 Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2806 least significant bit not the most significant bit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2807
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2808 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2809 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2810 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2811 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2812 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2813 017 /* b = a/2 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2814 018 int mp_div_2(mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2815 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2816 020 int x, res, oldused;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2817 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2818 022 /* copy */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2819 023 if (b->alloc < a->used) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2820 024 if ((res = mp_grow (b, a->used)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2821 025 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2822 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2823 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2824 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2825 029 oldused = b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2826 030 b->used = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2827 031 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2828 032 register mp_digit r, rr, *tmpa, *tmpb;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2829 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2830 034 /* source alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2831 035 tmpa = a->dp + b->used - 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2832 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2833 037 /* dest alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2834 038 tmpb = b->dp + b->used - 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2835 039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2836 040 /* carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2837 041 r = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2838 042 for (x = b->used - 1; x >= 0; x--) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2839 043 /* get the carry for the next iteration */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2840 044 rr = *tmpa & 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2841 045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2842 046 /* shift the current digit, add in carry and store */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2843 047 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2844 048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2845 049 /* forward carry to next iteration */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2846 050 r = rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2847 051 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2848 052
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2849 053 /* zero excess digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2850 054 tmpb = b->dp + b->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2851 055 for (x = b->used; x < oldused; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2852 056 *tmpb++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2853 057 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2854 058 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2855 059 b->sign = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2856 060 mp_clamp (b);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2857 061 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2858 062 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2859 063 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2860 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2861 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2862
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2863 \section{Polynomial Basis Operations}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2864 Recall from section 4.3 that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2865 the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2866 place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2867 division and Karatsuba multiplication.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2868
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2869 Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2870 $y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2871 polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2872
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2873 \subsection{Multiplication by $x$}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2874
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2875 Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2876 degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2877 multiplying by the integer $\beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2878
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2879 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2880 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2881 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2882 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2883 \hline Algorithm \textbf{mp\_lshd}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2884 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2885 \textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2886 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2887 1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2888 2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2889 3. If the reallocation failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2890 4. $a.used \leftarrow a.used + b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2891 5. $i \leftarrow a.used - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2892 6. $j \leftarrow a.used - 1 - b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2893 7. for $n$ from $a.used - 1$ to $b$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2894 \hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2895 \hspace{3mm}7.2 $i \leftarrow i - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2896 \hspace{3mm}7.3 $j \leftarrow j - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2897 8. for $n$ from 0 to $b - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2898 \hspace{3mm}8.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2899 9. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2900 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2901 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2902 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2903 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2904 \caption{Algorithm mp\_lshd}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2905 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2906
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2907 \textbf{Algorithm mp\_lshd.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2908 This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2909 from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2910 motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2911 different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2912 typically used on values where the original value is no longer required. The algorithm will return success immediately if
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2913 $b \le 0$ since the rest of algorithm is only valid when $b > 0$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2914
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2915 First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2916 the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2917 The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2918 step 8 sets the lower $b$ digits to zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2919
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2920 \newpage
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2921 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2922 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2923 \includegraphics{pics/sliding_window.ps}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2924 \caption{Sliding Window Movement}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2925 \label{pic:sliding_window}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2926 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2927 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2928
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2929 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2930 \hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2931 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2932 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2933 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2934 017 /* shift left a certain amount of digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2935 018 int mp_lshd (mp_int * a, int b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2936 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2937 020 int x, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2938 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2939 022 /* if its less than zero return */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2940 023 if (b <= 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2941 024 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2942 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2943 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2944 027 /* grow to fit the new digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2945 028 if (a->alloc < a->used + b) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2946 029 if ((res = mp_grow (a, a->used + b)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2947 030 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2948 031 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2949 032 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2950 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2951 034 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2952 035 register mp_digit *top, *bottom;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2953 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2954 037 /* increment the used by the shift amount then copy upwards */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2955 038 a->used += b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2956 039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2957 040 /* top */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2958 041 top = a->dp + a->used - 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2959 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2960 043 /* base */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2961 044 bottom = a->dp + a->used - 1 - b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2962 045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2963 046 /* much like mp_rshd this is implemented using a sliding window
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2964 047 * except the window goes the otherway around. Copying from
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2965 048 * the bottom to the top. see bn_mp_rshd.c for more info.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2966 049 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2967 050 for (x = a->used - 1; x >= b; x--) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2968 051 *top-- = *bottom--;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2969 052 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2970 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2971 054 /* zero the lower digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2972 055 top = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2973 056 for (x = 0; x < b; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2974 057 *top++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2975 058 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2976 059 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2977 060 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2978 061 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
2979 062 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2980 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2981 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2982
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2983 The if statement (line 23) ensures that the $b$ variable is greater than zero since we do not interpret negative
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2984 shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2985 the need for an additional variable in the for loop. The variable $top$ (line 41) is an alias
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2986 for the leading digit while $bottom$ (line 44) is an alias for the trailing edge. The aliases form a
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
2987 window of exactly $b$ digits over the input.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2988
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2989 \subsection{Division by $x$}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2990
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2991 Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2992
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2993 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2994 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2995 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2996 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2997 \hline Algorithm \textbf{mp\_rshd}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2998 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2999 \textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3000 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3001 1. If $b \le 0$ then return. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3002 2. If $a.used \le b$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3003 \hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3004 \hspace{3mm}2.2 Return. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3005 3. $i \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3006 4. $j \leftarrow b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3007 5. for $n$ from 0 to $a.used - b - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3008 \hspace{3mm}5.1 $a_i \leftarrow a_j$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3009 \hspace{3mm}5.2 $i \leftarrow i + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3010 \hspace{3mm}5.3 $j \leftarrow j + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3011 6. for $n$ from $a.used - b$ to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3012 \hspace{3mm}6.1 $a_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3013 7. $a.used \leftarrow a.used - b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3014 8. Return. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3015 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3016 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3017 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3018 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3019 \caption{Algorithm mp\_rshd}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3020 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3022 \textbf{Algorithm mp\_rshd.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3023 This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3024 it does not require single precision division. This algorithm does not actually return an error code as it cannot fail.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3026 If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3027 to the shift count $b$ then it will simply zero the input and return.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3029 After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3030 is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3031 Also the digits are copied from the leading to the trailing edge.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3033 Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3035 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3036 \hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3037 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3038 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3039 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3040 017 /* shift right a certain amount of digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3041 018 void mp_rshd (mp_int * a, int b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3042 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3043 020 int x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3044 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3045 022 /* if b <= 0 then ignore it */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3046 023 if (b <= 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3047 024 return;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3048 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3049 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3050 027 /* if b > used then simply zero it and return */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3051 028 if (a->used <= b) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3052 029 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3053 030 return;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3054 031 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3055 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3056 033 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3057 034 register mp_digit *bottom, *top;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3058 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3059 036 /* shift the digits down */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3060 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3061 038 /* bottom */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3062 039 bottom = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3063 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3064 041 /* top [offset into digits] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3065 042 top = a->dp + b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3066 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3067 044 /* this is implemented as a sliding window where
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3068 045 * the window is b-digits long and digits from
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3069 046 * the top of the window are copied to the bottom
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3070 047 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3071 048 * e.g.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3072 049
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3073 050 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3074 051 /\symbol{92} | ---->
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3075 052 \symbol{92}-------------------/ ---->
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3076 053 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3077 054 for (x = 0; x < (a->used - b); x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3078 055 *bottom++ = *top++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3079 056 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3080 057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3081 058 /* zero the top digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3082 059 for (; x < a->used; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3083 060 *bottom++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3084 061 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3085 062 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3086 063
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3087 064 /* remove excess digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3088 065 a->used -= b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3089 066 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
3090 067 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3091 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3092 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3093
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3094 The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3095 form a sliding window except we copy in the other direction. After the window (line 59) we then zero
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3096 the upper digits of the input to make sure the result is correct.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3097
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3098 \section{Powers of Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3099
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3100 Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3101 example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3102 shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3103
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3104 \subsection{Multiplication by Power of Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3105
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3106 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3107 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3108 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3109 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3110 \hline Algorithm \textbf{mp\_mul\_2d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3111 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3112 \textbf{Output}. $c \leftarrow a \cdot 2^b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3113 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3114 1. $c \leftarrow a$. (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3115 2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3116 3. If the reallocation failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3117 4. If $b \ge lg(\beta)$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3118 \hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3119 \hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3120 5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3121 6. If $d \ne 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3122 \hspace{3mm}6.1 $mask \leftarrow 2^d$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3123 \hspace{3mm}6.2 $r \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3124 \hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3125 \hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3126 \hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3127 \hspace{6mm}6.3.3 $r \leftarrow rr$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3128 \hspace{3mm}6.4 If $r > 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3129 \hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3130 \hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3131 7. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3132 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3133 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3134 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3135 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3136 \caption{Algorithm mp\_mul\_2d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3137 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3138
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3139 \textbf{Algorithm mp\_mul\_2d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3140 This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3141 quickly compute the product.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3142
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3143 First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3144 $\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3145 left.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3146
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3147 After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3148 required. If it is non-zero a modified shift loop is used to calculate the remaining product.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3149 Essentially the loop is a generic version of algorith mp\_mul2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3150 variable is used to extract the upper $d$ bits to form the carry for the next iteration.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3151
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3152 This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3153 complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3154
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3155 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3156 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3157 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3158 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3159 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3160 017 /* shift left by a certain bit count */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3161 018 int mp_mul_2d (mp_int * a, int b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3162 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3163 020 mp_digit d;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3164 021 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3165 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3166 023 /* copy */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3167 024 if (a != c) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3168 025 if ((res = mp_copy (a, c)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3169 026 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3170 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3171 028 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3172 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3173 030 if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3174 031 if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3175 032 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3176 033 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3177 034 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3178 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3179 036 /* shift by as many digits in the bit count */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3180 037 if (b >= (int)DIGIT_BIT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3181 038 if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3182 039 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3183 040 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3184 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3185 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3186 043 /* shift any bit count < DIGIT_BIT */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3187 044 d = (mp_digit) (b % DIGIT_BIT);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3188 045 if (d != 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3189 046 register mp_digit *tmpc, shift, mask, r, rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3190 047 register int x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3191 048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3192 049 /* bitmask for carries */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3193 050 mask = (((mp_digit)1) << d) - 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3194 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3195 052 /* shift for msbs */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3196 053 shift = DIGIT_BIT - d;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3197 054
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3198 055 /* alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3199 056 tmpc = c->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3200 057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3201 058 /* carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3202 059 r = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3203 060 for (x = 0; x < c->used; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3204 061 /* get the higher bits of the current word */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3205 062 rr = (*tmpc >> shift) & mask;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3206 063
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3207 064 /* shift the current word and OR in the carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3208 065 *tmpc = ((*tmpc << d) | r) & MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3209 066 ++tmpc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3210 067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3211 068 /* set the carry to the carry bits of the current word */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3212 069 r = rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3213 070 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3214 071
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3215 072 /* set final carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3216 073 if (r != 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3217 074 c->dp[(c->used)++] = r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3218 075 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3219 076 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3220 077 mp_clamp (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3221 078 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3222 079 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
3223 080 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3224 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3225 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3226
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3227 The shifting is performed in--place which means the first step (line 24) is to copy the input to the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3228 destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3229 has to be grown (line 31) to accomodate the result.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3230
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3231 If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3232 of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3233 loop (lines 45 to 76) we make use of pre--computed values $shift$ and $mask$. These are used to
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3234 extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3235 chain between consecutive iterations to propagate the carry.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3236
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3237 \subsection{Division by Power of Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3238
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3239 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3240 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3241 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3242 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3243 \hline Algorithm \textbf{mp\_div\_2d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3244 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3245 \textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3246 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3247 1. If $b \le 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3248 \hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3249 \hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3250 \hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3251 2. $c \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3252 3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3253 4. If $b \ge lg(\beta)$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3254 \hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3255 5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3256 6. If $k \ne 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3257 \hspace{3mm}6.1 $mask \leftarrow 2^k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3258 \hspace{3mm}6.2 $r \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3259 \hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3260 \hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3261 \hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3262 \hspace{6mm}6.3.3 $r \leftarrow rr$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3263 7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3264 8. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3265 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3266 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3267 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3268 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3269 \caption{Algorithm mp\_div\_2d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3270 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3271
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3272 \textbf{Algorithm mp\_div\_2d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3273 This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3274 mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3275 by using algorithm mp\_mod\_2d.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3276
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3277 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3278 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3279 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3280 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3281 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3282 017 /* shift right by a certain bit count (store quotient in c, optional remaind
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3283 er in d) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3284 018 int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3285 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3286 020 mp_digit D, r, rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3287 021 int x, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3288 022 mp_int t;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3289 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3290 024
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3291 025 /* if the shift count is <= 0 then we do no work */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3292 026 if (b <= 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3293 027 res = mp_copy (a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3294 028 if (d != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3295 029 mp_zero (d);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3296 030 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3297 031 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3298 032 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3299 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3300 034 if ((res = mp_init (&t)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3301 035 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3302 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3303 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3304 038 /* get the remainder */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3305 039 if (d != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3306 040 if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3307 041 mp_clear (&t);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3308 042 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3309 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3310 044 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3311 045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3312 046 /* copy */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3313 047 if ((res = mp_copy (a, c)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3314 048 mp_clear (&t);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3315 049 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3316 050 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3317 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3318 052 /* shift by as many digits in the bit count */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3319 053 if (b >= (int)DIGIT_BIT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3320 054 mp_rshd (c, b / DIGIT_BIT);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3321 055 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3322 056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3323 057 /* shift any bit count < DIGIT_BIT */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3324 058 D = (mp_digit) (b % DIGIT_BIT);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3325 059 if (D != 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3326 060 register mp_digit *tmpc, mask, shift;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3327 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3328 062 /* mask */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3329 063 mask = (((mp_digit)1) << D) - 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3330 064
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3331 065 /* shift for lsb */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3332 066 shift = DIGIT_BIT - D;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3333 067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3334 068 /* alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3335 069 tmpc = c->dp + (c->used - 1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3336 070
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3337 071 /* carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3338 072 r = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3339 073 for (x = c->used - 1; x >= 0; x--) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3340 074 /* get the lower bits of this word in a temp */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3341 075 rr = *tmpc & mask;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3342 076
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3343 077 /* shift the current word and mix in the carry bits from the previous
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3344 word */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3345 078 *tmpc = (*tmpc >> D) | (r << shift);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3346 079 --tmpc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3347 080
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3348 081 /* set the carry to the carry bits of the current word found above */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3349 082 r = rr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3350 083 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3351 084 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3352 085 mp_clamp (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3353 086 if (d != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3354 087 mp_exch (&t, d);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3355 088 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3356 089 mp_clear (&t);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3357 090 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3358 091 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
3359 092 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3360 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3361 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3362
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3363 The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3364 ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3365 result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3366 the quotient is obtained.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3367
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3368 The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3369 the direction of the shifts.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3370
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3371 \subsection{Remainder of Division by Power of Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3372
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3373 The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3374 algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3375
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3376 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3377 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3378 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3379 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3380 \hline Algorithm \textbf{mp\_mod\_2d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3381 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3382 \textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3383 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3384 1. If $b \le 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3385 \hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3386 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3387 2. If $b > a.used \cdot lg(\beta)$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3388 \hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3389 \hspace{3mm}2.2 Return the result of step 2.1. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3390 3. $c \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3391 4. If step 3 failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3392 5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3393 \hspace{3mm}5.1 $c_n \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3394 6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3395 7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3396 8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3397 9. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3398 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3399 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3400 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3401 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3402 \caption{Algorithm mp\_mod\_2d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3403 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3404
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3405 \textbf{Algorithm mp\_mod\_2d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3406 This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3407 result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3408 is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3409
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3410 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3411 \hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3412 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3413 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3414 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3415 017 /* calc a value mod 2**b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3416 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3417 019 mp_mod_2d (mp_int * a, int b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3418 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3419 021 int x, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3420 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3421 023 /* if b is <= 0 then zero the int */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3422 024 if (b <= 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3423 025 mp_zero (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3424 026 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3425 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3426 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3427 029 /* if the modulus is larger than the value than return */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3428 030 if (b >= (int) (a->used * DIGIT_BIT)) \{
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3429 031 res = mp_copy (a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3430 032 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3431 033 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3432 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3433 035 /* copy */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3434 036 if ((res = mp_copy (a, c)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3435 037 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3436 038 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3437 039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3438 040 /* zero digits above the last digit of the modulus */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3439 041 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x+
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3440 +) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3441 042 c->dp[x] = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3442 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3443 044 /* clear the digit that is not completely outside/inside the modulus */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3444 045 c->dp[b / DIGIT_BIT] &=
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3445 046 (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digi
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3446 t) 1));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3447 047 mp_clamp (c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3448 048 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3449 049 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
3450 050 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3451 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3452 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3453
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3454 We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3455 than the input we just mp\_copy() the input and return right away. After this point we know we must actually
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3456 perform some work to produce the remainder.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3457
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3458 Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3459 the number. First we zero any digits above the last digit in $2^b$ (line 41). Next we reduce the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3460 leading digit of both (line 45) and then mp\_clamp().
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3461
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3462 \section*{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3463 \begin{tabular}{cl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3464 $\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3465 & in $O(n)$ time. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3466 &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3467 $\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3468 & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3469 & upto $64$ with a hamming weight less than three. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3470 &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3471 $\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3472 & $2^k - 1$ as well. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3473 &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3474 $\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3475 & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3476 & any $n$-bit input. Note that the time of addition is ignored in the \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3477 & calculation. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3478 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3479 $\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3480 & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3481 & the cost of addition. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3482 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3483 $\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3484 & for $n = 64 \ldots 1024$ in steps of $64$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3485 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3486 $\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3487 & calculating the result of a signed comparison. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3488 &
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3489 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3490
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3491 \chapter{Multiplication and Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3492 \section{The Multipliers}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3493 For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3494 algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3495 where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3496 and squaring, leaving modular reductions for the subsequent chapter.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3497
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3498 The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3499 exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3500 exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3501 35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3502 multiplications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3503
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3504 For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3505 against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3506 overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3507 1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3508 This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3509
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3510 \section{Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3511 \subsection{The Baseline Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3512 \label{sec:basemult}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3513 \index{baseline multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3514 Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3515 algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3516 multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3517 simplify most discussions, it will be assumed that the inputs have comparable number of digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3518
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3519 The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3520 used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3521 facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3522 modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3523 will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3524
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3525 Recall from sub-section 4.2.2 the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3526 include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3527 constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see sub-section 5.2.2 for more information}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3528
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3529 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3530 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3531 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3532 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3533 \hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3534 \textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3535 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3536 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3537 1. If min$(a.used, b.used) < \delta$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3538 \hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3539 \hspace{3mm}1.2 Return the result of step 1.1 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3540 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3541 Allocate and initialize a temporary mp\_int. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3542 2. Init $t$ to be of size $digs$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3543 3. If step 2 failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3544 4. $t.used \leftarrow digs$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3545 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3546 Compute the product. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3547 5. for $ix$ from $0$ to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3548 \hspace{3mm}5.1 $u \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3549 \hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3550 \hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3551 \hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3552 \hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3553 \hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3554 \hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3555 \hspace{3mm}5.5 if $ix + pb < digs$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3556 \hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3557 6. Clamp excess digits of $t$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3558 7. Swap $c$ with $t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3559 8. Clear $t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3560 9. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3561 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3562 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3563 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3564 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3565 \caption{Algorithm s\_mp\_mul\_digs}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3566 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3567
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3568 \textbf{Algorithm s\_mp\_mul\_digs.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3569 This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3570 a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3571 algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3572 Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3573 inputs.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3574
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3575 The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3576 input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3577 temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3578 compute products when either $a = c$ or $b = c$ without overwriting the inputs.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3579
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3580 All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3581 is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3582 will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3583 innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3584
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3585 For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3586 visualized in the following table.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3587
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3588 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3589 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3590 \begin{tabular}{|c|c|c|c|c|c|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3591 \hline && & 5 & 7 & 6 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3592 \hline $\times$&& & 2 & 4 & 1 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3593 \hline &&&&&&\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3594 && & 5 & 7 & 6 & $10^0(1)(576)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3595 &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3596 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3597 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3598 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3599 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3600 \caption{Long-Hand Multiplication Diagram}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3601 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3602
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3603 Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3604 count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3605
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3606 Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3607 is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3608 double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3609 5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3610 $t_{ix+iy}$ and the result would be lost.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3611
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3612 At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3613 digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3614 exceed the precision requested.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3615
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3616 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3617 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3618 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3619 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3620 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3621 017 /* multiplies |a| * |b| and only computes upto digs digits of result
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3622 018 * HAC pp. 595, Algorithm 14.12 Modified so you can control how
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3623 019 * many digits of output are created.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3624 020 */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3625 021 int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3626 022 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3627 023 mp_int t;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3628 024 int res, pa, pb, ix, iy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3629 025 mp_digit u;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3630 026 mp_word r;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3631 027 mp_digit tmpx, *tmpt, *tmpy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3632 028
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3633 029 /* can we use the fast multiplier? */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3634 030 if (((digs) < MP_WARRAY) &&
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3635 031 MIN (a->used, b->used) <
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3636 032 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3637 033 return fast_s_mp_mul_digs (a, b, c, digs);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3638 034 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3639 035
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3640 036 if ((res = mp_init_size (&t, digs)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3641 037 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3642 038 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3643 039 t.used = digs;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3644 040
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3645 041 /* compute the digits of the product directly */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3646 042 pa = a->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3647 043 for (ix = 0; ix < pa; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3648 044 /* set the carry to zero */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3649 045 u = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3650 046
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3651 047 /* limit ourselves to making digs digits of output */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3652 048 pb = MIN (b->used, digs - ix);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3653 049
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3654 050 /* setup some aliases */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3655 051 /* copy of the digit from a used within the nested loop */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3656 052 tmpx = a->dp[ix];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3657 053
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3658 054 /* an alias for the destination shifted ix places */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3659 055 tmpt = t.dp + ix;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3660 056
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3661 057 /* an alias for the digits of b */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3662 058 tmpy = b->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3663 059
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3664 060 /* compute the columns of the output and propagate the carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3665 061 for (iy = 0; iy < pb; iy++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3666 062 /* compute the column as a mp_word */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3667 063 r = ((mp_word)*tmpt) +
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3668 064 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3669 065 ((mp_word) u);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3670 066
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3671 067 /* the new column is the lower part of the result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3672 068 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3673 069
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3674 070 /* get the carry word from the result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3675 071 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3676 072 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3677 073 /* set carry if it is placed below digs */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3678 074 if (ix + iy < digs) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3679 075 *tmpt = u;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3680 076 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3681 077 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3682 078
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3683 079 mp_clamp (&t);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3684 080 mp_exch (&t, c);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3685 081
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3686 082 mp_clear (&t);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3687 083 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3688 084 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3689 085 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3690 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3691 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3692
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3693 First we determine (line 30) if the Comba method can be used first since it's faster. The conditions for
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3694 sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3695 \textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3696 set to $\delta$ but can be reduced when memory is at a premium.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3697
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3698 If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3699 $t$ (line 36) to the exact size of the output to avoid further re--allocations. At this point we now
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3700 begin the $O(n^2)$ loop.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3701
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3702 This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3703 digits as output. In each iteration of the outer loop the $pb$ variable is set (line 48) to the maximum
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3704 number of inner loop iterations.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3705
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3706 Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3707 carry from the previous iteration. A particularly important observation is that most modern optimizing
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3708 C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3709 is required for the product. In x86 terms for example, this means using the MUL instruction.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3710
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3711 Each digit of the product is stored in turn (line 68) and the carry propagated (line 71) to the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3712 next iteration.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3713
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3714 \subsection{Faster Multiplication by the ``Comba'' Method}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3715
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3716 One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3717 computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3718 in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3719 Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3720 interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3721 five years before.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3722
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3723 At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3724 twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3725 are produced then added together to form the final result. In the baseline algorithm the columns are added together
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3726 after each iteration to get the result instantaneously.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3727
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3728 In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3729 the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3730 after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3731 the product vector $\vec x$ as follows.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3732
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3733 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3734 \vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3735 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3736
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3737 Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3738 of $576$ and $241$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3739
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3740 \newpage\begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3741 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3742 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3743 \begin{tabular}{|c|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3744 \hline & & 5 & 7 & 6 & First Input\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3745 \hline $\times$ & & 2 & 4 & 1 & Second Input\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3746 \hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3747 & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3748 $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3749 \hline 10 & 34 & 45 & 31 & 6 & Final Result \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3750 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3751 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3752 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3753 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3754 \caption{Comba Multiplication Diagram}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3755 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3756
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3757 At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3758 Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3759 congruent to adding a leading zero digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3760
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3761 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3762 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3763 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3764 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3765 \hline Algorithm \textbf{Comba Fixup}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3766 \textbf{Input}. Vector $\vec x$ of dimension $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3767 \textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3768 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3769 1. for $n$ from $0$ to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3770 \hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3771 \hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3772 2. Return($\vec x$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3773 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3774 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3775 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3776 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3777 \caption{Algorithm Comba Fixup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3778 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3779
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3780 With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3781 $241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3782 efficient than the baseline algorithm why not simply always use this algorithm?
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3783
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3784 \subsubsection{Column Weight.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3785 At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3786 independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3787 the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3788 three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3789 an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3790 min$(m, n)$ which is fairly obvious.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3791
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3792 The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3793 from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3794 two quantities we must not violate the following
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3795
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3796 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3797 k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3798 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3799
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3800 Which reduces to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3801
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3802 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3803 k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3804 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3805
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3806 Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3807 found.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3808
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3809 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3810 k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3811 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3812
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3813 The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3814 the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3815 $256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3816
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3817 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3818 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3819 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3820 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3821 \hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3822 \textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3823 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3824 \hline \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3825 Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3826 1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3827 2. If step 1 failed return(\textit{MP\_MEM}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3828 \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3829 3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3830 \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3831 4. $\_ \hat W \leftarrow 0$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3832 5. for $ix$ from 0 to $pa - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3833 \hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3834 \hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3835 \hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3836 \hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3837 \hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3838 \hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3839 \hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3840 6. $W_{pa} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3841 \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3842 7. $oldused \leftarrow c.used$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3843 8. $c.used \leftarrow digs$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3844 9. for $ix$ from $0$ to $pa$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3845 \hspace{3mm}9.1 $c_{ix} \leftarrow W_{ix}$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3846 10. for $ix$ from $pa + 1$ to $oldused - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3847 \hspace{3mm}10.1 $c_{ix} \leftarrow 0$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3848 \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3849 11. Clamp $c$. \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3850 12. Return MP\_OKAY. \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3851 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3852 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3853 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3854 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3855 \caption{Algorithm fast\_s\_mp\_mul\_digs}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3856 \label{fig:COMBAMULT}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3857 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3858
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3859 \textbf{Algorithm fast\_s\_mp\_mul\_digs.}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3860 This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3861
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3862 The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3863 loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3864 reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3865
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3866 The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3867 $b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3868 $ix$ is. This is used for the immediately subsequent statement where we find $iy$.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3869
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3870 The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3871 means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3872 pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3873 move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3874 $tx \ge a.used$ or $ty < 0$ occurs.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3875
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3876 After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3877 into the next round by dividing $\_ \hat W$ by $\beta$.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3878
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3879 To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3880 cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3881 $O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3882 the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3883 and addition operations in the nested loop in parallel.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3884
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3885 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3886 \hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3887 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3888 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3889 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3890 017 /* Fast (comba) multiplier
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3891 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3892 019 * This is the fast column-array [comba] multiplier. It is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3893 020 * designed to compute the columns of the product first
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3894 021 * then handle the carries afterwards. This has the effect
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3895 022 * of making the nested loops that compute the columns very
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3896 023 * simple and schedulable on super-scalar processors.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3897 024 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3898 025 * This has been modified to produce a variable number of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3899 026 * digits of output so if say only a half-product is required
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3900 027 * you don't have to compute the upper half (a feature
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3901 028 * required for fast Barrett reduction).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3902 029 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3903 030 * Based on Algorithm 14.12 on pp.595 of HAC.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3904 031 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3905 032 */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3906 033 int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3907 034 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3908 035 int olduse, res, pa, ix, iz;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3909 036 mp_digit W[MP_WARRAY];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3910 037 register mp_word _W;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3911 038
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3912 039 /* grow the destination as required */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3913 040 if (c->alloc < digs) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3914 041 if ((res = mp_grow (c, digs)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3915 042 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3916 043 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3917 044 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3918 045
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3919 046 /* number of output digits to produce */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3920 047 pa = MIN(digs, a->used + b->used);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3921 048
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3922 049 /* clear the carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3923 050 _W = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3924 051 for (ix = 0; ix < pa; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3925 052 int tx, ty;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3926 053 int iy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3927 054 mp_digit *tmpx, *tmpy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3928 055
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3929 056 /* get offsets into the two bignums */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3930 057 ty = MIN(b->used-1, ix);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3931 058 tx = ix - ty;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3932 059
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3933 060 /* setup temp aliases */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3934 061 tmpx = a->dp + tx;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3935 062 tmpy = b->dp + ty;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3936 063
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3937 064 /* this is the number of times the loop will iterrate, essentially
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3938 065 while (tx++ < a->used && ty-- >= 0) \{ ... \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3939 066 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3940 067 iy = MIN(a->used-tx, ty+1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3941 068
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3942 069 /* execute loop */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3943 070 for (iz = 0; iz < iy; ++iz) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3944 071 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3945 072 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3946 073
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3947 074 /* store term */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3948 075 W[ix] = ((mp_digit)_W) & MP_MASK;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3949 076
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3950 077 /* make next carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3951 078 _W = _W >> ((mp_word)DIGIT_BIT);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3952 079 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3953 080
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3954 081 /* store final carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3955 082 W[ix] = (mp_digit)(_W & MP_MASK);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3956 083
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3957 084 /* setup dest */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3958 085 olduse = c->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3959 086 c->used = pa;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3960 087
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3961 088 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3962 089 register mp_digit *tmpc;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3963 090 tmpc = c->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3964 091 for (ix = 0; ix < pa+1; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3965 092 /* now extract the previous digit [below the carry] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3966 093 *tmpc++ = W[ix];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3967 094 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3968 095
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3969 096 /* clear unused digits [that existed in the old copy of c] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3970 097 for (; ix < olduse; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3971 098 *tmpc++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3972 099 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3973 100 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3974 101 mp_clamp (c);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3975 102 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3976 103 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3977 104 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3978 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3979 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3980
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3981 As per the pseudo--code we first calculate $pa$ (line 47) as the number of digits to output. Next we begin the outer loop
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3982 to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines 61, 62) to point
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3983 inside the two multiplicands quickly.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3984
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3985 The inner loop (lines 70 to 72) of this implementation is where the tradeoff come into play. Originally this comba
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3986 implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3987 the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3988 one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3989 is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3990 slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3991 compiler has aliased $\_ \hat W$ to a CPU register.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3992
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3993 After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 75, 78) to forward it as
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
3994 a carry for the next pass. After the outer loop we use the final carry (line 82) as the last digit of the product.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3995
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3996 \subsection{Polynomial Basis Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3997 To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3998 the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3999 $g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4000
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4001 The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4002 directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4003 requires $O(n^2)$ time and would in practice be slower than the Comba technique.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4004
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4005 However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4006 coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4007 Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4008 effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4009
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4010 The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4011 $W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4012 fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4013 by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4014
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4015 When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4016 is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4017 $W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4018 simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4019 The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4020 points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4022 If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4023 $\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4024 $\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4025 example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4027 \begin{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4028 \zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4029 16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4030 \end{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4032 Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4033 polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4035 As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4036 multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4037 $O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4038 summarizes the exponents for various values of $n$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4039
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4040 \begin{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4041 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4042 \begin{tabular}{|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4043 \hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4044 \hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4045 \hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4046 \hline $4$ & $1.403677461$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4047 \hline $5$ & $1.365212389$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4048 \hline $10$ & $1.278753601$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4049 \hline $100$ & $1.149426538$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4050 \hline $1000$ & $1.100270931$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4051 \hline $10000$ & $1.075252070$ &\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4052 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4053 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4054 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4055 \caption{Asymptotic Running Time of Polynomial Basis Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4056 \label{fig:exponent}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4057 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4058
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4059 At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4060 of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4061 numbers.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4062
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4063 \subsubsection{Cutoff Point}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4064 The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4065 the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4066 polynomial basis approach more costly to use with small inputs.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4068 Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4069 point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4070 when $m > y$ the Comba methods are slower than the polynomial basis algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4071
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4072 The exact location of $y$ depends on several key architectural elements of the computer platform in question.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4074 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4075 \item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4076 on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4077 the cutoff point $y$ will be.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4078
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4079 \item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4080 grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4081 directly reflects on the ratio previous mentioned.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4082
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4083 \item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4084 influence over the cutoff point.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4085
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4086 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4087
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4088 A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4089 is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4090 a high resolution timer is available.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4091
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4092 \subsection{Karatsuba Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4093 Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4094 general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4095 light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4096
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4097 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4098 f(x) \cdot g(x) = acx^2 + ((a - b)(c - d) - (ac + bd))x + bd
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4099 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4100
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4101 Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4102 this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4103 out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4104 $\zeta_0$, $\zeta_{\infty}$ and $-\zeta_{-1}$. Consider the resultant system of equations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4105
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4106 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4107 \begin{tabular}{rcrcrcrc}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4108 $\zeta_{0}$ & $=$ & & & & & $w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4109 $-\zeta_{-1}$ & $=$ & $-w_2$ & $+$ & $w_1$ & $-$ & $w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4110 $\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4111 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4112 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4113
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4114 By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4115 of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4116 making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman. It is worth noting that the point
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4117 $\zeta_1$ could be substituted for $-\zeta_{-1}$. In this case the first and third row are subtracted instead of added to the second row.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4118
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4119 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4120 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4121 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4122 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4123 \hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4124 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4125 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4126 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4127 1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4128 2. If step 2 failed then return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4129 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4130 Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4131 3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4132 4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4133 5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4134 6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4135 7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4136 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4137 Calculate the three products. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4138 8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4139 9. $x1y1 \leftarrow x1 \cdot y1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4140 10. $t1 \leftarrow x1 - x0$ (\textit{mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4141 11. $x0 \leftarrow y1 - y0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4142 12. $t1 \leftarrow t1 \cdot x0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4143 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4144 Calculate the middle term. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4145 13. $x0 \leftarrow x0y0 + x1y1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4146 14. $t1 \leftarrow x0 - t1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4147 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4148 Calculate the final product. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4149 15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4150 16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4151 17. $t1 \leftarrow x0y0 + t1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4152 18. $c \leftarrow t1 + x1y1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4153 19. Clear all of the temporary variables. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4154 20. Return(\textit{MP\_OKAY}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4155 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4156 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4157 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4158 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4159 \caption{Algorithm mp\_karatsuba\_mul}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4160 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4161
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4162 \textbf{Algorithm mp\_karatsuba\_mul.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4163 This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4164 from Knuth \cite[pp. 294-295]{TAOCPV2}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4165
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4166 \index{radix point}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4167 In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4168 be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4169 smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4170 compute the lower halves. Step 6 and 7 computer the upper halves.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4171
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4172 After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4173 $x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 - x0$ has been computed. By using $x0$ instead
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4174 of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4175
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4176 The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4177
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4178 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4179 \hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4180 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4181 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4182 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4183 017 /* c = |a| * |b| using Karatsuba Multiplication using
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4184 018 * three half size multiplications
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4185 019 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4186 020 * Let B represent the radix [e.g. 2**DIGIT_BIT] and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4187 021 * let n represent half of the number of digits in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4188 022 * the min(a,b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4189 023 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4190 024 * a = a1 * B**n + a0
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4191 025 * b = b1 * B**n + b0
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4192 026 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4193 027 * Then, a * b =>
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4194 028 a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4195 029 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4196 030 * Note that a1b1 and a0b0 are used twice and only need to be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4197 031 * computed once. So in total three half size (half # of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4198 032 * digit) multiplications are performed, a0b0, a1b1 and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4199 033 * (a1-b1)(a0-b0)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4200 034 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4201 035 * Note that a multiplication of half the digits requires
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4202 036 * 1/4th the number of single precision multiplications so in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4203 037 * total after one call 25% of the single precision multiplications
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4204 038 * are saved. Note also that the call to mp_mul can end up back
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4205 039 * in this function if the a0, a1, b0, or b1 are above the threshold.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4206 040 * This is known as divide-and-conquer and leads to the famous
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4207 041 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4208 042 * the standard O(N**2) that the baseline/comba methods use.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4209 043 * Generally though the overhead of this method doesn't pay off
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4210 044 * until a certain size (N ~ 80) is reached.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4211 045 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4212 046 int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4213 047 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4214 048 mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4215 049 int B, err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4216 050
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4217 051 /* default the return code to an error */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4218 052 err = MP_MEM;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4219 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4220 054 /* min # of digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4221 055 B = MIN (a->used, b->used);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4222 056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4223 057 /* now divide in two */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4224 058 B = B >> 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4225 059
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4226 060 /* init copy all the temps */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4227 061 if (mp_init_size (&x0, B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4228 062 goto ERR;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4229 063 if (mp_init_size (&x1, a->used - B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4230 064 goto X0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4231 065 if (mp_init_size (&y0, B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4232 066 goto X1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4233 067 if (mp_init_size (&y1, b->used - B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4234 068 goto Y0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4235 069
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4236 070 /* init temps */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4237 071 if (mp_init_size (&t1, B * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4238 072 goto Y1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4239 073 if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4240 074 goto T1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4241 075 if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4242 076 goto X0Y0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4243 077
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4244 078 /* now shift the digits */
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4245 079 x0.used = y0.used = B;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4246 080 x1.used = a->used - B;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4247 081 y1.used = b->used - B;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4248 082
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4249 083 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4250 084 register int x;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4251 085 register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4252 086
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4253 087 /* we copy the digits directly instead of using higher level functions
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4254 088 * since we also need to shift the digits
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4255 089 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4256 090 tmpa = a->dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4257 091 tmpb = b->dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4258 092
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4259 093 tmpx = x0.dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4260 094 tmpy = y0.dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4261 095 for (x = 0; x < B; x++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4262 096 *tmpx++ = *tmpa++;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4263 097 *tmpy++ = *tmpb++;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4264 098 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4265 099
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4266 100 tmpx = x1.dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4267 101 for (x = B; x < a->used; x++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4268 102 *tmpx++ = *tmpa++;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4269 103 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4270 104
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4271 105 tmpy = y1.dp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4272 106 for (x = B; x < b->used; x++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4273 107 *tmpy++ = *tmpb++;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4274 108 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4275 109 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4276 110
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4277 111 /* only need to clamp the lower words since by definition the
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4278 112 * upper words x1/y1 must have a known number of digits
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4279 113 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4280 114 mp_clamp (&x0);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4281 115 mp_clamp (&y0);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4282 116
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4283 117 /* now calc the products x0y0 and x1y1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4284 118 /* after this x0 is no longer required, free temp [x0==t2]! */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4285 119 if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4286 120 goto X1Y1; /* x0y0 = x0*y0 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4287 121 if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4288 122 goto X1Y1; /* x1y1 = x1*y1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4289 123
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4290 124 /* now calc x1-x0 and y1-y0 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4291 125 if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4292 126 goto X1Y1; /* t1 = x1 - x0 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4293 127 if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4294 128 goto X1Y1; /* t2 = y1 - y0 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4295 129 if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4296 130 goto X1Y1; /* t1 = (x1 - x0) * (y1 - y0) */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4297 131
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4298 132 /* add x0y0 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4299 133 if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4300 134 goto X1Y1; /* t2 = x0y0 + x1y1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4301 135 if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4302 136 goto X1Y1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4303 137
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4304 138 /* shift by B */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4305 139 if (mp_lshd (&t1, B) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4306 140 goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4307 141 if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4308 142 goto X1Y1; /* x1y1 = x1y1 << 2*B */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4309 143
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4310 144 if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4311 145 goto X1Y1; /* t1 = x0y0 + t1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4312 146 if (mp_add (&t1, &x1y1, c) != MP_OKAY)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4313 147 goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4314 148
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4315 149 /* Algorithm succeeded set the return code to MP_OKAY */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4316 150 err = MP_OKAY;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4317 151
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4318 152 X1Y1:mp_clear (&x1y1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4319 153 X0Y0:mp_clear (&x0y0);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4320 154 T1:mp_clear (&t1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4321 155 Y1:mp_clear (&y1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4322 156 Y0:mp_clear (&y0);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4323 157 X1:mp_clear (&x1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4324 158 X0:mp_clear (&x0);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4325 159 ERR:
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4326 160 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4327 161 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4328 162 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4329 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4330 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4331
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4332 The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4333 wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4334 to handle error recovery with a single piece of code. Lines 61 to 75 handle initializing all of the temporary variables
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4335 required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4336 the temporaries that have been successfully allocated so far.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4337
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4338 The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4339 additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4340 number of digits for the next section of code.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4341
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4342 The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4343 to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4344 \textbf{sign} members are copied first. The first for loop on line 101 copies the lower halves. Since they are both the same magnitude it
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4345 is simpler to calculate both lower halves in a single loop. The for loop on lines 106 and 106 calculate the upper halves $x1$ and
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4346 $y1$ respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4347
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4348 By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4349
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4350 When line 150 is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4351 the same code that handles errors can be used to clear the temporary variables and return.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4352
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4353 \subsection{Toom-Cook $3$-Way Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4354 Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4355 chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4356 $16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4357 of the $W(x)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4358
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4359 With the five relations that Toom-Cook specifies, the following system of equations is formed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4360
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4361 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4362 \begin{tabular}{rcrcrcrcrcr}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4363 $\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4364 $16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4365 $\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4366 $\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4367 $\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4368 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4369 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4370
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4371 A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4372 of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4373 the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4374 (\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4375
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4376 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4377 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4378 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4379 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4380 \hline Algorithm \textbf{mp\_toom\_mul}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4381 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4382 \textbf{Output}. $c \leftarrow a \cdot b $ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4383 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4384 Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4385 1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4386 2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4387 3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4388 4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4389 5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4390 6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4391 7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4392 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4393 Find the five equations for $w_0, w_1, ..., w_4$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4394 8. $w_0 \leftarrow a_0 \cdot b_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4395 9. $w_4 \leftarrow a_2 \cdot b_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4396 10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4397 11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4398 12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4399 13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4400 14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4401 15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4402 16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4403 17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4404 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4405 Continued on the next page.\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4406 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4407 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4408 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4409 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4410 \caption{Algorithm mp\_toom\_mul}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4411 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4412
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4413 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4414 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4415 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4416 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4417 \hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4418 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4419 \textbf{Output}. $c \leftarrow a \cdot b $ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4420 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4421 Now solve the system of equations. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4422 18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4423 19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4424 20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4425 21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4426 22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4427 23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4428 24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4429 25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4430 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4431 Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4432 26. for $n$ from $1$ to $4$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4433 \hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4434 27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4435 28. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4436 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4437 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4438 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4439 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4440 \caption{Algorithm mp\_toom\_mul (continued)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4441 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4442
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4443 \textbf{Algorithm mp\_toom\_mul.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4444 This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4445 algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4446 description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4447 any given step.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4448
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4449 The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4450 integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4451
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4452 The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4453 to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4454 $f(y)$ and $g(y)$ which significantly speeds up the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4455
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4456 After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4457 $w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4458 the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4459 that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4460
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4461 Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4462 result $a \cdot b$ is produced.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4463
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4464 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4465 \hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4466 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4467 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4468 016
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4469 017 /* multiplication using the Toom-Cook 3-way algorithm
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4470 018 *
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4471 019 * Much more complicated than Karatsuba but has a lower
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4472 020 * asymptotic running time of O(N**1.464). This algorithm is
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4473 021 * only particularly useful on VERY large inputs
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4474 022 * (we're talking 1000s of digits here...).
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4475 023 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4476 024 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4477 025 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4478 026 mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4479 027 int res, B;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4480 028
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4481 029 /* init temps */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4482 030 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4483 031 &a0, &a1, &a2, &b0, &b1,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4484 032 &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4485 033 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4486 034 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4487 035
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4488 036 /* B */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4489 037 B = MIN(a->used, b->used) / 3;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4490 038
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4491 039 /* a = a2 * B**2 + a1 * B + a0 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4492 040 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4493 041 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4494 042 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4495 043
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4496 044 if ((res = mp_copy(a, &a1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4497 045 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4498 046 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4499 047 mp_rshd(&a1, B);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4500 048 mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4501 049
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4502 050 if ((res = mp_copy(a, &a2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4503 051 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4504 052 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4505 053 mp_rshd(&a2, B*2);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4506 054
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4507 055 /* b = b2 * B**2 + b1 * B + b0 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4508 056 if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4509 057 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4510 058 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4511 059
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4512 060 if ((res = mp_copy(b, &b1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4513 061 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4514 062 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4515 063 mp_rshd(&b1, B);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4516 064 mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4517 065
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4518 066 if ((res = mp_copy(b, &b2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4519 067 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4520 068 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4521 069 mp_rshd(&b2, B*2);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4522 070
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4523 071 /* w0 = a0*b0 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4524 072 if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4525 073 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4526 074 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4527 075
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4528 076 /* w4 = a2 * b2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4529 077 if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4530 078 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4531 079 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4532 080
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4533 081 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4534 082 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4535 083 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4536 084 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4537 085 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4538 086 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4539 087 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4540 088 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4541 089 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4542 090 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4543 091 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4544 092 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4545 093 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4546 094
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4547 095 if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4548 096 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4549 097 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4550 098 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4551 099 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4552 100 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4553 101 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4554 102 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4555 103 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4556 104 if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4557 105 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4558 106 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4559 107
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4560 108 if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4561 109 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4562 110 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4563 111
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4564 112 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4565 113 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4566 114 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4567 115 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4568 116 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4569 117 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4570 118 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4571 119 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4572 120 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4573 121 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4574 122 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4575 123 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4576 124 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4577 125
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4578 126 if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4579 127 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4580 128 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4581 129 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4582 130 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4583 131 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4584 132 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4585 133 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4586 134 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4587 135 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4588 136 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4589 137 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4590 138
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4591 139 if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4592 140 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4593 141 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4594 142
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4595 143
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4596 144 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4597 145 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4598 146 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4599 147 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4600 148 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4601 149 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4602 150 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4603 151 if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4604 152 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4605 153 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4606 154 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4607 155 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4608 156 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4609 157 if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4610 158 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4611 159 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4612 160
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4613 161 /* now solve the matrix
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4614 162
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4615 163 0 0 0 0 1
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4616 164 1 2 4 8 16
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4617 165 1 1 1 1 1
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4618 166 16 8 4 2 1
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4619 167 1 0 0 0 0
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4620 168
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4621 169 using 12 subtractions, 4 shifts,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4622 170 2 small divisions and 1 small multiplication
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4623 171 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4624 172
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4625 173 /* r1 - r4 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4626 174 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4627 175 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4628 176 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4629 177 /* r3 - r0 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4630 178 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4631 179 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4632 180 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4633 181 /* r1/2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4634 182 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4635 183 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4636 184 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4637 185 /* r3/2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4638 186 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4639 187 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4640 188 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4641 189 /* r2 - r0 - r4 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4642 190 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4643 191 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4644 192 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4645 193 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4646 194 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4647 195 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4648 196 /* r1 - r2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4649 197 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4650 198 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4651 199 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4652 200 /* r3 - r2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4653 201 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4654 202 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4655 203 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4656 204 /* r1 - 8r0 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4657 205 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4658 206 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4659 207 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4660 208 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4661 209 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4662 210 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4663 211 /* r3 - 8r4 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4664 212 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4665 213 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4666 214 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4667 215 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4668 216 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4669 217 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4670 218 /* 3r2 - r1 - r3 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4671 219 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4672 220 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4673 221 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4674 222 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4675 223 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4676 224 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4677 225 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4678 226 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4679 227 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4680 228 /* r1 - r2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4681 229 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4682 230 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4683 231 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4684 232 /* r3 - r2 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4685 233 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4686 234 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4687 235 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4688 236 /* r1/3 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4689 237 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4690 238 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4691 239 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4692 240 /* r3/3 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4693 241 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4694 242 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4695 243 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4696 244
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4697 245 /* at this point shift W[n] by B*n */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4698 246 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4699 247 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4700 248 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4701 249 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4702 250 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4703 251 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4704 252 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4705 253 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4706 254 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4707 255 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4708 256 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4709 257 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4710 258
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4711 259 if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4712 260 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4713 261 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4714 262 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4715 263 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4716 264 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4717 265 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4718 266 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4719 267 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4720 268 if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4721 269 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4722 270 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4723 271
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4724 272 ERR:
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4725 273 mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4726 274 &a0, &a1, &a2, &b0, &b1,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4727 275 &b2, &tmp1, &tmp2, NULL);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4728 276 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4729 277 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4730 278
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4731 279 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4732 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4733 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4734
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4735 The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4736 large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4737 Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4738 algorithm is not practical as Karatsuba has a much lower cutoff point.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4739
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4740 First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines 40 to 69) with
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4741 combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4742 for $b$.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4743
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4744 Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4745 we get those out of the way first (lines 72 and 77). Next we compute $w1, w2$ and $w3$ using Horners method.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4746
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4747 After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4748 straight forward.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4749
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4750 \subsection{Signed Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4751 Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4752 of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4753
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4754 \begin{figure}[!here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4755 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4756 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4757 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4758 \hline Algorithm \textbf{mp\_mul}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4759 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4760 \textbf{Output}. $c \leftarrow a \cdot b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4761 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4762 1. If $a.sign = b.sign$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4763 \hspace{3mm}1.1 $sign = MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4764 2. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4765 \hspace{3mm}2.1 $sign = MP\_ZNEG$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4766 3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4767 \hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4768 4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4769 \hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4770 5. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4771 \hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4772 \hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4773 \hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4774 \hspace{3mm}5.3 else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4775 \hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4776 6. $c.sign \leftarrow sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4777 7. Return the result of the unsigned multiplication performed. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4778 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4779 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4780 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4781 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4782 \caption{Algorithm mp\_mul}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4783 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4784
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4785 \textbf{Algorithm mp\_mul.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4786 This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4787 available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4788 s\_mp\_mul\_digs will clear it.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4789
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4790 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4791 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4792 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4793 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4794 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4795 017 /* high level multiplication (handles sign) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4796 018 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4797 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4798 020 int res, neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4799 021 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4800 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4801 023 /* use Toom-Cook? */
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4802 024 #ifdef BN_MP_TOOM_MUL_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4803 025 if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4804 026 res = mp_toom_mul(a, b, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4805 027 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4806 028 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4807 029 #ifdef BN_MP_KARATSUBA_MUL_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4808 030 /* use Karatsuba? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4809 031 if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4810 032 res = mp_karatsuba_mul (a, b, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4811 033 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4812 034 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4813 035 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4814 036 /* can we use the fast multiplier?
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4815 037 *
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4816 038 * The fast multiplier can be used if the output will
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4817 039 * have less than MP_WARRAY digits and the number of
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4818 040 * digits won't affect carry propagation
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4819 041 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4820 042 int digs = a->used + b->used + 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4821 043
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4822 044 #ifdef BN_FAST_S_MP_MUL_DIGS_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4823 045 if ((digs < MP_WARRAY) &&
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4824 046 MIN(a->used, b->used) <=
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4825 047 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4826 048 res = fast_s_mp_mul_digs (a, b, c, digs);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4827 049 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4828 050 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4829 051 #ifdef BN_S_MP_MUL_DIGS_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4830 052 res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4831 053 #else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4832 054 res = MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4833 055 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4834 056
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4835 057 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4836 058 c->sign = (c->used > 0) ? neg : MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4837 059 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4838 060 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4839 061 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4840 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4841 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4842
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4843 The implementation is rather simplistic and is not particularly noteworthy. Line 23 computes the sign of the result using the ``?''
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
4844 operator from the C programming language. Line 47 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4845
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4846 \section{Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4847 \label{sec:basesquare}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4848
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4849 Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4850 available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4851 performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4852 the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4853 $1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4854 and $3 \cdot 1 = 1 \cdot 3$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4855
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4856 For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4857 required for multiplication. The following diagram gives an example of the operations required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4858
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4859 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4860 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4861 \begin{tabular}{ccccc|c}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4862 &&1&2&3&\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4863 $\times$ &&1&2&3&\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4864 \hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4865 & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4866 $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4867 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4868 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4869 \caption{Squaring Optimization Diagram}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4870 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4871
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4872 Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4873 represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4874
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4875 The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4876 appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4877 products and at most one square (\textit{see the exercise section}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4878
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4879 The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4880 occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4881 Column two of row one is a square and column three is the first unique column.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4882
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4883 \subsection{The Baseline Squaring Algorithm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4884 The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4885 will not handle.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4886
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4887 \begin{figure}[!here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4888 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4889 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4890 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4891 \hline Algorithm \textbf{s\_mp\_sqr}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4892 \textbf{Input}. mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4893 \textbf{Output}. $b \leftarrow a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4894 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4895 1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4896 2. If step 1 failed return(\textit{MP\_MEM}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4897 3. $t.used \leftarrow 2 \cdot a.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4898 4. For $ix$ from 0 to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4899 \hspace{3mm}Calculate the square. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4900 \hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4901 \hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4902 \hspace{3mm}Calculate the double products after the square. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4903 \hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4904 \hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4905 \hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4906 \hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4907 \hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4908 \hspace{3mm}Set the last carry. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4909 \hspace{3mm}4.5 While $u > 0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4910 \hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4911 \hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4912 \hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4913 \hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4914 5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4915 6. Exchange $b$ and $t$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4916 7. Clear $t$ (\textit{mp\_clear}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4917 8. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4918 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4919 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4920 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4921 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4922 \caption{Algorithm s\_mp\_sqr}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4923 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4924
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4925 \textbf{Algorithm s\_mp\_sqr.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4926 This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4927 \cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4928 destination mp\_int to be the same as the source mp\_int.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4929
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4930 The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4931 the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4932 the carry and compute the double products.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4933
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4934 The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4935 very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4936 when it is multiplied by two, it can be properly represented by a mp\_word.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4937
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4938 Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4939 results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4940
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4941 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4942 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4943 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4944 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4945 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4946 017 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4947 018 int s_mp_sqr (mp_int * a, mp_int * b)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4948 019 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4949 020 mp_int t;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4950 021 int res, ix, iy, pa;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4951 022 mp_word r;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4952 023 mp_digit u, tmpx, *tmpt;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4953 024
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4954 025 pa = a->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4955 026 if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4956 027 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4957 028 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4958 029
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4959 030 /* default used is maximum possible size */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4960 031 t.used = 2*pa + 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4961 032
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4962 033 for (ix = 0; ix < pa; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4963 034 /* first calculate the digit at 2*ix */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4964 035 /* calculate double precision result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4965 036 r = ((mp_word) t.dp[2*ix]) +
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4966 037 ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4967 038
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4968 039 /* store lower part in result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4969 040 t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4970 041
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4971 042 /* get the carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4972 043 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4973 044
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4974 045 /* left hand side of A[ix] * A[iy] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4975 046 tmpx = a->dp[ix];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4976 047
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4977 048 /* alias for where to store the results */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4978 049 tmpt = t.dp + (2*ix + 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4979 050
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4980 051 for (iy = ix + 1; iy < pa; iy++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4981 052 /* first calculate the product */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4982 053 r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4983 054
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4984 055 /* now calculate the double precision result, note we use
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4985 056 * addition instead of *2 since it's easier to optimize
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4986 057 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4987 058 r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4988 059
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4989 060 /* store lower part */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4990 061 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4991 062
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4992 063 /* get carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4993 064 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4994 065 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4995 066 /* propagate upwards */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4996 067 while (u != ((mp_digit) 0)) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4997 068 r = ((mp_word) *tmpt) + ((mp_word) u);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4998 069 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
4999 070 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5000 071 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5001 072 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5002 073
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5003 074 mp_clamp (&t);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5004 075 mp_exch (&t, b);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5005 076 mp_clear (&t);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5006 077 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5007 078 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5008 079 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5009 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5010 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5011
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5012 Inside the outer loop (line 33) the square term is calculated on line 36. The carry (line 43) has been
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5013 extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5014 (lines 46 and 49) to simplify the inner loop. The doubling is performed using two
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5015 additions (line 58) since it is usually faster than shifting, if not at least as fast.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5016
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5017 The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5018 get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5019 square a number.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5020
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5021 \subsection{Faster Squaring by the ``Comba'' Method}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5022 A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5023 drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5024 performance hazards.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5026 The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5027 propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5028 that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5029 $ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5030
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5031 However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5032 mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5033 carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5035 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5036 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5037 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5038 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5039 \hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5040 \textbf{Input}. mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5041 \textbf{Output}. $b \leftarrow a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5042 \hline \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5043 Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5044 1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5045 2. If step 1 failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5046 \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5047 3. $pa \leftarrow 2 \cdot a.used$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5048 4. $\hat W1 \leftarrow 0$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5049 5. for $ix$ from $0$ to $pa - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5050 \hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5051 \hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5052 \hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5053 \hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5054 \hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5055 \hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5056 \hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5057 \hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5058 \hspace{3mm}5.8 if $ix$ is even then \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5059 \hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5060 \hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5061 \hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5062 \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5063 6. $oldused \leftarrow b.used$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5064 7. $b.used \leftarrow 2 \cdot a.used$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5065 8. for $ix$ from $0$ to $pa - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5066 \hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5067 9. for $ix$ from $pa$ to $oldused - 1$ do \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5068 \hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5069 10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5070 11. Return(\textit{MP\_OKAY}). \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5071 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5072 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5073 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5074 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5075 \caption{Algorithm fast\_s\_mp\_sqr}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5076 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5077
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5078 \textbf{Algorithm fast\_s\_mp\_sqr.}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5079 This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5080 s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5081 This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5082
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5083 First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5084 products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5085 addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5086 $a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5087 of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5088 fewer multiplications and the routine ends up being faster.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5089
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5090 Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5091 only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5092
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5093 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5094 \hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5095 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5096 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5097 016
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5098 017 /* the jist of squaring...
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5099 018 * you do like mult except the offset of the tmpx [one that
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5100 019 * starts closer to zero] can't equal the offset of tmpy.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5101 020 * So basically you set up iy like before then you min it with
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5102 021 * (ty-tx) so that it never happens. You double all those
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5103 022 * you add in the inner loop
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5104 023
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5105 024 After that loop you do the squares and add them in.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5106 025 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5107 026
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5108 027 int fast_s_mp_sqr (mp_int * a, mp_int * b)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5109 028 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5110 029 int olduse, res, pa, ix, iz;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5111 030 mp_digit W[MP_WARRAY], *tmpx;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5112 031 mp_word W1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5113 032
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5114 033 /* grow the destination as required */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5115 034 pa = a->used + a->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5116 035 if (b->alloc < pa) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5117 036 if ((res = mp_grow (b, pa)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5118 037 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5119 038 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5120 039 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5121 040
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5122 041 /* number of output digits to produce */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5123 042 W1 = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5124 043 for (ix = 0; ix < pa; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5125 044 int tx, ty, iy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5126 045 mp_word _W;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5127 046 mp_digit *tmpy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5128 047
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5129 048 /* clear counter */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5130 049 _W = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5131 050
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5132 051 /* get offsets into the two bignums */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5133 052 ty = MIN(a->used-1, ix);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5134 053 tx = ix - ty;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5135 054
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5136 055 /* setup temp aliases */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5137 056 tmpx = a->dp + tx;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5138 057 tmpy = a->dp + ty;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5139 058
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5140 059 /* this is the number of times the loop will iterrate, essentially
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5141 060 while (tx++ < a->used && ty-- >= 0) \{ ... \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5142 061 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5143 062 iy = MIN(a->used-tx, ty+1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5144 063
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5145 064 /* now for squaring tx can never equal ty
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5146 065 * we halve the distance since they approach at a rate of 2x
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5147 066 * and we have to round because odd cases need to be executed
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5148 067 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5149 068 iy = MIN(iy, (ty-tx+1)>>1);
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5150 069
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5151 070 /* execute loop */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5152 071 for (iz = 0; iz < iy; iz++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5153 072 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5154 073 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5155 074
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5156 075 /* double the inner product and add carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5157 076 _W = _W + _W + W1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5158 077
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5159 078 /* even columns have the square term in them */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5160 079 if ((ix&1) == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5161 080 _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5162 081 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5163 082
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5164 083 /* store it */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5165 084 W[ix] = (mp_digit)(_W & MP_MASK);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5166 085
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5167 086 /* make next carry */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5168 087 W1 = _W >> ((mp_word)DIGIT_BIT);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5169 088 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5170 089
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5171 090 /* setup dest */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5172 091 olduse = b->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5173 092 b->used = a->used+a->used;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5174 093
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5175 094 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5176 095 mp_digit *tmpb;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5177 096 tmpb = b->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5178 097 for (ix = 0; ix < pa; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5179 098 *tmpb++ = W[ix] & MP_MASK;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5180 099 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5181 100
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5182 101 /* clear unused digits [that existed in the old copy of c] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5183 102 for (; ix < olduse; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5184 103 *tmpb++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5185 104 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5186 105 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5187 106 mp_clamp (b);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5188 107 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5189 108 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5190 109 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5191 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5192 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5193
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5194 This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5195 the special case of squaring.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5196
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5197 \subsection{Polynomial Basis Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5198 The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5199 is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5200 multiplications to find the $\zeta$ relations, squaring operations are performed instead.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5201
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5202 \subsection{Karatsuba Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5203 Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5204 Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5205 number with the following equation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5206
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5207 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5208 h(x) = a^2x^2 + \left (a^2 + b^2 - (a - b)^2 \right )x + b^2
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5209 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5210
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5211 Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a - b)^2$. As in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5212 Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5213 $O \left ( n^{lg(3)} \right )$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5214
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5215 If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5216 instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5217 time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5218 point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5219
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5220 Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5221 The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5222 were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5223
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5224 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5225 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5226 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5227 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5228 \hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5229 \textbf{Input}. mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5230 \textbf{Output}. $b \leftarrow a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5231 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5232 1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5233 2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5234 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5235 Split the input. e.g. $a = x1\beta^B + x0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5236 3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5237 4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5238 5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5239 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5240 Calculate the three squares. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5241 6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5242 7. $x1x1 \leftarrow x1^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5243 8. $t1 \leftarrow x1 - x0$ (\textit{mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5244 9. $t1 \leftarrow t1^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5245 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5246 Compute the middle term. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5247 10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5248 11. $t1 \leftarrow t2 - t1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5249 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5250 Compute final product. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5251 12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5252 13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5253 14. $t1 \leftarrow t1 + x0x0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5254 15. $b \leftarrow t1 + x1x1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5255 16. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5256 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5257 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5258 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5259 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5260 \caption{Algorithm mp\_karatsuba\_sqr}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5261 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5262
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5263 \textbf{Algorithm mp\_karatsuba\_sqr.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5264 This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5265 multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5266
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5267 The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5268 placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5269 as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5270
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5271 By expanding $\left (x1 - x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $x1^2 + x0^2 - (x1 - x0)^2 = 2 \cdot x0 \cdot x1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5272 Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5273 this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5274
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5275 Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5276 machine clock cycles.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5277
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5278 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5279 5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5280 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5281
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5282 For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5283 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5284 \begin{tabular}{rcl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5285 ${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5286 ${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5287 ${13 \over 9}$ & $<$ & $n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5288 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5289 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5290
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5291 This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5292 where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5293 the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5294 ratio of 1:7. } than simpler operations such as addition.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5295
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5296 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5297 \hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5298 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5299 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5300 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5301 017 /* Karatsuba squaring, computes b = a*a using three
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5302 018 * half size squarings
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5303 019 *
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5304 020 * See comments of karatsuba_mul for details. It
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5305 021 * is essentially the same algorithm but merely
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5306 022 * tuned to perform recursive squarings.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5307 023 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5308 024 int mp_karatsuba_sqr (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5309 025 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5310 026 mp_int x0, x1, t1, t2, x0x0, x1x1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5311 027 int B, err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5312 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5313 029 err = MP_MEM;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5314 030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5315 031 /* min # of digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5316 032 B = a->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5317 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5318 034 /* now divide in two */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5319 035 B = B >> 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5320 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5321 037 /* init copy all the temps */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5322 038 if (mp_init_size (&x0, B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5323 039 goto ERR;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5324 040 if (mp_init_size (&x1, a->used - B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5325 041 goto X0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5326 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5327 043 /* init temps */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5328 044 if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5329 045 goto X1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5330 046 if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5331 047 goto T1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5332 048 if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5333 049 goto T2;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5334 050 if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5335 051 goto X0X0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5336 052
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5337 053 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5338 054 register int x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5339 055 register mp_digit *dst, *src;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5340 056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5341 057 src = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5342 058
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5343 059 /* now shift the digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5344 060 dst = x0.dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5345 061 for (x = 0; x < B; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5346 062 *dst++ = *src++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5347 063 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5348 064
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5349 065 dst = x1.dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5350 066 for (x = B; x < a->used; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5351 067 *dst++ = *src++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5352 068 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5353 069 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5354 070
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5355 071 x0.used = B;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5356 072 x1.used = a->used - B;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5357 073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5358 074 mp_clamp (&x0);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5359 075
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5360 076 /* now calc the products x0*x0 and x1*x1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5361 077 if (mp_sqr (&x0, &x0x0) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5362 078 goto X1X1; /* x0x0 = x0*x0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5363 079 if (mp_sqr (&x1, &x1x1) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5364 080 goto X1X1; /* x1x1 = x1*x1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5365 081
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5366 082 /* now calc (x1-x0)**2 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5367 083 if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5368 084 goto X1X1; /* t1 = x1 - x0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5369 085 if (mp_sqr (&t1, &t1) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5370 086 goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5371 087
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5372 088 /* add x0y0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5373 089 if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5374 090 goto X1X1; /* t2 = x0x0 + x1x1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5375 091 if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5376 092 goto X1X1; /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5377 093
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5378 094 /* shift by B */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5379 095 if (mp_lshd (&t1, B) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5380 096 goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5381 097 if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5382 098 goto X1X1; /* x1x1 = x1x1 << 2*B */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5383 099
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5384 100 if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5385 101 goto X1X1; /* t1 = x0x0 + t1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5386 102 if (mp_add (&t1, &x1x1, b) != MP_OKAY)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5387 103 goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5388 104
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5389 105 err = MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5390 106
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5391 107 X1X1:mp_clear (&x1x1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5392 108 X0X0:mp_clear (&x0x0);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5393 109 T2:mp_clear (&t2);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5394 110 T1:mp_clear (&t1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5395 111 X1:mp_clear (&x1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5396 112 X0:mp_clear (&x0);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5397 113 ERR:
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5398 114 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5399 115 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5400 116 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5401 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5402 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5403
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5404 This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5405 shift the input into the two halves. The loop from line 53 to line 69 has been modified since only one input exists. The \textbf{used}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5406 count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5407 to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5408
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5409 By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5410 is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5411 it is actually below the Comba limit (\textit{at 110 digits}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5412
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5413 This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5414 redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5415 mp\_clears are executed normally.
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5416
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5417 \subsection{Toom-Cook Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5418 The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5419 instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5420 derive their own Toom-Cook squaring algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5421
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5422 \subsection{High Level Squaring}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5423 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5424 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5425 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5426 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5427 \hline Algorithm \textbf{mp\_sqr}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5428 \textbf{Input}. mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5429 \textbf{Output}. $b \leftarrow a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5430 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5431 1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5432 \hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5433 2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5434 \hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5435 3. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5436 \hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5437 \hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5438 \hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5439 \hspace{3mm}3.3 else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5440 \hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5441 4. $b.sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5442 5. Return the result of the unsigned squaring performed. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5443 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5444 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5445 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5446 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5447 \caption{Algorithm mp\_sqr}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5448 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5449
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5450 \textbf{Algorithm mp\_sqr.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5451 This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5452 \textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5453 neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5454
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5455 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5456 \hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5457 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5458 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5459 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5460 017 /* computes b = a*a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5461 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5462 019 mp_sqr (mp_int * a, mp_int * b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5463 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5464 021 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5465 022
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5466 023 #ifdef BN_MP_TOOM_SQR_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5467 024 /* use Toom-Cook? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5468 025 if (a->used >= TOOM_SQR_CUTOFF) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5469 026 res = mp_toom_sqr(a, b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5470 027 /* Karatsuba? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5471 028 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5472 029 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5473 030 #ifdef BN_MP_KARATSUBA_SQR_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5474 031 if (a->used >= KARATSUBA_SQR_CUTOFF) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5475 032 res = mp_karatsuba_sqr (a, b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5476 033 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5477 034 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5478 035 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5479 036 #ifdef BN_FAST_S_MP_SQR_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5480 037 /* can we use the fast comba multiplier? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5481 038 if ((a->used * 2 + 1) < MP_WARRAY &&
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5482 039 a->used <
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5483 040 (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5484 041 res = fast_s_mp_sqr (a, b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5485 042 \} else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5486 043 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5487 044 #ifdef BN_S_MP_SQR_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5488 045 res = s_mp_sqr (a, b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5489 046 #else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5490 047 res = MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5491 048 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5492 049 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5493 050 b->sign = MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5494 051 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5495 052 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5496 053 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5497 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5498 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5499
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5500 \section*{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5501 \begin{tabular}{cl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5502 $\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5503 & that have different number of digits in Karatsuba multiplication. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5504 & \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5505 $\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5506 & of double products and at most one square is stated. Prove this statement. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5507 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5508 $\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5509 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5510 $\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5511 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5512 $\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5513 & required for equation $6.7$ to be true. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5514 & \\
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5515 $\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5516 & compute subsets of the columns in each thread. Determine a cutoff point where \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5517 & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5518 &\\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5519 $\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5520 & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5521 & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5522 & \\
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5523 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5524
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5525 \chapter{Modular Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5526 \section{Basics of Modular Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5527 \index{modular residue}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5528 Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5529 such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5530 modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5531 in~\ref{sec:division}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5532
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5533 Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5534 $r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5535 ``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5536 other forms of residues.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5537
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5538 Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5539 is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5540 RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5541 elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5542 exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5543 range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5544 algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5545
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5546 \section{The Barrett Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5547 The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5548 division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5549
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5550 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5551 c = a - b \cdot \lfloor a/b \rfloor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5552 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5553
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5554 Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5555 targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5556 DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5557 It would take another common optimization to optimize the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5558
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5559 \subsection{Fixed Point Arithmetic}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5560 The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5561 point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5562 fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5563 integer and a $q$-bit fraction part (\textit{where $p+q = k$}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5564
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5565 In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5566 value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5567 moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5568 to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5569 fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5570
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5571 This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5572 of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5573 equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5574 $a$ by another integer $b$ can be achieved with the following expression.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5575
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5576 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5577 \lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5578 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5579
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5580 The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5581 modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5582 are considerably faster than division on most processors.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5583
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5584 Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5585 leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5586 the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5587 larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5588 to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5589
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5590 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5591 c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5592 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5593
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5594 Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5595 variable also helps re-inforce the idea that it is meant to be computed once and re-used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5596
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5597 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5598 c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5599 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5600
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5601 Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5602 reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5603 precision.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5604
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5605 Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5606 another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5607 reduce the number.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5608
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5609 For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5610 $a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5611 By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5612
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5613 \subsection{Choosing a Radix Point}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5614 Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5615 that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5616 See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5617 the initial multiplication that finds the quotient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5618
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5619 Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5620 the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5621 two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5622 $m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5623 express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5624 ${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5625 is bound by $0 \le {a' \over b} < 1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5626
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5627 Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5628 ``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5629 with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5630
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5631 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5632 c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5633 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5634
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5635 Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5636 exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5637 would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5638 $\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5639 by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5640 can be off by an additional value of one for a total of at most two. This implies that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5641 $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5642 $b$ once or twice the residue is found.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5643
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5644 The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5645 precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5646 This is considerably faster than the original attempt.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5647
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5648 For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5649 represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5650 With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5651 $\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5652 is found.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5653
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5654 \subsection{Trimming the Quotient}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5655 So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5656 it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5657 optimization.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5658
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5659 After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5660 half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5661 multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5662 In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5663
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5664 The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5665 multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5666 of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5667
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5668 \subsection{Trimming the Residue}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5669 After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5670 multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5671 result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5672 implicitly zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5673
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5674 The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5675 $O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5676 be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5677 only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5678
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5679 With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5680 is considerably faster than the straightforward $3m^2$ method.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5681
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5682 \subsection{The Barrett Algorithm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5683 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5684 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5685 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5686 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5687 \hline Algorithm \textbf{mp\_reduce}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5688 \textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5689 \textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5690 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5691 Let $m$ represent the number of digits in $b$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5692 1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5693 2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5694 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5695 Produce the quotient. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5696 3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5697 4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5698 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5699 Subtract the multiple of modulus from the input. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5700 5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5701 6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5702 7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5703 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5704 Add $\beta^{m+1}$ if a carry occured. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5705 8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5706 \hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5707 \hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5708 \hspace{3mm}8.3 $a \leftarrow a + q$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5709 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5710 Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5711 9. While $a \ge b$ do (\textit{mp\_cmp}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5712 \hspace{3mm}9.1 $c \leftarrow a - b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5713 10. Clear $q$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5714 11. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5715 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5716 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5717 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5718 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5719 \caption{Algorithm mp\_reduce}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5720 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5721
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5722 \textbf{Algorithm mp\_reduce.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5723 This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5724 \cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5725 be adhered to for the algorithm to work.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5726
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5727 First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5728 a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5729 for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5730 Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5731 algorithm and is assumed to be calculated and stored before the algorithm is used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5732
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5733 Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5734 $s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5735 instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5736 of digits in $b$ is very much smaller than $\beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5737
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5738 While it is known that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5739 $a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5740 ``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5741 fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5742
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5743 The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5744 performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5745
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5746 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5747 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5748 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5749 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5750 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5751 017 /* reduces x mod m, assumes 0 < x < m**2, mu is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5752 018 * precomputed via mp_reduce_setup.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5753 019 * From HAC pp.604 Algorithm 14.42
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5754 020 */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5755 021 int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5756 022 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5757 023 mp_int q;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5758 024 int res, um = m->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5759 025
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5760 026 /* q = x */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5761 027 if ((res = mp_init_copy (&q, x)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5762 028 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5763 029 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5764 030
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5765 031 /* q1 = x / b**(k-1) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5766 032 mp_rshd (&q, um - 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5767 033
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5768 034 /* according to HAC this optimization is ok */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5769 035 if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5770 036 if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5771 037 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5772 038 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5773 039 \} else \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5774 040 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5775 041 if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5776 042 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5777 043 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5778 044 #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5779 045 if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5780 046 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5781 047 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5782 048 #else
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5783 049 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5784 050 res = MP_VAL;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5785 051 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5786 052 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5787 053 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5788 054 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5789 055
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5790 056 /* q3 = q2 / b**(k+1) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5791 057 mp_rshd (&q, um + 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5792 058
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5793 059 /* x = x mod b**(k+1), quick (no division) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5794 060 if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5795 061 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5796 062 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5797 063
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5798 064 /* q = q * m mod b**(k+1), quick (no division) */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5799 065 if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5800 066 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5801 067 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5802 068
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5803 069 /* x = x - q */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5804 070 if ((res = mp_sub (x, &q, x)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5805 071 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5806 072 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5807 073
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5808 074 /* If x < 0, add b**(k+1) to it */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5809 075 if (mp_cmp_d (x, 0) == MP_LT) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5810 076 mp_set (&q, 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5811 077 if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5812 078 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5813 079 if ((res = mp_add (x, &q, x)) != MP_OKAY)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5814 080 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5815 081 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5816 082
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5817 083 /* Back off if it's too big */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5818 084 while (mp_cmp (x, m) != MP_LT) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5819 085 if ((res = s_mp_sub (x, m, x)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5820 086 goto CLEANUP;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5821 087 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5822 088 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5823 089
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5824 090 CLEANUP:
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5825 091 mp_clear (&q);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5826 092
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5827 093 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5828 094 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5829 095 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5830 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5831 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5832
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5833 The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5834 the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5835 in the modulus. In the source code this is evaluated on lines 36 to 43 where algorithm s\_mp\_mul\_high\_digs is used when it is
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5836 safe to do so.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5837
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5838 \subsection{The Barrett Setup Algorithm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5839 In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5840 future use so that the Barrett algorithm can be used without delay.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5841
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
5842 \newpage\begin{figure}[!here]
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5843 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5844 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5845 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5846 \hline Algorithm \textbf{mp\_reduce\_setup}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5847 \textbf{Input}. mp\_int $a$ ($a > 1$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5848 \textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5849 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5850 1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5851 2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5852 3. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5853 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5854 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5855 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5856 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5857 \caption{Algorithm mp\_reduce\_setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5858 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5859
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5860 \textbf{Algorithm mp\_reduce\_setup.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5861 This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5862 is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5863
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5864 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5865 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5866 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5867 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5868 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5869 017 /* pre-calculate the value required for Barrett reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5870 018 * For a given modulus "b" it calulates the value required in "a"
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5871 019 */
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5872 020 int mp_reduce_setup (mp_int * a, mp_int * b)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5873 021 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5874 022 int res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5875 023
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5876 024 if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5877 025 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5878 026 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5879 027 return mp_div (a, b, a, NULL);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5880 028 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
5881 029 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5882 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5883 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5884
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5885 This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5886 which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5887 remainder to be passed as NULL meaning to ignore the value.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5888
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5889 \section{The Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5890 Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5891 form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5892 residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5893
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5894 Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5895 $n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5896 is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5897
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5898 \textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5899 to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5900
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5901 \textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5902 this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5903 multiplication by $k^{-1}$ modulo $n$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5904
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5905 From these two simple facts the following simple algorithm can be derived.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5906
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5907 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5908 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5909 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5910 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5911 \hline Algorithm \textbf{Montgomery Reduction}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5912 \textbf{Input}. Integer $x$, $n$ and $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5913 \textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5914 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5915 1. for $t$ from $1$ to $k$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5916 \hspace{3mm}1.1 If $x$ is odd then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5917 \hspace{6mm}1.1.1 $x \leftarrow x + n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5918 \hspace{3mm}1.2 $x \leftarrow x/2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5919 2. Return $x$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5920 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5921 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5922 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5923 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5924 \caption{Algorithm Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5925 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5926
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5927 The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5928 added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5929 $x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5930 final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5931 $0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5932
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5933 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5934 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5935 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5936 \begin{tabular}{|c|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5937 \hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5938 \hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5939 \hline $2$ & $x/2 = 1453$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5940 \hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5941 \hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5942 \hline $5$ & $x/2 = 278$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5943 \hline $6$ & $x/2 = 139$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5944 \hline $7$ & $x + n = 396$, $x/2 = 198$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5945 \hline $8$ & $x/2 = 99$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5946 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5947 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5948 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5949 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5950 \caption{Example of Montgomery Reduction (I)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5951 \label{fig:MONT1}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5952 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5953
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5954 Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 8$. The result of the algorithm $r = 99$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5955 congruent to the value of $2^{-8} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^8$ modulo $257$ the correct residue
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5956 $r \equiv 158$ is produced.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5957
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5958 Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5959 and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5960 Fortunately there exists an alternative representation of the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5961
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5962 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5963 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5964 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5965 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5966 \hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5967 \textbf{Input}. Integer $x$, $n$ and $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5968 \textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5969 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5970 1. for $t$ from $0$ to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5971 \hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5972 \hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5973 2. Return $x/2^k$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5974 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5975 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5976 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5977 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5978 \caption{Algorithm Montgomery Reduction (modified I)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5979 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5980
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5981 This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5982 precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5983
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5984 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5985 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5986 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5987 \begin{tabular}{|c|l|r|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5988 \hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5989 \hline -- & $5555$ & $1010110110011$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5990 \hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5991 \hline $2$ & $5812$ & $1011010110100$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5992 \hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5993 \hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5994 \hline $5$ & $8896$ & $10001011000000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5995 \hline $6$ & $8896$ & $10001011000000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5996 \hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5997 \hline $8$ & $25344$ & $110001100000000$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5998 \hline -- & $x/2^k = 99$ & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5999 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6000 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6001 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6002 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6003 \caption{Example of Montgomery Reduction (II)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6004 \label{fig:MONT2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6005 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6006
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6007 Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 8$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6008 With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6009 loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6010 zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6011
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6012 \subsection{Digit Based Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6013 Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6014 previous algorithm re-written to compute the Montgomery reduction in this new fashion.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6015
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6016 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6017 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6018 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6019 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6020 \hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6021 \textbf{Input}. Integer $x$, $n$ and $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6022 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6023 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6024 1. for $t$ from $0$ to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6025 \hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6026 2. Return $x/\beta^k$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6027 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6028 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6029 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6030 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6031 \caption{Algorithm Montgomery Reduction (modified II)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6032 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6034 The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6035 the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6036 problem breaks down to solving the following congruency.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6038 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6039 \begin{tabular}{rcl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6040 $x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6041 $\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6042 $\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6043 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6044 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6046 In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6047 extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6049 For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6050 represent the value to reduce.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6052 \newpage\begin{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6053 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6054 \begin{tabular}{|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6055 \hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6056 \hline -- & $33$ & --\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6057 \hline $0$ & $33 + \mu n = 50$ & $1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6058 \hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6059 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6060 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6061 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6062 \caption{Example of Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6063 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6064
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6065 The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6066 which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6067 the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6068 the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6069
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6070 \subsection{Baseline Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6071 The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6072 Montgomery reductions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6074 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6075 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6076 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6077 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6078 \hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6079 \textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6080 \hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6081 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6082 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6083 1. $digs \leftarrow 2n.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6084 2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6085 \hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6086 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6087 Setup $x$ for the reduction. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6088 3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6089 4. $x.used \leftarrow digs$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6090 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6091 Eliminate the lower $k$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6092 5. For $ix$ from $0$ to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6093 \hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6094 \hspace{3mm}5.2 $u \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6095 \hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6096 \hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6097 \hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6098 \hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6099 \hspace{3mm}5.4 While $u > 0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6100 \hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6101 \hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6102 \hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6103 \hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6104 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6105 Divide by $\beta^k$ and fix up as required. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6106 6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6107 7. If $x \ge n$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6108 \hspace{3mm}7.1 $x \leftarrow x - n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6109 8. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6110 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6111 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6112 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6113 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6114 \caption{Algorithm mp\_montgomery\_reduce}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6115 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6116
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6117 \textbf{Algorithm mp\_montgomery\_reduce.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6118 This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6119 on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6120 restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6121 for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6122 advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6123
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6124 Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6125 the size of the input. This algorithm is discussed in sub-section 6.3.3.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6126
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6127 Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6128 calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6129 multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6130
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6131 Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6132 in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6133 multiplications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6134
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6135 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6136 \hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6137 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6138 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6139 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6140 017 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6141 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6142 019 mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6143 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6144 021 int ix, res, digs;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6145 022 mp_digit mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6146 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6147 024 /* can the fast reduction [comba] method be used?
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6148 025 *
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6149 026 * Note that unlike in mul you're safely allowed *less*
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6150 027 * than the available columns [255 per default] since carries
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6151 028 * are fixed up in the inner loop.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6152 029 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6153 030 digs = n->used * 2 + 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6154 031 if ((digs < MP_WARRAY) &&
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6155 032 n->used <
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6156 033 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6157 034 return fast_mp_montgomery_reduce (x, n, rho);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6158 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6159 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6160 037 /* grow the input as required */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6161 038 if (x->alloc < digs) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6162 039 if ((res = mp_grow (x, digs)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6163 040 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6164 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6165 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6166 043 x->used = digs;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6167 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6168 045 for (ix = 0; ix < n->used; ix++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6169 046 /* mu = ai * rho mod b
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6170 047 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6171 048 * The value of rho must be precalculated via
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6172 049 * montgomery_setup() such that
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6173 050 * it equals -1/n0 mod b this allows the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6174 051 * following inner loop to reduce the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6175 052 * input one digit at a time
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6176 053 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6177 054 mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6178 055
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6179 056 /* a = a + mu * m * b**i */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6180 057 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6181 058 register int iy;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6182 059 register mp_digit *tmpn, *tmpx, u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6183 060 register mp_word r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6184 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6185 062 /* alias for digits of the modulus */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6186 063 tmpn = n->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6187 064
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6188 065 /* alias for the digits of x [the input] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6189 066 tmpx = x->dp + ix;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6190 067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6191 068 /* set the carry to zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6192 069 u = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6193 070
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6194 071 /* Multiply and add in place */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6195 072 for (iy = 0; iy < n->used; iy++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6196 073 /* compute product and sum */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6197 074 r = ((mp_word)mu) * ((mp_word)*tmpn++) +
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6198 075 ((mp_word) u) + ((mp_word) * tmpx);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6199 076
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6200 077 /* get carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6201 078 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6202 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6203 080 /* fix digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6204 081 *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6205 082 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6206 083 /* At this point the ix'th digit of x should be zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6207 084
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6208 085
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6209 086 /* propagate carries upwards as required*/
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6210 087 while (u) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6211 088 *tmpx += u;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6212 089 u = *tmpx >> DIGIT_BIT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6213 090 *tmpx++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6214 091 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6215 092 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6216 093 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6217 094
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6218 095 /* at this point the n.used'th least
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6219 096 * significant digits of x are all zero
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6220 097 * which means we can shift x to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6221 098 * right by n.used digits and the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6222 099 * residue is unchanged.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6223 100 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6224 101
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6225 102 /* x = x/b**n.used */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6226 103 mp_clamp(x);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6227 104 mp_rshd (x, n->used);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6228 105
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6229 106 /* if x >= n then x = x - n */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6230 107 if (mp_cmp_mag (x, n) != MP_LT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6231 108 return s_mp_sub (x, n, x);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6232 109 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6233 110
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6234 111 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6235 112 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6236 113 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6237 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6238 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6239
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6240 This is the baseline implementation of the Montgomery reduction algorithm. Lines 30 to 35 determine if the Comba based
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6241 routine can be used instead. Line 48 computes the value of $\mu$ for that particular iteration of the outer loop.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6242
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6243 The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6244 the alias $tmpn$ refers to the modulus $n$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6245
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6246 \subsection{Faster ``Comba'' Montgomery Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6247
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6248 The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6249 nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6250 technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6251 a $k \times 1$ product $k$ times.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6252
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6253 The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6254 carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6255 Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6256
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6257 With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6258 the speed of the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6259
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6260 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6261 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6262 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6263 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6264 \hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6265 \textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6266 \hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6267 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6268 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6269 Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6270 1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6271 Copy the digits of $x$ into the array $\hat W$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6272 2. For $ix$ from $0$ to $x.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6273 \hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6274 3. For $ix$ from $x.used$ to $2n.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6275 \hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6276 Elimiate the lower $k$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6277 4. for $ix$ from $0$ to $n.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6278 \hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6279 \hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6280 \hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6281 \hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6282 Propagate carries upwards. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6283 5. for $ix$ from $n.used$ to $2n.used + 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6284 \hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6285 Shift right and reduce modulo $\beta$ simultaneously. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6286 6. for $ix$ from $0$ to $n.used + 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6287 \hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6288 Zero excess digits and fixup $x$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6289 7. if $x.used > n.used + 1$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6290 \hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6291 \hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6292 8. $x.used \leftarrow n.used + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6293 9. Clamp excessive digits of $x$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6294 10. If $x \ge n$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6295 \hspace{3mm}10.1 $x \leftarrow x - n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6296 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6297 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6298 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6299 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6300 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6301 \caption{Algorithm fast\_mp\_montgomery\_reduce}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6302 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6303
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6304 \textbf{Algorithm fast\_mp\_montgomery\_reduce.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6305 This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6306 faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6307 on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6308 the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6309 a modulus of at most $3,556$ bits in length.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6310
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6311 As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6312 contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6313 4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6314 as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6315 a single precision multiplication instead half the amount of time is spent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6316
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6317 Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6318 4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6319 how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6320 point.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6321
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6322 Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6323 stored in the destination $x$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6324
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6325 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6326 \hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6327 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6328 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6329 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6330 017 /* computes xR**-1 == x (mod N) via Montgomery Reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6331 018 *
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6332 019 * This is an optimized implementation of montgomery_reduce
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6333 020 * which uses the comba method to quickly calculate the columns of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6334 021 * reduction.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6335 022 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6336 023 * Based on Algorithm 14.32 on pp.601 of HAC.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6337 024 */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6338 025 int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6339 026 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6340 027 int ix, res, olduse;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6341 028 mp_word W[MP_WARRAY];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6342 029
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6343 030 /* get old used count */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6344 031 olduse = x->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6345 032
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6346 033 /* grow a as required */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6347 034 if (x->alloc < n->used + 1) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6348 035 if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6349 036 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6350 037 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6351 038 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6352 039
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6353 040 /* first we have to get the digits of the input into
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6354 041 * an array of double precision words W[...]
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6355 042 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6356 043 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6357 044 register mp_word *_W;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6358 045 register mp_digit *tmpx;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6359 046
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6360 047 /* alias for the W[] array */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6361 048 _W = W;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6362 049
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6363 050 /* alias for the digits of x*/
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6364 051 tmpx = x->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6365 052
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6366 053 /* copy the digits of a into W[0..a->used-1] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6367 054 for (ix = 0; ix < x->used; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6368 055 *_W++ = *tmpx++;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6369 056 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6370 057
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6371 058 /* zero the high words of W[a->used..m->used*2] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6372 059 for (; ix < n->used * 2 + 1; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6373 060 *_W++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6374 061 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6375 062 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6376 063
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6377 064 /* now we proceed to zero successive digits
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6378 065 * from the least significant upwards
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6379 066 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6380 067 for (ix = 0; ix < n->used; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6381 068 /* mu = ai * m' mod b
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6382 069 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6383 070 * We avoid a double precision multiplication (which isn't required)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6384 071 * by casting the value down to a mp_digit. Note this requires
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6385 072 * that W[ix-1] have the carry cleared (see after the inner loop)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6386 073 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6387 074 register mp_digit mu;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6388 075 mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6389 076
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6390 077 /* a = a + mu * m * b**i
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6391 078 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6392 079 * This is computed in place and on the fly. The multiplication
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6393 080 * by b**i is handled by offseting which columns the results
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6394 081 * are added to.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6395 082 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6396 083 * Note the comba method normally doesn't handle carries in the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6397 084 * inner loop In this case we fix the carry from the previous
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6398 085 * column since the Montgomery reduction requires digits of the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6399 086 * result (so far) [see above] to work. This is
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6400 087 * handled by fixing up one carry after the inner loop. The
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6401 088 * carry fixups are done in order so after these loops the
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6402 089 * first m->used words of W[] have the carries fixed
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6403 090 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6404 091 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6405 092 register int iy;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6406 093 register mp_digit *tmpn;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6407 094 register mp_word *_W;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6408 095
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6409 096 /* alias for the digits of the modulus */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6410 097 tmpn = n->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6411 098
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6412 099 /* Alias for the columns set by an offset of ix */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6413 100 _W = W + ix;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6414 101
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6415 102 /* inner loop */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6416 103 for (iy = 0; iy < n->used; iy++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6417 104 *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6418 105 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6419 106 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6420 107
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6421 108 /* now fix carry for next digit, W[ix+1] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6422 109 W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6423 110 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6424 111
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6425 112 /* now we have to propagate the carries and
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6426 113 * shift the words downward [all those least
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6427 114 * significant digits we zeroed].
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6428 115 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6429 116 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6430 117 register mp_digit *tmpx;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6431 118 register mp_word *_W, *_W1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6432 119
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6433 120 /* nox fix rest of carries */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6434 121
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6435 122 /* alias for current word */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6436 123 _W1 = W + ix;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6437 124
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6438 125 /* alias for next word, where the carry goes */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6439 126 _W = W + ++ix;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6440 127
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6441 128 for (; ix <= n->used * 2 + 1; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6442 129 *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6443 130 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6444 131
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6445 132 /* copy out, A = A/b**n
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6446 133 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6447 134 * The result is A/b**n but instead of converting from an
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6448 135 * array of mp_word to mp_digit than calling mp_rshd
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6449 136 * we just copy them in the right order
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6450 137 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6451 138
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6452 139 /* alias for destination word */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6453 140 tmpx = x->dp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6454 141
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6455 142 /* alias for shifted double precision result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6456 143 _W = W + n->used;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6457 144
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6458 145 for (ix = 0; ix < n->used + 1; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6459 146 *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6460 147 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6461 148
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6462 149 /* zero oldused digits, if the input a was larger than
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6463 150 * m->used+1 we'll have to clear the digits
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6464 151 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6465 152 for (; ix < olduse; ix++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6466 153 *tmpx++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6467 154 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6468 155 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6469 156
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6470 157 /* set the max used and clamp */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6471 158 x->used = n->used + 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6472 159 mp_clamp (x);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6473 160
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6474 161 /* if A >= m then A = A - m */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6475 162 if (mp_cmp_mag (x, n) != MP_LT) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6476 163 return s_mp_sub (x, n, x);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6477 164 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6478 165 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6479 166 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6480 167 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6481 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6482 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6483
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6484 The $\hat W$ array is first filled with digits of $x$ on line 50 then the rest of the digits are zeroed on line 54. Both loops share
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6485 the same alias variables to make the code easier to read.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6486
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6487 The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6488 forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line 109 fixes the carry
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6489 for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6490
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6491 The for loop on line 108 propagates the rest of the carries upwards through the columns. The for loop on line 125 reduces the columns
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6492 modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6493 digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6494
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6495 \subsection{Montgomery Setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6496 To calculate the variable $\rho$ a relatively simple algorithm will be required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6497
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6498 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6499 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6500 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6501 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6502 \hline Algorithm \textbf{mp\_montgomery\_setup}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6503 \textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6504 \textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6505 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6506 1. $b \leftarrow n_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6507 2. If $b$ is even return(\textit{MP\_VAL}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6508 3. $x \leftarrow ((b + 2) \mbox{ AND } 4) << 1) + b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6509 4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6510 \hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6511 5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6512 6. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6513 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6514 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6515 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6516 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6517 \caption{Algorithm mp\_montgomery\_setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6518 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6519
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6520 \textbf{Algorithm mp\_montgomery\_setup.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6521 This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6522 to calculate $1/n_0$ when $\beta$ is a power of two.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6523
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6524 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6525 \hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6526 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6527 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6528 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6529 017 /* setups the montgomery reduction stuff */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6530 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6531 019 mp_montgomery_setup (mp_int * n, mp_digit * rho)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6532 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6533 021 mp_digit x, b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6534 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6535 023 /* fast inversion mod 2**k
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6536 024 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6537 025 * Based on the fact that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6538 026 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6539 027 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6540 028 * => 2*X*A - X*X*A*A = 1
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6541 029 * => 2*(1) - (1) = 1
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6542 030 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6543 031 b = n->dp[0];
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6544 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6545 033 if ((b & 1) == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6546 034 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6547 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6548 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6549 037 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6550 038 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6551 039 #if !defined(MP_8BIT)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6552 040 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6553 041 #endif
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6554 042 #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6555 043 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6556 044 #endif
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6557 045 #ifdef MP_64BIT
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6558 046 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6559 047 #endif
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6560 048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6561 049 /* rho = -1/m mod b */
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6562 050 *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6563 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6564 052 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6565 053 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6566 054 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6567 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6568 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6569
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6570 This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6571 multiplications when $\beta$ is not the default 28-bits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6572
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6573 \section{The Diminished Radix Algorithm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6574 The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6575 or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6576
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6577 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6578 (x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6579 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6580
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6581 This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6582 then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6583 of the above equation is very simple. First write $x$ in the product form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6584
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6585 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6586 x = qn + r
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6587 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6588
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6589 Now reduce both sides modulo $(n - k)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6590
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6591 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6592 x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6593 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6594
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6595 The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6596 into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6597
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6598 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6599 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6600 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6601 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6602 \hline Algorithm \textbf{Diminished Radix Reduction}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6603 \textbf{Input}. Integer $x$, $n$, $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6604 \textbf{Output}. $x \mbox{ mod } (n - k)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6605 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6606 1. $q \leftarrow \lfloor x / n \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6607 2. $q \leftarrow k \cdot q$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6608 3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6609 4. $x \leftarrow x + q$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6610 5. If $x \ge (n - k)$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6611 \hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6612 \hspace{3mm}5.2 Goto step 1. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6613 6. Return $x$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6614 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6615 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6616 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6617 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6618 \caption{Algorithm Diminished Radix Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6619 \label{fig:DR}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6620 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6621
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6622 This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6623 once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6624
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6625 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6626 0 \le x < n^2 + k^2 - 2nk
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6627 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6628
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6629 The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6630
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6631 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6632 q < n - 2k - k^2/n
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6633 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6634
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6635 Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6636 $0 \le x < n$. By step four the sum $x + q$ is bounded by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6637
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6638 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6639 0 \le q + x < (k + 1)n - 2k^2 - 1
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6640 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6641
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6642 With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6643 sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6644 range $0 \le x < (n - k - 1)^2$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6645
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6646 \begin{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6647 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6648 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6649 \begin{tabular}{|l|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6650 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6651 $x = 123456789, n = 256, k = 3$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6652 \hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6653 $q \leftarrow q*k = 1446759$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6654 $x \leftarrow x \mbox{ mod } n = 21$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6655 $x \leftarrow x + q = 1446780$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6656 $x \leftarrow x - (n - k) = 1446527$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6657 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6658 $q \leftarrow \lfloor x/n \rfloor = 5650$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6659 $q \leftarrow q*k = 16950$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6660 $x \leftarrow x \mbox{ mod } n = 127$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6661 $x \leftarrow x + q = 17077$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6662 $x \leftarrow x - (n - k) = 16824$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6663 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6664 $q \leftarrow \lfloor x/n \rfloor = 65$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6665 $q \leftarrow q*k = 195$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6666 $x \leftarrow x \mbox{ mod } n = 184$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6667 $x \leftarrow x + q = 379$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6668 $x \leftarrow x - (n - k) = 126$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6669 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6670 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6671 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6672 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6673 \caption{Example Diminished Radix Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6674 \label{fig:EXDR}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6675 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6676
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6677 Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6678 is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6679 three passes were required to find the residue $x \equiv 126$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6680
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6681
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6682 \subsection{Choice of Moduli}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6683 On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6684 modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6685
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6686 Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6687 Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6688 by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6689 which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6690
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6691 However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6692 performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6693 Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6694
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6695 Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6696 modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6697 $2^p$ logic except $p$ must be a multiple of $lg(\beta)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6698
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6699 \subsection{Choice of $k$}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6700 Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6701 in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6702 as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6703
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6704 \subsection{Restricted Diminished Radix Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6705 The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6706 an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6707 of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6708 of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6709 exponentiations are performed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6710
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6711 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6712 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6713 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6714 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6715 \hline Algorithm \textbf{mp\_dr\_reduce}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6716 \textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6717 \hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6718 \textbf{Output}. $x \mbox{ mod } n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6719 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6720 1. $m \leftarrow n.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6721 2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6722 3. $\mu \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6723 4. for $i$ from $0$ to $m - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6724 \hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6725 \hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6726 \hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6727 5. $x_{m} \leftarrow \mu$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6728 6. for $i$ from $m + 1$ to $x.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6729 \hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6730 7. Clamp excess digits of $x$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6731 8. If $x \ge n$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6732 \hspace{3mm}8.1 $x \leftarrow x - n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6733 \hspace{3mm}8.2 Goto step 3. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6734 9. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6735 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6736 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6737 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6738 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6739 \caption{Algorithm mp\_dr\_reduce}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6740 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6741
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6742 \textbf{Algorithm mp\_dr\_reduce.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6743 This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6744 with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6745
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6746 This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6747 and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6748 the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6749 digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6750 $x$ before the addition of the multiple of the upper half.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6751
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6752 At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6753 at step 3.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6754
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6755 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6756 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6757 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6758 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6759 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6760 017 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6761 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6762 019 * Based on algorithm from the paper
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6763 020 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6764 021 * "Generating Efficient Primes for Discrete Log Cryptosystems"
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6765 022 * Chae Hoon Lim, Pil Joong Lee,
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6766 023 * POSTECH Information Research Laboratories
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6767 024 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6768 025 * The modulus must be of a special format [see manual]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6769 026 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6770 027 * Has been modified to use algorithm 7.10 from the LTM book instead
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6771 028 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6772 029 * Input x must be in the range 0 <= x <= (n-1)**2
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6773 030 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6774 031 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6775 032 mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6776 033 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6777 034 int err, i, m;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6778 035 mp_word r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6779 036 mp_digit mu, *tmpx1, *tmpx2;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6780 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6781 038 /* m = digits in modulus */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6782 039 m = n->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6783 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6784 041 /* ensure that "x" has at least 2m digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6785 042 if (x->alloc < m + m) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6786 043 if ((err = mp_grow (x, m + m)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6787 044 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6788 045 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6789 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6790 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6791 048 /* top of loop, this is where the code resumes if
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6792 049 * another reduction pass is required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6793 050 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6794 051 top:
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6795 052 /* aliases for digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6796 053 /* alias for lower half of x */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6797 054 tmpx1 = x->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6798 055
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6799 056 /* alias for upper half of x, or x/B**m */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6800 057 tmpx2 = x->dp + m;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6801 058
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6802 059 /* set carry to zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6803 060 mu = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6804 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6805 062 /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6806 063 for (i = 0; i < m; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6807 064 r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6808 065 *tmpx1++ = (mp_digit)(r & MP_MASK);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6809 066 mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6810 067 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6811 068
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6812 069 /* set final carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6813 070 *tmpx1++ = mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6814 071
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6815 072 /* zero words above m */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6816 073 for (i = m + 1; i < x->used; i++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6817 074 *tmpx1++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6818 075 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6819 076
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6820 077 /* clamp, sub and return */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6821 078 mp_clamp (x);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6822 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6823 080 /* if x >= n then subtract and reduce again
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6824 081 * Each successive "recursion" makes the input smaller and smaller.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6825 082 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6826 083 if (mp_cmp_mag (x, n) != MP_LT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6827 084 s_mp_sub(x, n, x);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6828 085 goto top;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6829 086 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6830 087 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6831 088 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6832 089 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6833 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6834 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6835
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6836 The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line 51 is where
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6837 the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6838 the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6839
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6840 The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6841 a division by $\beta^m$ can be simulated virtually for free. The loop on line 63 performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11})
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6842 in this algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6843
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6844 By line 70 the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line 73 the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6845 same pointer will point to the $m+1$'th digit where the zeroes will be placed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6846
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6847 Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6848 With the same logic at line 84 the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6849 as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6850 does not need to be checked.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6851
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6852 \subsubsection{Setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6853 To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6854 completeness.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6855
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6856 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6857 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6858 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6859 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6860 \hline Algorithm \textbf{mp\_dr\_setup}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6861 \textbf{Input}. mp\_int $n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6862 \textbf{Output}. $k = \beta - n_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6863 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6864 1. $k \leftarrow \beta - n_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6865 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6866 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6867 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6868 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6869 \caption{Algorithm mp\_dr\_setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6870 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6871
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6872 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6873 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6874 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6875 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6876 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6877 017 /* determines the setup value */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6878 018 void mp_dr_setup(mp_int *a, mp_digit *d)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6879 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6880 020 /* the casts are required if DIGIT_BIT is one less than
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6881 021 * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6882 022 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6883 023 *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6884 024 ((mp_word)a->dp[0]));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6885 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6886 026
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6887 027 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6888 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6889 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6890
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6891 \subsubsection{Modulus Detection}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6892 Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6893 of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6894
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6895 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6896 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6897 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6898 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6899 \hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6900 \textbf{Input}. mp\_int $n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6901 \textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6902 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6903 1. If $n.used < 2$ then return($0$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6904 2. for $ix$ from $1$ to $n.used - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6905 \hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6906 3. Return($1$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6907 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6908 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6909 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6910 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6911 \caption{Algorithm mp\_dr\_is\_modulus}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6912 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6913
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6914 \textbf{Algorithm mp\_dr\_is\_modulus.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6915 This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6916 in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6917 step 3 then $n$ must be of Diminished Radix form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6918
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6919 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6920 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6921 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6922 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6923 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6924 017 /* determines if a number is a valid DR modulus */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6925 018 int mp_dr_is_modulus(mp_int *a)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6926 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6927 020 int ix;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6928 021
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6929 022 /* must be at least two digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6930 023 if (a->used < 2) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6931 024 return 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6932 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6933 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6934 027 /* must be of the form b**k - a [a <= b] so all
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6935 028 * but the first digit must be equal to -1 (mod b).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6936 029 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6937 030 for (ix = 1; ix < a->used; ix++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6938 031 if (a->dp[ix] != MP_MASK) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6939 032 return 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6940 033 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6941 034 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6942 035 return 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6943 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6944 037
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
6945 038 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6946 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6947 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6948
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6949 \subsection{Unrestricted Diminished Radix Reduction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6950 The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6951 is a straightforward adaptation of algorithm~\ref{fig:DR}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6952
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6953 In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6954 algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6955
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6956 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6957 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6958 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6959 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6960 \hline Algorithm \textbf{mp\_reduce\_2k}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6961 \textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6962 \hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6963 \textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6964 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6965 1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6966 2. While $a \ge n$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6967 \hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6968 \hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6969 \hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6970 \hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6971 \hspace{3mm}2.5 If $a \ge n$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6972 \hspace{6mm}2.5.1 $a \leftarrow a - n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6973 3. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6974 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6975 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6976 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6977 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6978 \caption{Algorithm mp\_reduce\_2k}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6979 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6980
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6981 \textbf{Algorithm mp\_reduce\_2k.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6982 This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6983 shift which makes the algorithm fairly inexpensive to use.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6984
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6985 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6986 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6987 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6988 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6989 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6990 017 /* reduces a modulo n where n is of the form 2**p - d */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6991 018 int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6992 019 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6993 020 mp_int q;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6994 021 int p, res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6995 022
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6996 023 if ((res = mp_init(&q)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6997 024 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6998 025 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
6999 026
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7000 027 p = mp_count_bits(n);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7001 028 top:
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7002 029 /* q = a/2**p, a = a mod 2**p */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7003 030 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7004 031 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7005 032 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7006 033
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7007 034 if (d != 1) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7008 035 /* q = q * d */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7009 036 if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7010 037 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7011 038 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7012 039 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7013 040
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7014 041 /* a = a + q */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7015 042 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7016 043 goto ERR;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7017 044 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7018 045
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7019 046 if (mp_cmp_mag(a, n) != MP_LT) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7020 047 s_mp_sub(a, n, a);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7021 048 goto top;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7022 049 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7023 050
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7024 051 ERR:
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7025 052 mp_clear(&q);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7026 053 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7027 054 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7028 055
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7029 056 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7030 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7031 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7033 The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7034 on line 30 calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7035 is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7036 any multiplications.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7038 The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7039 positive. By using the unsigned versions the overhead is kept to a minimum.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7041 \subsubsection{Unrestricted Setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7042 To setup this reduction algorithm the value of $k = 2^p - n$ is required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7044 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7045 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7046 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7047 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7048 \hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7049 \textbf{Input}. mp\_int $n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7050 \textbf{Output}. $k = 2^p - n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7051 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7052 1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7053 2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7054 3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7055 4. $k \leftarrow x_0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7056 5. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7057 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7058 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7059 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7060 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7061 \caption{Algorithm mp\_reduce\_2k\_setup}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7062 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7063
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7064 \textbf{Algorithm mp\_reduce\_2k\_setup.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7065 This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7066 is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7068 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7069 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7070 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7071 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7072 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7073 017 /* determines the setup value */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7074 018 int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7075 019 \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7076 020 int res, p;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7077 021 mp_int tmp;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7078 022
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7079 023 if ((res = mp_init(&tmp)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7080 024 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7081 025 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7082 026
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7083 027 p = mp_count_bits(a);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7084 028 if ((res = mp_2expt(&tmp, p)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7085 029 mp_clear(&tmp);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7086 030 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7087 031 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7088 032
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7089 033 if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7090 034 mp_clear(&tmp);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7091 035 return res;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7092 036 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7093 037
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7094 038 *d = tmp.dp[0];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7095 039 mp_clear(&tmp);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7096 040 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7097 041 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7098 042 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7099 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7100 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7101
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7102 \subsubsection{Unrestricted Detection}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7103 An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7104
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7105 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7106 \item The number has only one digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7107 \item The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7108 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7109
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7110 If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7111 one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7112 that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7113 significant bit. The resulting sum will be a power of two.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7114
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7115 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7116 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7117 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7118 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7119 \hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7120 \textbf{Input}. mp\_int $n$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7121 \textbf{Output}. $1$ if of proper form, $0$ otherwise \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7122 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7123 1. If $n.used = 0$ then return($0$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7124 2. If $n.used = 1$ then return($1$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7125 3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7126 4. for $x$ from $lg(\beta)$ to $p$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7127 \hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7128 5. Return($1$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7129 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7130 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7131 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7132 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7133 \caption{Algorithm mp\_reduce\_is\_2k}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7134 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7135
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7136 \textbf{Algorithm mp\_reduce\_is\_2k.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7137 This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7138
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7139 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7140 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7141 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7142 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7143 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7144 017 /* determines if mp_reduce_2k can be used */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7145 018 int mp_reduce_is_2k(mp_int *a)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7146 019 \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7147 020 int ix, iy, iw;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7148 021 mp_digit iz;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7149 022
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7150 023 if (a->used == 0) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7151 024 return MP_NO;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7152 025 \} else if (a->used == 1) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7153 026 return MP_YES;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7154 027 \} else if (a->used > 1) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7155 028 iy = mp_count_bits(a);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7156 029 iz = 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7157 030 iw = 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7158 031
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7159 032 /* Test every bit from the second digit up, must be 1 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7160 033 for (ix = DIGIT_BIT; ix < iy; ix++) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7161 034 if ((a->dp[iw] & iz) == 0) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7162 035 return MP_NO;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7163 036 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7164 037 iz <<= 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7165 038 if (iz > (mp_digit)MP_MASK) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7166 039 ++iw;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7167 040 iz = 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7168 041 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7169 042 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7170 043 \}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7171 044 return MP_YES;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7172 045 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7173 046
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7174 047 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7175 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7176 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7177
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7178
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7179
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7180 \section{Algorithm Comparison}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7181 So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7182 that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7183 all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7184
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7185 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7186 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7187 \begin{tabular}{|c|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7188 \hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7189 \hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7190 \hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7191 \hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7192 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7193 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7194 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7195 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7196
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7197 In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7198 reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7199 calling the half precision multipliers, addition and division by $\beta$ algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7200
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7201 For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7202 shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7203 primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7204 modular exponentiation to greatly speed up the operation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7205
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7206
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7207
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7208 \section*{Exercises}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7209 \begin{tabular}{cl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7210 $\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7211 & calculates the correct value of $\rho$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7212 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7213 $\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7214 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7215 $\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7216 & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7217 & terminate within $1 \le k \le 10$ iterations. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7218 & \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7219 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7220
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7221
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7222 \chapter{Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7223 Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7224 in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7225 cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7226 such cryptosystem and many methods have been sought to speed it up.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7227
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7228 \section{Exponentiation Basics}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7229 A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7230 the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7231 with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7232
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7233 Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7234 are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7235 significant bit. If $b$ is a $k$-bit integer than the following equation is true.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7236
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7237 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7238 a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7239 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7240
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7241 By taking the base $a$ logarithm of both sides of the equation the following equation is the result.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7242
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7243 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7244 b = \sum_{i=0}^{k-1}2^i \cdot b_i
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7245 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7246
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7247 The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7248 $a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7249 $k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7250
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7251 While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7252 be computed in an auxilary variable. Consider the following equivalent algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7253
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7254 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7255 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7256 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7257 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7258 \hline Algorithm \textbf{Left to Right Exponentiation}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7259 \textbf{Input}. Integer $a$, $b$ and $k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7260 \textbf{Output}. $c = a^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7261 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7262 1. $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7263 2. for $i$ from $k - 1$ to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7264 \hspace{3mm}2.1 $c \leftarrow c^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7265 \hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7266 3. Return $c$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7267 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7268 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7269 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7270 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7271 \caption{Left to Right Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7272 \label{fig:LTOR}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7273 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7274
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7275 This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7276 multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7277 product.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7278
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7279 For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7280
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7281 \newpage\begin{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7282 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7283 \begin{tabular}{|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7284 \hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7285 \hline - & $1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7286 \hline $5$ & $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7287 \hline $4$ & $a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7288 \hline $3$ & $a^4 \cdot a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7289 \hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7290 \hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7291 \hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7292 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7293 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7294 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7295 \caption{Example of Left to Right Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7296 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7297
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7298 When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7299 called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7300
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7301 \subsection{Single Digit Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7302 The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7303 to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7304 $b$ that are greater than three.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7305
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7306 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7307 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7308 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7309 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7310 \hline Algorithm \textbf{mp\_expt\_d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7311 \textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7312 \textbf{Output}. $c = a^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7313 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7314 1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7315 2. $c \leftarrow 1$ (\textit{mp\_set}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7316 3. for $x$ from 1 to $lg(\beta)$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7317 \hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7318 \hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7319 \hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7320 \hspace{3mm}3.3 $b \leftarrow b << 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7321 4. Clear $g$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7322 5. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7323 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7324 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7325 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7326 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7327 \caption{Algorithm mp\_expt\_d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7328 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7329
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7330 \textbf{Algorithm mp\_expt\_d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7331 This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7332 quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7333 exponent is a fixed width.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7334
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7335 A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7336 $1$ in the subsequent step.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7337
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7338 Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7339 on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7340 of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7341 iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7342
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7343 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7344 \hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7345 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7346 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7347 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7348 017 /* calculate c = a**b using a square-multiply algorithm */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7349 018 int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7350 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7351 020 int res, x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7352 021 mp_int g;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7353 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7354 023 if ((res = mp_init_copy (&g, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7355 024 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7356 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7357 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7358 027 /* set initial result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7359 028 mp_set (c, 1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7360 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7361 030 for (x = 0; x < (int) DIGIT_BIT; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7362 031 /* square */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7363 032 if ((res = mp_sqr (c, c)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7364 033 mp_clear (&g);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7365 034 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7366 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7367 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7368 037 /* if the bit is set multiply */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7369 038 if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7370 039 if ((res = mp_mul (c, &g, c)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7371 040 mp_clear (&g);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7372 041 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7373 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7374 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7375 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7376 045 /* shift to next bit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7377 046 b <<= 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7378 047 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7379 048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7380 049 mp_clear (&g);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7381 050 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7382 051 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7383 052 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7384 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7385 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7386
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7387 Line 28 sets the initial value of the result to $1$. Next the loop on line 30 steps through each bit of the exponent starting from
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7388 the most significant down towards the least significant. The invariant squaring operation placed on line 32 is performed first. After
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7389 the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7390 46 moves all of the bits of the exponent upwards towards the most significant location.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7391
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7392 \section{$k$-ary Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7393 When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7394 slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7395 the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7396 computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7397 portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7398
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7399 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7400 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7401 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7402 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7403 \hline Algorithm \textbf{$k$-ary Exponentiation}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7404 \textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7405 \textbf{Output}. $c = a^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7406 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7407 1. $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7408 2. for $i$ from $t - 1$ to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7409 \hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7410 \hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7411 \hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7412 3. Return $c$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7413 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7414 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7415 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7416 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7417 \caption{$k$-ary Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7418 \label{fig:KARY}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7419 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7420
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7421 The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7422 precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7423 $2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7424 However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7425
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7426 Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7427 original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7428 has increased slightly but the number of multiplications has nearly halved.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7429
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7430 \subsection{Optimal Values of $k$}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7431 An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7432 approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7433 for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7434
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7435 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7436 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7437 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7438 \begin{tabular}{|c|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7439 \hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7440 \hline $16$ & $2$ & $27$ & $24$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7441 \hline $32$ & $3$ & $49$ & $48$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7442 \hline $64$ & $3$ & $92$ & $96$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7443 \hline $128$ & $4$ & $175$ & $192$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7444 \hline $256$ & $4$ & $335$ & $384$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7445 \hline $512$ & $5$ & $645$ & $768$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7446 \hline $1024$ & $6$ & $1257$ & $1536$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7447 \hline $2048$ & $6$ & $2452$ & $3072$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7448 \hline $4096$ & $7$ & $4808$ & $6144$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7449 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7450 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7451 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7452 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7453 \caption{Optimal Values of $k$ for $k$-ary Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7454 \label{fig:OPTK}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7455 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7456
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7457 \subsection{Sliding-Window Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7458 A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7459 this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7460 algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7461
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7462 Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7463
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7464 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7465 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7466 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7467 \begin{tabular}{|c|c|c|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7468 \hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7469 \hline $16$ & $3$ & $24$ & $27$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7470 \hline $32$ & $3$ & $45$ & $49$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7471 \hline $64$ & $4$ & $87$ & $92$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7472 \hline $128$ & $4$ & $167$ & $175$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7473 \hline $256$ & $5$ & $322$ & $335$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7474 \hline $512$ & $6$ & $628$ & $645$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7475 \hline $1024$ & $6$ & $1225$ & $1257$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7476 \hline $2048$ & $7$ & $2403$ & $2452$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7477 \hline $4096$ & $8$ & $4735$ & $4808$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7478 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7479 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7480 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7481 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7482 \caption{Optimal Values of $k$ for Sliding Window Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7483 \label{fig:OPTK2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7484 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7485
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7486 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7487 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7488 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7489 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7490 \hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7491 \textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7492 \textbf{Output}. $c = a^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7493 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7494 1. $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7495 2. for $i$ from $t - 1$ to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7496 \hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7497 \hspace{6mm}2.1.1 $c \leftarrow c^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7498 \hspace{3mm}2.2 else do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7499 \hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7500 \hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7501 \hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7502 \hspace{6mm}2.2.4 $i \leftarrow i - k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7503 3. Return $c$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7504 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7505 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7506 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7507 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7508 \caption{Sliding Window $k$-ary Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7509 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7510
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7511 Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7512 algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7513 the size as the previous table.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7514
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7515 Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7516 the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7517 exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7518 a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7519 squarings. The second method requires $8$ multiplications and $18$ squarings.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7520
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7521 In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7522
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7523 \section{Modular Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7524
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7525 Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7526 $d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7527 modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7528
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7529 This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7530 one of the algorithms presented in chapter six.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7531
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7532 Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7533 will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7534 value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7535 terminates with an error.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7536
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7537 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7538 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7539 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7540 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7541 \hline Algorithm \textbf{mp\_exptmod}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7542 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7543 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7544 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7545 1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7546 2. If $b.sign = MP\_NEG$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7547 \hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7548 \hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7549 \hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7550 3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7551 \hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7552 4. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7553 \hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7554 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7555 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7556 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7557 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7558 \caption{Algorithm mp\_exptmod}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7559 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7560
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7561 \textbf{Algorithm mp\_exptmod.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7562 The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7563 which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7564 except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7565 algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7566
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7567 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7568 \hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7569 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7570 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7571 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7572 017
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7573 018 /* this is a shell function that calls either the normal or Montgomery
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7574 019 * exptmod functions. Originally the call to the montgomery code was
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7575 020 * embedded in the normal function but that wasted alot of stack space
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7576 021 * for nothing (since 99% of the time the Montgomery code would be called)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7577 022 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7578 023 int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7579 024 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7580 025 int dr;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7581 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7582 027 /* modulus P must be positive */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7583 028 if (P->sign == MP_NEG) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7584 029 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7585 030 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7586 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7587 032 /* if exponent X is negative we have to recurse */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7588 033 if (X->sign == MP_NEG) \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7589 034 #ifdef BN_MP_INVMOD_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7590 035 mp_int tmpG, tmpX;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7591 036 int err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7592 037
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7593 038 /* first compute 1/G mod P */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7594 039 if ((err = mp_init(&tmpG)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7595 040 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7596 041 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7597 042 if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7598 043 mp_clear(&tmpG);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7599 044 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7600 045 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7601 046
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7602 047 /* now get |X| */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7603 048 if ((err = mp_init(&tmpX)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7604 049 mp_clear(&tmpG);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7605 050 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7606 051 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7607 052 if ((err = mp_abs(X, &tmpX)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7608 053 mp_clear_multi(&tmpG, &tmpX, NULL);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7609 054 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7610 055 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7611 056
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7612 057 /* and now compute (1/G)**|X| instead of G**X [X < 0] */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7613 058 err = mp_exptmod(&tmpG, &tmpX, P, Y);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7614 059 mp_clear_multi(&tmpG, &tmpX, NULL);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7615 060 return err;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7616 061 #else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7617 062 /* no invmod */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7618 063 return MP_VAL;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7619 064 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7620 065 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7621 066
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7622 067 /* modified diminished radix reduction */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7623 068 #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7624 069 if (mp_reduce_is_2k_l(P) == MP_YES) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7625 070 return s_mp_exptmod(G, X, P, Y, 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7626 071 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7627 072 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
7628 073
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7629 074 #ifdef BN_MP_DR_IS_MODULUS_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7630 075 /* is it a DR modulus? */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7631 076 dr = mp_dr_is_modulus(P);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7632 077 #else
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7633 078 /* default to no */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7634 079 dr = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7635 080 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7636 081
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7637 082 #ifdef BN_MP_REDUCE_IS_2K_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7638 083 /* if not, is it a unrestricted DR modulus? */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7639 084 if (dr == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7640 085 dr = mp_reduce_is_2k(P) << 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7641 086 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7642 087 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7643 088
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7644 089 /* if the modulus is odd or dr != 0 use the montgomery method */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7645 090 #ifdef BN_MP_EXPTMOD_FAST_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7646 091 if (mp_isodd (P) == 1 || dr != 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7647 092 return mp_exptmod_fast (G, X, P, Y, dr);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7648 093 \} else \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7649 094 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7650 095 #ifdef BN_S_MP_EXPTMOD_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7651 096 /* otherwise use the generic Barrett reduction technique */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7652 097 return s_mp_exptmod (G, X, P, Y, 0);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7653 098 #else
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7654 099 /* no exptmod for evens */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7655 100 return MP_VAL;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7656 101 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7657 102 #ifdef BN_MP_EXPTMOD_FAST_C
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7658 103 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7659 104 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7660 105 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7661 106
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7662 107 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7663 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7664 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7665
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7666 In order to keep the algorithms in a known state the first step on line 28 is to reject any negative modulus as input. If the exponent is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7667 negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7668 the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7669 exponent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7670
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7671 If the exponent is positive the algorithm resumes the exponentiation. Line 76 determines if the modulus is of the restricted Diminished Radix
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7672 form. If it is not line 69 attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7673 of three values.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7674
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7675 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7676 \item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7677 \item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7678 \item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7679 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7680
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7681 Line 69 determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise,
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7682 the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7683
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7684 \subsection{Barrett Modular Exponentiation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7685
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7686 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7687 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7688 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7689 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7690 \hline Algorithm \textbf{s\_mp\_exptmod}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7691 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7692 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7693 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7694 1. $k \leftarrow lg(x)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7695 2. $winsize \leftarrow \left \lbrace \begin{array}{ll}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7696 2 & \mbox{if }k \le 7 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7697 3 & \mbox{if }7 < k \le 36 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7698 4 & \mbox{if }36 < k \le 140 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7699 5 & \mbox{if }140 < k \le 450 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7700 6 & \mbox{if }450 < k \le 1303 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7701 7 & \mbox{if }1303 < k \le 3529 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7702 8 & \mbox{if }3529 < k \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7703 \end{array} \right .$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7704 3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7705 4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7706 5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7707 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7708 Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7709 6. $k \leftarrow 2^{winsize - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7710 7. $M_{k} \leftarrow M_1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7711 8. for $ix$ from 0 to $winsize - 2$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7712 \hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7713 \hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7714 9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7715 \hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7716 \hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7717 10. $res \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7718 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7719 Start Sliding Window. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7720 11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7721 12. Loop \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7722 \hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7723 \hspace{3mm}12.2 If $bitcnt = 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7724 \hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7725 \hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7726 \hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7727 \hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7728 Continued on next page. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7729 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7730 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7731 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7732 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7733 \caption{Algorithm s\_mp\_exptmod}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7734 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7735
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7736 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7737 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7738 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7739 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7740 \hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7741 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7742 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7743 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7744 \hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7745 \hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7746 \hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7747 \hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7748 \hspace{6mm}12.6.1 $res \leftarrow res^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7749 \hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7750 \hspace{6mm}12.6.3 Goto step 12. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7751 \hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7752 \hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7753 \hspace{3mm}12.9 $mode \leftarrow 2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7754 \hspace{3mm}12.10 If $bitcpy = winsize$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7755 \hspace{6mm}Window is full so perform the squarings and single multiplication. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7756 \hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7757 \hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7758 \hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7759 \hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7760 \hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7761 \hspace{6mm}Reset the window. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7762 \hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7763 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7764 No more windows left. Check for residual bits of exponent. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7765 13. If $mode = 2$ and $bitcpy > 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7766 \hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7767 \hspace{6mm}13.1.1 $res \leftarrow res^2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7768 \hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7769 \hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7770 \hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7771 \hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7772 \hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7773 14. $y \leftarrow res$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7774 15. Clear $res$, $mu$ and the $M$ array. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7775 16. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7776 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7777 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7778 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7779 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7780 \caption{Algorithm s\_mp\_exptmod (continued)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7781 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7782
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7783 \textbf{Algorithm s\_mp\_exptmod.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7784 This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7785 algorithm to keep the product small throughout the algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7786
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7787 The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7788 larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7789 table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7790
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7791 After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7792 the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7793 times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7794
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7795 Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7796 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7797 \item The variable $mode$ dictates how the bits of the exponent are interpreted.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7798 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7799 \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7800 $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7801 \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7802 are read and a single squaring is performed. If a non-zero bit is read a new window is created.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7803 \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7804 downwards.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7805 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7806 \item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7807 is fetched from the exponent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7808 \item The variable $buf$ holds the currently read digit of the exponent.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7809 \item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7810 \item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7811 the appropriate operations performed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7812 \item The variable $bitbuf$ holds the current bits of the window being formed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7813 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7814
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7815 All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7816 inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7817 read and if there are no digits left than the loop terminates.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7818
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7819 After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7820 upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7821 trailing edges the entire exponent is read from most significant bit to least significant bit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7822
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7823 At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7824 algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7825 the two cases of $mode = 1$ and $mode = 2$ respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7826
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7827 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7828 \begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7829 \includegraphics{pics/expt_state.ps}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7830 \caption{Sliding Window State Diagram}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7831 \label{pic:expt_state}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7832 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7833 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7834
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7835 By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7836 a Left-to-Right algorithm is used to process the remaining few bits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7837
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7838 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7839 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7840 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7841 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7842 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7843 017 #ifdef MP_LOW_MEM
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7844 018 #define TAB_SIZE 32
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7845 019 #else
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7846 020 #define TAB_SIZE 256
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7847 021 #endif
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7848 022
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7849 023 int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmod
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7850 e)
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7851 024 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7852 025 mp_int M[TAB_SIZE], res, mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7853 026 mp_digit buf;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7854 027 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7855 028 int (*redux)(mp_int*,mp_int*,mp_int*);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7856 029
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7857 030 /* find window size */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7858 031 x = mp_count_bits (X);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7859 032 if (x <= 7) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7860 033 winsize = 2;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7861 034 \} else if (x <= 36) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7862 035 winsize = 3;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7863 036 \} else if (x <= 140) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7864 037 winsize = 4;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7865 038 \} else if (x <= 450) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7866 039 winsize = 5;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7867 040 \} else if (x <= 1303) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7868 041 winsize = 6;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7869 042 \} else if (x <= 3529) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7870 043 winsize = 7;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7871 044 \} else \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7872 045 winsize = 8;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7873 046 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7874 047
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7875 048 #ifdef MP_LOW_MEM
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7876 049 if (winsize > 5) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7877 050 winsize = 5;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7878 051 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7879 052 #endif
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7880 053
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7881 054 /* init M array */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7882 055 /* init first cell */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7883 056 if ((err = mp_init(&M[1])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7884 057 return err;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7885 058 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7886 059
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7887 060 /* now init the second half of the array */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7888 061 for (x = 1<<(winsize-1); x < (1 << winsize); x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7889 062 if ((err = mp_init(&M[x])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7890 063 for (y = 1<<(winsize-1); y < x; y++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7891 064 mp_clear (&M[y]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7892 065 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7893 066 mp_clear(&M[1]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7894 067 return err;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7895 068 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7896 069 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7897 070
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7898 071 /* create mu, used for Barrett reduction */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7899 072 if ((err = mp_init (&mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7900 073 goto LBL_M;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7901 074 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7902 075
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7903 076 if (redmode == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7904 077 if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7905 078 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7906 079 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7907 080 redux = mp_reduce;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7908 081 \} else \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7909 082 if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7910 083 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7911 084 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7912 085 redux = mp_reduce_2k_l;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7913 086 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7914 087
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7915 088 /* create M table
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7916 089 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7917 090 * The M table contains powers of the base,
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7918 091 * e.g. M[x] = G**x mod P
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7919 092 *
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7920 093 * The first half of the table is not
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7921 094 * computed though accept for M[0] and M[1]
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7922 095 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7923 096 if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7924 097 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7925 098 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7926 099
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7927 100 /* compute the value at M[1<<(winsize-1)] by squaring
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7928 101 * M[1] (winsize-1) times
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7929 102 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7930 103 if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7931 104 goto LBL_MU;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7932 105 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7933 106
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7934 107 for (x = 0; x < (winsize - 1); x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7935 108 /* square it */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7936 109 if ((err = mp_sqr (&M[1 << (winsize - 1)],
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7937 110 &M[1 << (winsize - 1)])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7938 111 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7939 112 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7940 113
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7941 114 /* reduce modulo P */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7942 115 if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7943 116 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7944 117 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7945 118 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7946 119
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7947 120 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7948 121 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7949 122 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7950 123 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7951 124 if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7952 125 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7953 126 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7954 127 if ((err = redux (&M[x], P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7955 128 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7956 129 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7957 130 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7958 131
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7959 132 /* setup result */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7960 133 if ((err = mp_init (&res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7961 134 goto LBL_MU;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7962 135 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7963 136 mp_set (&res, 1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7964 137
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7965 138 /* set initial mode and bit cnt */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7966 139 mode = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7967 140 bitcnt = 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7968 141 buf = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7969 142 digidx = X->used - 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7970 143 bitcpy = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7971 144 bitbuf = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7972 145
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7973 146 for (;;) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7974 147 /* grab next digit as required */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7975 148 if (--bitcnt == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7976 149 /* if digidx == -1 we are out of digits */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7977 150 if (digidx == -1) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7978 151 break;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7979 152 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7980 153 /* read next digit and reset the bitcnt */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7981 154 buf = X->dp[digidx--];
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7982 155 bitcnt = (int) DIGIT_BIT;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7983 156 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7984 157
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7985 158 /* grab the next msb from the exponent */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7986 159 y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7987 160 buf <<= (mp_digit)1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7988 161
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7989 162 /* if the bit is zero and mode == 0 then we ignore it
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7990 163 * These represent the leading zero bits before the first 1 bit
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7991 164 * in the exponent. Technically this opt is not required but it
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7992 165 * does lower the # of trivial squaring/reductions used
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7993 166 */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7994 167 if (mode == 0 && y == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7995 168 continue;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7996 169 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7997 170
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7998 171 /* if the bit is zero and mode == 1 then we square */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
7999 172 if (mode == 1 && y == 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8000 173 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8001 174 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8002 175 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8003 176 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8004 177 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8005 178 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8006 179 continue;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8007 180 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8008 181
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8009 182 /* else we add it to the window */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8010 183 bitbuf |= (y << (winsize - ++bitcpy));
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8011 184 mode = 2;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8012 185
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8013 186 if (bitcpy == winsize) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8014 187 /* ok window is filled so square as required and multiply */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8015 188 /* square first */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8016 189 for (x = 0; x < winsize; x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8017 190 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8018 191 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8019 192 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8020 193 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8021 194 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8022 195 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8023 196 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8024 197
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8025 198 /* then multiply */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8026 199 if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8027 200 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8028 201 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8029 202 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8030 203 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8031 204 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8032 205
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8033 206 /* empty window and reset */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8034 207 bitcpy = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8035 208 bitbuf = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8036 209 mode = 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8037 210 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8038 211 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8039 212
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8040 213 /* if bits remain then square/multiply */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8041 214 if (mode == 2 && bitcpy > 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8042 215 /* square then multiply if the bit is set */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8043 216 for (x = 0; x < bitcpy; x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8044 217 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8045 218 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8046 219 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8047 220 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8048 221 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8049 222 \}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8050 223
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8051 224 bitbuf <<= 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8052 225 if ((bitbuf & (1 << winsize)) != 0) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8053 226 /* then multiply */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8054 227 if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8055 228 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8056 229 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8057 230 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8058 231 goto LBL_RES;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8059 232 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8060 233 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8061 234 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8062 235 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8063 236
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8064 237 mp_exch (&res, Y);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8065 238 err = MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8066 239 LBL_RES:mp_clear (&res);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8067 240 LBL_MU:mp_clear (&mu);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8068 241 LBL_M:
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8069 242 mp_clear(&M[1]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8070 243 for (x = 1<<(winsize-1); x < (1 << winsize); x++) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8071 244 mp_clear (&M[x]);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8072 245 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8073 246 return err;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8074 247 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8075 248 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8076 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8077 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8078
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8079 Lines 21 through 40 determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8080 from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8081 on line 32 the value of $x$ is already known to be greater than $140$.
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8082
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8083 The conditional piece of code beginning on line 48 allows the window size to be restricted to five bits. This logic is used to ensure
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8084 the table of precomputed powers of $G$ remains relatively small.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8085
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8086 The for loop on line 61 initializes the $M$ array while lines 62 and 77 compute the value of $\mu$ required for
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8087 Barrett reduction.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8088
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8089 -- More later.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8090
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8091 \section{Quick Power of Two}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8092 Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8093 equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8094
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8095 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8096 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8097 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8098 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8099 \hline Algorithm \textbf{mp\_2expt}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8100 \textbf{Input}. integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8101 \textbf{Output}. $a \leftarrow 2^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8102 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8103 1. $a \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8104 2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8105 3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8106 4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8107 5. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8108 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8109 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8110 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8111 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8112 \caption{Algorithm mp\_2expt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8113 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8114
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8115 \textbf{Algorithm mp\_2expt.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8116
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8117 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8118 \hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8119 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8120 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8121 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8122 017 /* computes a = 2**b
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8123 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8124 019 * Simple algorithm which zeroes the int, grows it then just sets one bit
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8125 020 * as required.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8126 021 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8127 022 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8128 023 mp_2expt (mp_int * a, int b)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8129 024 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8130 025 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8131 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8132 027 /* zero a as per default */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8133 028 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8134 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8135 030 /* grow a to accomodate the single bit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8136 031 if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8137 032 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8138 033 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8139 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8140 035 /* set the used count of where the bit will go */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8141 036 a->used = b / DIGIT_BIT + 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8142 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8143 038 /* put the single bit in its place */
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8144 039 a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8145 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8146 041 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8147 042 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8148 043 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8149 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8150 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8151
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8152 \chapter{Higher Level Algorithms}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8153
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8154 This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8155 routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8156
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8157 The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8158 for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8159 These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8160 various representations of integers. For example, converting from an mp\_int to a string of character.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8161
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8162 \section{Integer Division with Remainder}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8163 \label{sec:division}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8164
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8165 Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8166 the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8167 will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8168 let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8169
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8170 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8171 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8172 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8173 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8174 \hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8175 \textbf{Input}. integer $x$ and $y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8176 \textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8177 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8178 1. $q \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8179 2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8180 3. for $t$ from $n$ down to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8181 \hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8182 \hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8183 \hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8184 4. $r \leftarrow y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8185 5. Return($q, r$) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8186 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8187 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8188 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8189 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8190 \caption{Algorithm Radix-$\beta$ Integer Division}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8191 \label{fig:raddiv}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8192 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8193
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8194 As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8195 their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8196
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8197 To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8198 simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8199 used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8200 digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8201 arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8202 As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8203
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8204 Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8205 $y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8206 remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8207 $237 \cdot 23 + 20 = 5471$ is true.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8208
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8209 \subsection{Quotient Estimation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8210 \label{sec:divest}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8211 As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8212 digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8213 speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8214 dividend and divisor are zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8215
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8216 The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8217 of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8218 using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8219 represent the most significant digits of the dividend and divisor respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8220
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8221 \textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8222 $k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8223 The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8224 cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8225 $-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8226 inequalities will prove the hypothesis.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8227
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8228 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8229 y - \hat k x \le y - \hat k x_s\beta^s
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8230 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8231
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8232 This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8233
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8234 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8235 y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8236 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8237
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8238 By simplifying the previous inequality the following inequality is formed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8239
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8240 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8241 y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8242 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8243
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8244 Subsequently,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8245
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8246 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8247 y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8248 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8249
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8250 Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8251
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8252
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8253 \subsection{Normalized Integers}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8254 For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8255 $x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8256 remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8257 lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8258
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8259 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8260 {{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8261 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8262
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8263 At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8264
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8265 \subsection{Radix-$\beta$ Division with Remainder}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8266 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8267 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8268 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8269 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8270 \hline Algorithm \textbf{mp\_div}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8271 \textbf{Input}. mp\_int $a, b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8272 \textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8273 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8274 1. If $b = 0$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8275 2. If $\vert a \vert < \vert b \vert$ then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8276 \hspace{3mm}2.1 $d \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8277 \hspace{3mm}2.2 $c \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8278 \hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8279 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8280 Setup the quotient to receive the digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8281 3. Grow $q$ to $a.used + 2$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8282 4. $q \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8283 5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8284 6. $sign \leftarrow \left \lbrace \begin{array}{ll}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8285 MP\_ZPOS & \mbox{if }a.sign = b.sign \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8286 MP\_NEG & \mbox{otherwise} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8287 \end{array} \right .$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8288 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8289 Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8290 7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8291 8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8292 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8293 Find the leading digit of the quotient. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8294 9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8295 10. $y \leftarrow y \cdot \beta^{n - t}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8296 11. While ($x \ge y$) do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8297 \hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8298 \hspace{3mm}11.2 $x \leftarrow x - y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8299 12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8300 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8301 Continued on the next page. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8302 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8303 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8304 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8305 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8306 \caption{Algorithm mp\_div}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8307 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8308
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8309 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8310 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8311 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8312 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8313 \hline Algorithm \textbf{mp\_div} (continued). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8314 \textbf{Input}. mp\_int $a, b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8315 \textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8316 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8317 Now find the remainder fo the digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8318 13. for $i$ from $n$ down to $(t + 1)$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8319 \hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8320 \hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8321 \hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8322 \hspace{3mm}13.3 else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8323 \hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8324 \hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8325 \hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8326 \hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8327 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8328 Fixup quotient estimation. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8329 \hspace{3mm}13.5 Loop \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8330 \hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8331 \hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8332 \hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8333 \hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8334 \hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8335 \hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8336 \hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8337 \hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8338 \hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8339 \hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8340 \hspace{6mm}13.10 t$1 \leftarrow y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8341 \hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8342 \hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8343 \hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8344 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8345 Finalize the result. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8346 14. Clamp excess digits of $q$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8347 15. $c \leftarrow q, c.sign \leftarrow sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8348 16. $x.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8349 17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8350 18. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8351 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8352 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8353 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8354 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8355 \caption{Algorithm mp\_div (continued)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8356 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8357 \textbf{Algorithm mp\_div.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8358 This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8359 division and will produce a fully qualified quotient and remainder.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8360
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8361 First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8362 zero and the remainder is the dividend.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8363
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8364 After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8365 divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8366 positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8367 This is performed by shifting both to the left by enough bits to get the desired normalization.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8368
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8369 At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8370 $2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8371 to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8372 shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8373 times to produce the desired leading digit of the quotient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8374
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8375 Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8376 accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8377 induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8378
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8379 Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8380 to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8381 order approximation to adjust the quotient digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8382
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8383 After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8384 by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8385 algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8386
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8387 Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8388 remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8389 is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8390 outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8391 respectively be replaced with a zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8392
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8393 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8394 \hspace{-5.1mm}{\bf File}: bn\_mp\_div.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8395 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8396 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8397 016
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8398 017 #ifdef BN_MP_DIV_SMALL
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8399 018
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8400 019 /* slower bit-bang division... also smaller */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8401 020 int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8402 021 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8403 022 mp_int ta, tb, tq, q;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8404 023 int res, n, n2;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8405 024
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8406 025 /* is divisor zero ? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8407 026 if (mp_iszero (b) == 1) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8408 027 return MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8409 028 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8410 029
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8411 030 /* if a < b then q=0, r = a */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8412 031 if (mp_cmp_mag (a, b) == MP_LT) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8413 032 if (d != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8414 033 res = mp_copy (a, d);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8415 034 \} else \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8416 035 res = MP_OKAY;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8417 036 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8418 037 if (c != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8419 038 mp_zero (c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8420 039 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8421 040 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8422 041 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8423 042
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8424 043 /* init our temps */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8425 044 if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8426 045 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8427 046 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8428 047
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8429 048
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8430 049 mp_set(&tq, 1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8431 050 n = mp_count_bits(a) - mp_count_bits(b);
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8432 051 if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8433 052 ((res = mp_abs(b, &tb)) != MP_OKAY) ||
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8434 053 ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8435 054 ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8436 055 goto LBL_ERR;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8437 056 \}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8438 057
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8439 058 while (n-- >= 0) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8440 059 if (mp_cmp(&tb, &ta) != MP_GT) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8441 060 if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8442 061 ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8443 062 goto LBL_ERR;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8444 063 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8445 064 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8446 065 if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8447 066 ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8448 067 goto LBL_ERR;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8449 068 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8450 069 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8451 070
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8452 071 /* now q == quotient and ta == remainder */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8453 072 n = a->sign;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8454 073 n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8455 074 if (c != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8456 075 mp_exch(c, &q);
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8457 076 c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8458 077 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8459 078 if (d != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8460 079 mp_exch(d, &ta);
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8461 080 d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8462 081 \}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8463 082 LBL_ERR:
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8464 083 mp_clear_multi(&ta, &tb, &tq, &q, NULL);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8465 084 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8466 085 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8467 086
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8468 087 #else
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8469 088
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8470 089 /* integer signed division.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8471 090 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8472 091 * HAC pp.598 Algorithm 14.20
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8473 092 *
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8474 093 * Note that the description in HAC is horribly
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8475 094 * incomplete. For example, it doesn't consider
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8476 095 * the case where digits are removed from 'x' in
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8477 096 * the inner loop. It also doesn't consider the
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8478 097 * case that y has fewer than three digits, etc..
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8479 098 *
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8480 099 * The overall algorithm is as described as
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8481 100 * 14.20 from HAC but fixed to treat these cases.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8482 101 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8483 102 int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8484 103 \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8485 104 mp_int q, x, y, t1, t2;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8486 105 int res, n, t, i, norm, neg;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8487 106
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8488 107 /* is divisor zero ? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8489 108 if (mp_iszero (b) == 1) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8490 109 return MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8491 110 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8492 111
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8493 112 /* if a < b then q=0, r = a */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8494 113 if (mp_cmp_mag (a, b) == MP_LT) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8495 114 if (d != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8496 115 res = mp_copy (a, d);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8497 116 \} else \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8498 117 res = MP_OKAY;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8499 118 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8500 119 if (c != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8501 120 mp_zero (c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8502 121 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8503 122 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8504 123 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8505 124
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8506 125 if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8507 126 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8508 127 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8509 128 q.used = a->used + 2;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8510 129
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8511 130 if ((res = mp_init (&t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8512 131 goto LBL_Q;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8513 132 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8514 133
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8515 134 if ((res = mp_init (&t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8516 135 goto LBL_T1;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8517 136 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8518 137
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8519 138 if ((res = mp_init_copy (&x, a)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8520 139 goto LBL_T2;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8521 140 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8522 141
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8523 142 if ((res = mp_init_copy (&y, b)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8524 143 goto LBL_X;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8525 144 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8526 145
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8527 146 /* fix the sign */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8528 147 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8529 148 x.sign = y.sign = MP_ZPOS;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8530 149
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8531 150 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8532 151 norm = mp_count_bits(&y) % DIGIT_BIT;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8533 152 if (norm < (int)(DIGIT_BIT-1)) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8534 153 norm = (DIGIT_BIT-1) - norm;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8535 154 if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8536 155 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8537 156 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8538 157 if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8539 158 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8540 159 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8541 160 \} else \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8542 161 norm = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8543 162 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8544 163
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8545 164 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8546 165 n = x.used - 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8547 166 t = y.used - 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8548 167
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8549 168 /* while (x >= y*b**n-t) do \{ q[n-t] += 1; x -= y*b**\{n-t\} \} */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8550 169 if ((res = mp_lshd (&y, n - t)) != MP_OKAY) \{ /* y = y*b**\{n-t\} */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8551 170 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8552 171 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8553 172
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8554 173 while (mp_cmp (&x, &y) != MP_LT) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8555 174 ++(q.dp[n - t]);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8556 175 if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8557 176 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8558 177 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8559 178 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8560 179
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8561 180 /* reset y by shifting it back down */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8562 181 mp_rshd (&y, n - t);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8563 182
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8564 183 /* step 3. for i from n down to (t + 1) */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8565 184 for (i = n; i >= (t + 1); i--) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8566 185 if (i > x.used) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8567 186 continue;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8568 187 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8569 188
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8570 189 /* step 3.1 if xi == yt then set q\{i-t-1\} to b-1,
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8571 190 * otherwise set q\{i-t-1\} to (xi*b + x\{i-1\})/yt */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8572 191 if (x.dp[i] == y.dp[t]) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8573 192 q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8574 193 \} else \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8575 194 mp_word tmp;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8576 195 tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8577 196 tmp |= ((mp_word) x.dp[i - 1]);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8578 197 tmp /= ((mp_word) y.dp[t]);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8579 198 if (tmp > (mp_word) MP_MASK)
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8580 199 tmp = MP_MASK;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8581 200 q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8582 201 \}
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8583 202
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8584 203 /* while (q\{i-t-1\} * (yt * b + y\{t-1\})) >
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8585 204 xi * b**2 + xi-1 * b + xi-2
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8586 205
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8587 206 do q\{i-t-1\} -= 1;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8588 207 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8589 208 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8590 209 do \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8591 210 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8592 211
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8593 212 /* find left hand */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8594 213 mp_zero (&t1);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8595 214 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8596 215 t1.dp[1] = y.dp[t];
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8597 216 t1.used = 2;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8598 217 if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8599 218 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8600 219 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8601 220
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8602 221 /* find right hand */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8603 222 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8604 223 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8605 224 t2.dp[2] = x.dp[i];
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8606 225 t2.used = 3;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8607 226 \} while (mp_cmp_mag(&t1, &t2) == MP_GT);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8608 227
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8609 228 /* step 3.3 x = x - q\{i-t-1\} * y * b**\{i-t-1\} */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8610 229 if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8611 230 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8612 231 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8613 232
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8614 233 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8615 234 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8616 235 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8617 236
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8618 237 if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8619 238 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8620 239 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8621 240
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8622 241 /* if x < 0 then \{ x = x + y*b**\{i-t-1\}; q\{i-t-1\} -= 1; \} */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8623 242 if (x.sign == MP_NEG) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8624 243 if ((res = mp_copy (&y, &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8625 244 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8626 245 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8627 246 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8628 247 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8629 248 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8630 249 if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8631 250 goto LBL_Y;
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8632 251 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8633 252
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8634 253 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8635 254 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8636 255 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8637 256
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8638 257 /* now q is the quotient and x is the remainder
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8639 258 * [which we have to normalize]
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8640 259 */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8641 260
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8642 261 /* get sign before writing to c */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8643 262 x.sign = x.used == 0 ? MP_ZPOS : a->sign;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8644 263
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8645 264 if (c != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8646 265 mp_clamp (&q);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8647 266 mp_exch (&q, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8648 267 c->sign = neg;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8649 268 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8650 269
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8651 270 if (d != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8652 271 mp_div_2d (&x, norm, &x, NULL);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8653 272 mp_exch (&x, d);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8654 273 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8655 274
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8656 275 res = MP_OKAY;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8657 276
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8658 277 LBL_Y:mp_clear (&y);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8659 278 LBL_X:mp_clear (&x);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8660 279 LBL_T2:mp_clear (&t2);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8661 280 LBL_T1:mp_clear (&t1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8662 281 LBL_Q:mp_clear (&q);
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8663 282 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8664 283 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8665 284
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8666 285 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8667 286
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8668 287 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8669 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8670 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8671
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8672 The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8673 remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8674 algorithm with only the quotient is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8675
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8676 \begin{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8677 mp_div(&a, &b, &c, NULL); /* c = [a/b] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8678 \end{verbatim}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8679
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8680 Lines 37 and 44 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8681 respectively. After the two trivial cases all of the temporary variables are initialized. Line 105 determines the sign of
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8682 the quotient and line 76 ensures that both $x$ and $y$ are positive.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8683
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8684 The number of bits in the leading digit is calculated on line 105. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8685 of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8686 exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8687 them to the left by $lg(\beta) - 1 - k$ bits.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8688
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8689 Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8690 leading digit of the quotient. The loop beginning on line 183 will produce the remainder of the quotient digits.
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8691
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8692 The conditional ``continue'' on line 114 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8693 algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8694 above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8695
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8696 Lines 130, 130 and 134 through 134 manually construct the high accuracy estimations by setting the digits of the two mp\_int
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8697 variables directly.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8698
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8699 \section{Single Digit Helpers}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8700
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8701 This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8702 the helper functions assume the single digit input is positive and will treat them as such.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8703
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8704 \subsection{Single Digit Addition and Subtraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8705
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8706 Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8707 algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8708
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8709 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8710 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8711 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8712 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8713 \hline Algorithm \textbf{mp\_add\_d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8714 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8715 \textbf{Output}. $c = a + b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8716 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8717 1. $t \leftarrow b$ (\textit{mp\_set}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8718 2. $c \leftarrow a + t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8719 3. Return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8720 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8721 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8722 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8723 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8724 \caption{Algorithm mp\_add\_d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8725 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8726
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8727 \textbf{Algorithm mp\_add\_d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8728 This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8729
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8730 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8731 \hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8732 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8733 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8734 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8735 017 /* single digit addition */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8736 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8737 019 mp_add_d (mp_int * a, mp_digit b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8738 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8739 021 int res, ix, oldused;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8740 022 mp_digit *tmpa, *tmpc, mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8741 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8742 024 /* grow c as required */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8743 025 if (c->alloc < a->used + 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8744 026 if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8745 027 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8746 028 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8747 029 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8748 030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8749 031 /* if a is negative and |a| >= b, call c = |a| - b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8750 032 if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8751 033 /* temporarily fix sign of a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8752 034 a->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8753 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8754 036 /* c = |a| - b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8755 037 res = mp_sub_d(a, b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8756 038
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8757 039 /* fix sign */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8758 040 a->sign = c->sign = MP_NEG;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8759 041
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8760 042 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8761 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8762 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8763 045 /* old number of used digits in c */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8764 046 oldused = c->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8765 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8766 048 /* sign always positive */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8767 049 c->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8768 050
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8769 051 /* source alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8770 052 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8771 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8772 054 /* destination alias */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8773 055 tmpc = c->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8774 056
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8775 057 /* if a is positive */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8776 058 if (a->sign == MP_ZPOS) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8777 059 /* add digit, after this we're propagating
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8778 060 * the carry.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8779 061 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8780 062 *tmpc = *tmpa++ + b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8781 063 mu = *tmpc >> DIGIT_BIT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8782 064 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8783 065
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8784 066 /* now handle rest of the digits */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8785 067 for (ix = 1; ix < a->used; ix++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8786 068 *tmpc = *tmpa++ + mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8787 069 mu = *tmpc >> DIGIT_BIT;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8788 070 *tmpc++ &= MP_MASK;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8789 071 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8790 072 /* set final carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8791 073 ix++;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8792 074 *tmpc++ = mu;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8793 075
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8794 076 /* setup size */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8795 077 c->used = a->used + 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8796 078 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8797 079 /* a was negative and |a| < b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8798 080 c->used = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8799 081
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8800 082 /* the result is a single digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8801 083 if (a->used == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8802 084 *tmpc++ = b - a->dp[0];
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8803 085 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8804 086 *tmpc++ = b;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8805 087 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8806 088
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8807 089 /* setup count so the clearing of oldused
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8808 090 * can fall through correctly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8809 091 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8810 092 ix = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8811 093 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8812 094
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8813 095 /* now zero to oldused */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8814 096 while (ix++ < oldused) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8815 097 *tmpc++ = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8816 098 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8817 099 mp_clamp(c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8818 100
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8819 101 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8820 102 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8821 103
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
8822 104 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8823 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8824 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8825
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8826 Clever use of the letter 't'.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8827
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8828 \subsubsection{Subtraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8829 The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8830
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8831 \subsection{Single Digit Multiplication}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8832 Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8833 multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8834 only has one digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8835
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8836 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8837 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8838 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8839 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8840 \hline Algorithm \textbf{mp\_mul\_d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8841 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8842 \textbf{Output}. $c = ab$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8843 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8844 1. $pa \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8845 2. Grow $c$ to at least $pa + 1$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8846 3. $oldused \leftarrow c.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8847 4. $c.used \leftarrow pa + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8848 5. $c.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8849 6. $\mu \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8850 7. for $ix$ from $0$ to $pa - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8851 \hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8852 \hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8853 \hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8854 8. $c_{pa} \leftarrow \mu$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8855 9. for $ix$ from $pa + 1$ to $oldused$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8856 \hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8857 10. Clamp excess digits of $c$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8858 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8859 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8860 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8861 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8862 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8863 \caption{Algorithm mp\_mul\_d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8864 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8865 \textbf{Algorithm mp\_mul\_d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8866 This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8867 Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8868
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8869 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8870 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8871 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8872 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8873 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8874 017 /* multiply by a digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8875 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8876 019 mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8877 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8878 021 mp_digit u, *tmpa, *tmpc;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8879 022 mp_word r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8880 023 int ix, res, olduse;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8881 024
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8882 025 /* make sure c is big enough to hold a*b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8883 026 if (c->alloc < a->used + 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8884 027 if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8885 028 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8886 029 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8887 030 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8888 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8889 032 /* get the original destinations used count */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8890 033 olduse = c->used;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8891 034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8892 035 /* set the sign */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8893 036 c->sign = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8894 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8895 038 /* alias for a->dp [source] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8896 039 tmpa = a->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8897 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8898 041 /* alias for c->dp [dest] */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8899 042 tmpc = c->dp;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8900 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8901 044 /* zero carry */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8902 045 u = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8903 046
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8904 047 /* compute columns */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8905 048 for (ix = 0; ix < a->used; ix++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8906 049 /* compute product and carry sum for this term */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8907 050 r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8908 051
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8909 052 /* mask off higher bits to get a single digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8910 053 *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8911 054
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8912 055 /* send carry into next iteration */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8913 056 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8914 057 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8915 058
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8916 059 /* store final carry [if any] and increment ix offset */
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8917 060 *tmpc++ = u;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8918 061 ++ix;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8919 062
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8920 063 /* now zero digits above the top */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8921 064 while (ix++ < olduse) \{
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8922 065 *tmpc++ = 0;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8923 066 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8924 067
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8925 068 /* set used count */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8926 069 c->used = a->used + 1;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8927 070 mp_clamp(c);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8928 071
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8929 072 return MP_OKAY;
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8930 073 \}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
8931 074 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8932 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8933 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8934
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8935 In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8936 read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8937
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8938 \subsection{Single Digit Division}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8939 Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8940 divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8941
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8942 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8943 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8944 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8945 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8946 \hline Algorithm \textbf{mp\_div\_d}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8947 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8948 \textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8949 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8950 1. If $b = 0$ then return(\textit{MP\_VAL}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8951 2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8952 3. Init $q$ to $a.used$ digits. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8953 4. $q.used \leftarrow a.used$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8954 5. $q.sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8955 6. $\hat w \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8956 7. for $ix$ from $a.used - 1$ down to $0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8957 \hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8958 \hspace{3mm}7.2 If $\hat w \ge b$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8959 \hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8960 \hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8961 \hspace{3mm}7.3 else\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8962 \hspace{6mm}7.3.1 $t \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8963 \hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8964 8. $d \leftarrow \hat w$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8965 9. Clamp excess digits of $q$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8966 10. $c \leftarrow q$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8967 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8968 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8969 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8970 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8971 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8972 \caption{Algorithm mp\_div\_d}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8973 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8974 \textbf{Algorithm mp\_div\_d.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8975 This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8976 algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8977 after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8978
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8979 If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8980 a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8981 from chapter seven.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8982
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8983 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8984 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8985 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8986 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8987 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8988 017 static int s_is_power_of_two(mp_digit b, int *p)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8989 018 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8990 019 int x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8991 020
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8992 021 for (x = 1; x < DIGIT_BIT; x++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8993 022 if (b == (((mp_digit)1)<<x)) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8994 023 *p = x;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8995 024 return 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8996 025 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8997 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8998 027 return 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8999 028 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9000 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9001 030 /* single digit division (based on routine from MPI) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9002 031 int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9003 032 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9004 033 mp_int q;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9005 034 mp_word w;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9006 035 mp_digit t;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9007 036 int res, ix;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9008 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9009 038 /* cannot divide by zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9010 039 if (b == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9011 040 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9012 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9013 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9014 043 /* quick outs */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9015 044 if (b == 1 || mp_iszero(a) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9016 045 if (d != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9017 046 *d = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9018 047 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9019 048 if (c != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9020 049 return mp_copy(a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9021 050 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9022 051 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9023 052 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9024 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9025 054 /* power of two ? */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9026 055 if (s_is_power_of_two(b, &ix) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9027 056 if (d != NULL) \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9028 057 *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9029 058 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9030 059 if (c != NULL) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9031 060 return mp_div_2d(a, ix, c, NULL);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9032 061 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9033 062 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9034 063 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9035 064
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9036 065 #ifdef BN_MP_DIV_3_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9037 066 /* three? */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9038 067 if (b == 3) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9039 068 return mp_div_3(a, c, d);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9040 069 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9041 070 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9042 071
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9043 072 /* no easy answer [c'est la vie]. Just division */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9044 073 if ((res = mp_init_size(&q, a->used)) != MP_OKAY) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9045 074 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9046 075 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9047 076
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9048 077 q.used = a->used;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9049 078 q.sign = a->sign;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9050 079 w = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9051 080 for (ix = a->used - 1; ix >= 0; ix--) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9052 081 w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9053 082
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9054 083 if (w >= b) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9055 084 t = (mp_digit)(w / b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9056 085 w -= ((mp_word)t) * ((mp_word)b);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9057 086 \} else \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9058 087 t = 0;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9059 088 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9060 089 q.dp[ix] = (mp_digit)t;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9061 090 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9062 091
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9063 092 if (d != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9064 093 *d = (mp_digit)w;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9065 094 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9066 095
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9067 096 if (c != NULL) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9068 097 mp_clamp(&q);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9069 098 mp_exch(&q, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9070 099 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9071 100 mp_clear(&q);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9072 101
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9073 102 return res;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9074 103 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9075 104
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9076 105 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9077 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9078 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9080 Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9081 indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9082
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9083 The division and remainder on lines 43 and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9084 processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9085 compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9086
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9087 \subsection{Single Digit Root Extraction}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9088
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9089 Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9090 (\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9091
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9092 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9093 x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9094 \label{eqn:newton}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9095 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9096
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9097 In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9098 simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9099 such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9100 algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9101
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9102 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9103 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9104 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9105 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9106 \hline Algorithm \textbf{mp\_n\_root}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9107 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9108 \textbf{Output}. $c^b \le a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9109 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9110 1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9111 2. $sign \leftarrow a.sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9112 3. $a.sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9113 4. t$2 \leftarrow 2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9114 5. Loop \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9115 \hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9116 \hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9117 \hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9118 \hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9119 \hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9120 \hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9121 \hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9122 \hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9123 6. Loop \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9124 \hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9125 \hspace{3mm}6.2 If t$2 > a$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9126 \hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9127 \hspace{6mm}6.2.2 Goto step 6. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9128 7. $a.sign \leftarrow sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9129 8. $c \leftarrow $ t$1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9130 9. $c.sign \leftarrow sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9131 10. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9132 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9133 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9134 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9135 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9136 \caption{Algorithm mp\_n\_root}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9137 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9138 \textbf{Algorithm mp\_n\_root.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9139 This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9140 that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9141 $x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9142 multiplications by t$1$ inside the loop.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9143
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9144 The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9145 root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9146
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9147 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9148 \hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9149 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9150 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9151 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9152 017 /* find the n'th root of an integer
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9153 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9154 019 * Result found such that (c)**b <= a and (c+1)**b > a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9155 020 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9156 021 * This algorithm uses Newton's approximation
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9157 022 * x[i+1] = x[i] - f(x[i])/f'(x[i])
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9158 023 * which will find the root in log(N) time where
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9159 024 * each step involves a fair bit. This is not meant to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9160 025 * find huge roots [square and cube, etc].
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9161 026 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9162 027 int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9163 028 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9164 029 mp_int t1, t2, t3;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9165 030 int res, neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9166 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9167 032 /* input must be positive if b is even */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9168 033 if ((b & 1) == 0 && a->sign == MP_NEG) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9169 034 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9170 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9171 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9172 037 if ((res = mp_init (&t1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9173 038 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9174 039 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9175 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9176 041 if ((res = mp_init (&t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9177 042 goto LBL_T1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9178 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9179 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9180 045 if ((res = mp_init (&t3)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9181 046 goto LBL_T2;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9182 047 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9183 048
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9184 049 /* if a is negative fudge the sign but keep track */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9185 050 neg = a->sign;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9186 051 a->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9187 052
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9188 053 /* t2 = 2 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9189 054 mp_set (&t2, 2);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9190 055
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9191 056 do \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9192 057 /* t1 = t2 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9193 058 if ((res = mp_copy (&t2, &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9194 059 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9195 060 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9196 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9197 062 /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9198 063
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9199 064 /* t3 = t1**(b-1) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9200 065 if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9201 066 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9202 067 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9203 068
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9204 069 /* numerator */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9205 070 /* t2 = t1**b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9206 071 if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9207 072 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9208 073 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9209 074
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9210 075 /* t2 = t1**b - a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9211 076 if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9212 077 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9213 078 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9214 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9215 080 /* denominator */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9216 081 /* t3 = t1**(b-1) * b */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9217 082 if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9218 083 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9219 084 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9220 085
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9221 086 /* t3 = (t1**b - a)/(b * t1**(b-1)) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9222 087 if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9223 088 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9224 089 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9225 090
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9226 091 if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9227 092 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9228 093 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9229 094 \} while (mp_cmp (&t1, &t2) != MP_EQ);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9230 095
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9231 096 /* result can be off by a few so check */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9232 097 for (;;) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9233 098 if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9234 099 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9235 100 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9236 101
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9237 102 if (mp_cmp (&t2, a) == MP_GT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9238 103 if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9239 104 goto LBL_T3;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9240 105 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9241 106 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9242 107 break;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9243 108 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9244 109 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9245 110
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9246 111 /* reset the sign of a first */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9247 112 a->sign = neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9248 113
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9249 114 /* set the result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9250 115 mp_exch (&t1, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9251 116
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9252 117 /* set the sign of the result */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9253 118 c->sign = neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9254 119
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9255 120 res = MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9256 121
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9257 122 LBL_T3:mp_clear (&t3);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9258 123 LBL_T2:mp_clear (&t2);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9259 124 LBL_T1:mp_clear (&t1);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9260 125 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9261 126 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9262 127 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9263 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9264 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9265
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9266 \section{Random Number Generation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9267
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9268 Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9269 factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9270 is solely for simulations and not intended for cryptographic use.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9271
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9272 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9273 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9274 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9275 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9276 \hline Algorithm \textbf{mp\_rand}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9277 \textbf{Input}. An integer $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9278 \textbf{Output}. A pseudo-random number of $b$ digits \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9279 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9280 1. $a \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9281 2. If $b \le 0$ return(\textit{MP\_OKAY}) \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9282 3. Pick a non-zero random digit $d$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9283 4. $a \leftarrow a + d$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9284 5. for $ix$ from 1 to $d - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9285 \hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9286 \hspace{3mm}5.2 Pick a random digit $d$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9287 \hspace{3mm}5.3 $a \leftarrow a + d$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9288 6. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9289 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9290 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9291 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9292 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9293 \caption{Algorithm mp\_rand}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9294 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9295 \textbf{Algorithm mp\_rand.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9296 This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9297 final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9298 the integers from $0$ to $\beta - 1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9299
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9300 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9301 \hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9302 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9303 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9304 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9305 017 /* makes a pseudo-random int of a given size */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9306 018 int
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9307 019 mp_rand (mp_int * a, int digits)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9308 020 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9309 021 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9310 022 mp_digit d;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9311 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9312 024 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9313 025 if (digits <= 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9314 026 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9315 027 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9316 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9317 029 /* first place a random non-zero digit */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9318 030 do \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9319 031 d = ((mp_digit) abs (rand ())) & MP_MASK;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9320 032 \} while (d == 0);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9321 033
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9322 034 if ((res = mp_add_d (a, d, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9323 035 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9324 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9325 037
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9326 038 while (--digits > 0) \{
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9327 039 if ((res = mp_lshd (a, 1)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9328 040 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9329 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9330 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9331 043 if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9332 044 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9333 045 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9334 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9335 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9336 048 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9337 049 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9338 050 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9339 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9340 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9341
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9342 \section{Formatted Representations}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9343 The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9344 be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9345 into a program.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9346
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9347 \subsection{Reading Radix-n Input}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9348 For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9349 printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9350 map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9351 such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9352 mediums.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9353
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9354 \newpage\begin{figure}[here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9355 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9356 \begin{tabular}{cc|cc|cc|cc}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9357 \hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9358 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9359 0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9360 4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9361 8 & 8 & 9 & 9 & 10 & A & 11 & B \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9362 12 & C & 13 & D & 14 & E & 15 & F \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9363 16 & G & 17 & H & 18 & I & 19 & J \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9364 20 & K & 21 & L & 22 & M & 23 & N \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9365 24 & O & 25 & P & 26 & Q & 27 & R \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9366 28 & S & 29 & T & 30 & U & 31 & V \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9367 32 & W & 33 & X & 34 & Y & 35 & Z \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9368 36 & a & 37 & b & 38 & c & 39 & d \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9369 40 & e & 41 & f & 42 & g & 43 & h \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9370 44 & i & 45 & j & 46 & k & 47 & l \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9371 48 & m & 49 & n & 50 & o & 51 & p \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9372 52 & q & 53 & r & 54 & s & 55 & t \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9373 56 & u & 57 & v & 58 & w & 59 & x \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9374 60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9375 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9376 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9377 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9378 \caption{Lower ASCII Map}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9379 \label{fig:ASC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9380 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9381
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9382 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9383 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9384 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9385 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9386 \hline Algorithm \textbf{mp\_read\_radix}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9387 \textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9388 \textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9389 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9390 1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9391 2. $ix \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9392 3. If $str_0 =$ ``-'' then do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9393 \hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9394 \hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9395 4. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9396 \hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9397 5. $a \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9398 6. for $iy$ from $ix$ to $sn - 1$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9399 \hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9400 \hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9401 \hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9402 \hspace{3mm}6.4 $a \leftarrow a + y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9403 7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9404 8. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9405 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9406 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9407 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9408 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9409 \caption{Algorithm mp\_read\_radix}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9410 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9411 \textbf{Algorithm mp\_read\_radix.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9412 This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9413 string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9414 and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9415 as part of larger input without any significant problem.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9416
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9417 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9418 \hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9419 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9420 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9421 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9422 017 /* read a string [ASCII] in a given radix */
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9423 018 int mp_read_radix (mp_int * a, const char *str, int radix)
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9424 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9425 020 int y, res, neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9426 021 char ch;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9427 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9428 023 /* make sure the radix is ok */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9429 024 if (radix < 2 || radix > 64) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9430 025 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9431 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9432 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9433 028 /* if the leading digit is a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9434 029 * minus set the sign to negative.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9435 030 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9436 031 if (*str == '-') \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9437 032 ++str;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9438 033 neg = MP_NEG;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9439 034 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9440 035 neg = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9441 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9442 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9443 038 /* set the integer to the default of zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9444 039 mp_zero (a);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9445 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9446 041 /* process each digit of the string */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9447 042 while (*str) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9448 043 /* if the radix < 36 the conversion is case insensitive
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9449 044 * this allows numbers like 1AB and 1ab to represent the same value
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9450 045 * [e.g. in hex]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9451 046 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9452 047 ch = (char) ((radix < 36) ? toupper (*str) : *str);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9453 048 for (y = 0; y < 64; y++) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9454 049 if (ch == mp_s_rmap[y]) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9455 050 break;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9456 051 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9457 052 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9458 053
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9459 054 /* if the char was found in the map
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9460 055 * and is less than the given radix add it
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9461 056 * to the number, otherwise exit the loop.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9462 057 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9463 058 if (y < radix) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9464 059 if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9465 060 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9466 061 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9467 062 if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9468 063 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9469 064 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9470 065 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9471 066 break;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9472 067 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9473 068 ++str;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9474 069 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9475 070
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9476 071 /* set the sign only if a != 0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9477 072 if (mp_iszero(a) != 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9478 073 a->sign = neg;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9479 074 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9480 075 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9481 076 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9482 077 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9483 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9484 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9485
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9486 \subsection{Generating Radix-$n$ Output}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9487 Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9488
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9489 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9490 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9491 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9492 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9493 \hline Algorithm \textbf{mp\_toradix}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9494 \textbf{Input}. A mp\_int $a$ and an integer $r$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9495 \textbf{Output}. The radix-$r$ representation of $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9496 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9497 1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9498 2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9499 3. $t \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9500 4. $str \leftarrow$ ``'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9501 5. if $t.sign = MP\_NEG$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9502 \hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9503 \hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9504 6. While ($t \ne 0$) do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9505 \hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9506 \hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9507 \hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9508 \hspace{3mm}6.4 $str \leftarrow str + y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9509 7. If $str_0 = $``$-$'' then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9510 \hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9511 8. Otherwise \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9512 \hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9513 9. Return(\textit{MP\_OKAY}).\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9514 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9515 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9516 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9517 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9518 \caption{Algorithm mp\_toradix}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9519 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9520 \textbf{Algorithm mp\_toradix.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9521 This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9522 successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9523 each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9524 are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9525 (see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9526
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9527 \begin{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9528 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9529 \begin{tabular}{|c|c|c|}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9530 \hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9531 \hline $1234$ & -- & -- \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9532 \hline $123$ & $4$ & ``4'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9533 \hline $12$ & $3$ & ``43'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9534 \hline $1$ & $2$ & ``432'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9535 \hline $0$ & $1$ & ``4321'' \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9536 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9537 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9538 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9539 \caption{Example of Algorithm mp\_toradix.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9540 \label{fig:mpradix}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9541 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9542
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9543 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9544 \hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9545 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9546 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9547 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9548 017 /* stores a bignum as a ASCII string in a given radix (2..64) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9549 018 int mp_toradix (mp_int * a, char *str, int radix)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9550 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9551 020 int res, digs;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9552 021 mp_int t;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9553 022 mp_digit d;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9554 023 char *_s = str;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9555 024
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9556 025 /* check range of the radix */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9557 026 if (radix < 2 || radix > 64) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9558 027 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9559 028 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9560 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9561 030 /* quick out if its zero */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9562 031 if (mp_iszero(a) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9563 032 *str++ = '0';
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9564 033 *str = '\symbol{92}0';
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9565 034 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9566 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9567 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9568 037 if ((res = mp_init_copy (&t, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9569 038 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9570 039 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9571 040
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9572 041 /* if it is negative output a - */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9573 042 if (t.sign == MP_NEG) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9574 043 ++_s;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9575 044 *str++ = '-';
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9576 045 t.sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9577 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9578 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9579 048 digs = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9580 049 while (mp_iszero (&t) == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9581 050 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9582 051 mp_clear (&t);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9583 052 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9584 053 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9585 054 *str++ = mp_s_rmap[d];
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9586 055 ++digs;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9587 056 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9588 057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9589 058 /* reverse the digits of the string. In this case _s points
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9590 059 * to the first digit [exluding the sign] of the number]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9591 060 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9592 061 bn_reverse ((unsigned char *)_s, digs);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9593 062
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9594 063 /* append a NULL so the string is properly terminated */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9595 064 *str = '\symbol{92}0';
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9596 065
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9597 066 mp_clear (&t);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9598 067 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9599 068 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9600 069
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9601 070 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9602 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9603 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9604
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9605 \chapter{Number Theoretic Algorithms}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9606 This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9607 symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9608 various Sieve based factoring algorithms.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9609
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9610 \section{Greatest Common Divisor}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9611 The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9612 both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9613 simultaneously.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9614
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9615 The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9616 $r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9617
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9618 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9619 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9620 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9621 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9622 \hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9623 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9624 \textbf{Output}. The greatest common divisor $(a, b)$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9625 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9626 1. While ($b > 0$) do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9627 \hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9628 \hspace{3mm}1.2 $a \leftarrow b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9629 \hspace{3mm}1.3 $b \leftarrow r$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9630 2. Return($a$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9631 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9632 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9633 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9634 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9635 \caption{Algorithm Greatest Common Divisor (I)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9636 \label{fig:gcd1}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9637 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9638
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9639 This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9640 relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9641 greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9642 In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9643
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9644 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9645 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9646 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9647 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9648 \hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9649 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9650 \textbf{Output}. The greatest common divisor $(a, b)$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9651 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9652 1. While ($b > 0$) do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9653 \hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9654 \hspace{3mm}1.2 $b \leftarrow b - a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9655 2. Return($a$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9656 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9657 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9658 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9659 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9660 \caption{Algorithm Greatest Common Divisor (II)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9661 \label{fig:gcd2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9662 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9663
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9664 \textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9665 The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9666 words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9667 divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9668 second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9669
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9670 As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9671 $b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9672 not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9673 the greatest common divisor.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9674
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9675 However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9676 Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9677
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9678 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9679 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9680 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9681 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9682 \hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9683 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9684 \textbf{Output}. The greatest common divisor $(a, b)$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9685 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9686 1. $k \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9687 2. While $a$ and $b$ are both divisible by $p$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9688 \hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9689 \hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9690 \hspace{3mm}2.3 $k \leftarrow k + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9691 3. While $a$ is divisible by $p$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9692 \hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9693 4. While $b$ is divisible by $p$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9694 \hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9695 5. While ($b > 0$) do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9696 \hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9697 \hspace{3mm}5.2 $b \leftarrow b - a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9698 \hspace{3mm}5.3 While $b$ is divisible by $p$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9699 \hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9700 6. Return($a \cdot p^k$). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9701 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9702 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9703 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9704 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9705 \caption{Algorithm Greatest Common Divisor (III)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9706 \label{fig:gcd3}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9707 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9708
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9709 This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9710 decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9711 divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9712 divided out of the difference $b - a$ so long as the division leaves no remainder.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9713
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9714 In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9715 to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9716 step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9717 largest of the pair.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9718
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9719 \subsection{Complete Greatest Common Divisor}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9720 The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9721 and will produce the greatest common divisor.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9722
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9723 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9724 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9725 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9726 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9727 \hline Algorithm \textbf{mp\_gcd}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9728 \textbf{Input}. mp\_int $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9729 \textbf{Output}. The greatest common divisor $c = (a, b)$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9730 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9731 1. If $a = 0$ and $b \ne 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9732 \hspace{3mm}1.1 $c \leftarrow b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9733 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9734 2. If $a \ne 0$ and $b = 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9735 \hspace{3mm}2.1 $c \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9736 \hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9737 3. If $a = b = 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9738 \hspace{3mm}3.1 $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9739 \hspace{3mm}3.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9740 4. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9741 5. $k \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9742 6. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9743 \hspace{3mm}6.1 $k \leftarrow k + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9744 \hspace{3mm}6.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9745 \hspace{3mm}6.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9746 7. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9747 \hspace{3mm}7.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9748 8. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9749 \hspace{3mm}8.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9750 9. While $v.used > 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9751 \hspace{3mm}9.1 If $\vert u \vert > \vert v \vert$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9752 \hspace{6mm}9.1.1 Swap $u$ and $v$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9753 \hspace{3mm}9.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9754 \hspace{3mm}9.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9755 \hspace{6mm}9.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9756 10. $c \leftarrow u \cdot 2^k$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9757 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9758 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9759 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9760 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9761 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9762 \caption{Algorithm mp\_gcd}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9763 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9764 \textbf{Algorithm mp\_gcd.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9765 This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9766 Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9767 Algorithm B and in practice this appears to be true.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9768
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9769 The first three steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9770 largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9771 $a$ and $b$ respectively and the algorithm will proceed to reduce the pair.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9772
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9773 Step six will divide out any common factors of two and keep track of the count in the variable $k$. After this step two is no longer a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9774 factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9775 seven and eight ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while loops will iterate since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9776 they cannot both be even.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9777
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9778 By step nine both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9779 or greater than $u$. This ensures that the subtraction on step 9.2 will always produce a positive and even result. Step 9.3 removes any
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9780 factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9781
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9782 After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9783 must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9784
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9785 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9786 \hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9787 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9788 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9789 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9790 017 /* Greatest Common Divisor using the binary method */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9791 018 int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9792 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9793 020 mp_int u, v;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9794 021 int k, u_lsb, v_lsb, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9795 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9796 023 /* either zero than gcd is the largest */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9797 024 if (mp_iszero (a) == 1 && mp_iszero (b) == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9798 025 return mp_abs (b, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9799 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9800 027 if (mp_iszero (a) == 0 && mp_iszero (b) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9801 028 return mp_abs (a, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9802 029 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9803 030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9804 031 /* optimized. At this point if a == 0 then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9805 032 * b must equal zero too
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9806 033 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9807 034 if (mp_iszero (a) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9808 035 mp_zero(c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9809 036 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9810 037 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9811 038
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9812 039 /* get copies of a and b we can modify */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9813 040 if ((res = mp_init_copy (&u, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9814 041 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9815 042 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9816 043
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9817 044 if ((res = mp_init_copy (&v, b)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9818 045 goto LBL_U;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9819 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9820 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9821 048 /* must be positive for the remainder of the algorithm */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9822 049 u.sign = v.sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9823 050
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9824 051 /* B1. Find the common power of two for u and v */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9825 052 u_lsb = mp_cnt_lsb(&u);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9826 053 v_lsb = mp_cnt_lsb(&v);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9827 054 k = MIN(u_lsb, v_lsb);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9828 055
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9829 056 if (k > 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9830 057 /* divide the power of two out */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9831 058 if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9832 059 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9833 060 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9834 061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9835 062 if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9836 063 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9837 064 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9838 065 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9839 066
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9840 067 /* divide any remaining factors of two out */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9841 068 if (u_lsb != k) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9842 069 if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9843 070 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9844 071 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9845 072 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9846 073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9847 074 if (v_lsb != k) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9848 075 if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9849 076 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9850 077 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9851 078 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9852 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9853 080 while (mp_iszero(&v) == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9854 081 /* make sure v is the largest */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9855 082 if (mp_cmp_mag(&u, &v) == MP_GT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9856 083 /* swap u and v to make sure v is >= u */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9857 084 mp_exch(&u, &v);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9858 085 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9859 086
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9860 087 /* subtract smallest from largest */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9861 088 if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9862 089 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9863 090 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9864 091
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9865 092 /* Divide out all factors of two */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9866 093 if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9867 094 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9868 095 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9869 096 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9870 097
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9871 098 /* multiply by 2**k which we divided out at the beginning */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9872 099 if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9873 100 goto LBL_V;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9874 101 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9875 102 c->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9876 103 res = MP_OKAY;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9877 104 LBL_V:mp_clear (&u);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9878 105 LBL_U:mp_clear (&v);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9879 106 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9880 107 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9881 108 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9882 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9883 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9884
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9885 This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9886 integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9887 it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9888 trivial cases of inputs are handled on lines 24 through 37. After those lines the inputs are assumed to be non-zero.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9889
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9890 Lines 34 and 40 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9891 must be divided out of the two inputs. The while loop on line 80 iterates so long as both are even. The local integer $k$ is used to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9892 keep track of how many factors of $2$ are pulled out of both values. It is assumed that the number of factors will not exceed the maximum
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9893 value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than entries than are accessible by an ``int'' so this is not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9894 a limitation.}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9895
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9896 At this point there are no more common factors of two in the two values. The while loops on lines 80 and 80 remove any independent
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9897 factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9898 on line 80 performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9899 place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9900
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9901 \section{Least Common Multiple}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9902 The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9903 least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9904 and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9905
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9906 The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9907 collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9908 Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9909 Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9910
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9911 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9912 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9913 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9914 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9915 \hline Algorithm \textbf{mp\_lcm}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9916 \textbf{Input}. mp\_int $a$ and $b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9917 \textbf{Output}. The least common multiple $c = [a, b]$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9918 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9919 1. $c \leftarrow (a, b)$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9920 2. $t \leftarrow a \cdot b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9921 3. $c \leftarrow \lfloor t / c \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9922 4. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9923 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9924 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9925 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9926 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9927 \caption{Algorithm mp\_lcm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9928 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9929 \textbf{Algorithm mp\_lcm.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9930 This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9931 dividing the product of the two inputs by their greatest common divisor.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9932
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9933 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9934 \hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9935 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9936 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9937 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9938 017 /* computes least common multiple as |a*b|/(a, b) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9939 018 int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9940 019 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9941 020 int res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9942 021 mp_int t1, t2;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9943 022
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9944 023
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9945 024 if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9946 025 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9947 026 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9948 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9949 028 /* t1 = get the GCD of the two inputs */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9950 029 if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9951 030 goto LBL_T;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9952 031 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9953 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9954 033 /* divide the smallest by the GCD */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9955 034 if (mp_cmp_mag(a, b) == MP_LT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9956 035 /* store quotient in t2 such that t2 * b is the LCM */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9957 036 if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9958 037 goto LBL_T;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9959 038 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9960 039 res = mp_mul(b, &t2, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9961 040 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9962 041 /* store quotient in t2 such that t2 * a is the LCM */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9963 042 if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9964 043 goto LBL_T;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9965 044 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9966 045 res = mp_mul(a, &t2, c);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9967 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9968 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9969 048 /* fix the sign to positive */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9970 049 c->sign = MP_ZPOS;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9971 050
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9972 051 LBL_T:
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9973 052 mp_clear_multi (&t1, &t2, NULL);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9974 053 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9975 054 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
9976 055 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9977 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9978 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9979
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9980 \section{Jacobi Symbol Computation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9981 To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9982 defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9983 equivalent to equation \ref{eqn:legendre}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9984
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9985 \textit{-- Tom, don't be an ass, cite your source here...!}
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
9986
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9987 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9988 a^{(p-1)/2} \equiv \begin{array}{rl}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9989 -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9990 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9991 1 & \mbox{if }a\mbox{ is a quadratic residue}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9992 \end{array} \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9993 \label{eqn:legendre}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9994 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9995
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9996 \textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9997 An integer $a$ is a quadratic residue if the following equation has a solution.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9998
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9999 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10000 x^2 \equiv a \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10001 \label{eqn:root}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10002 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10003
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10004 Consider the following equation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10005
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10006 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10007 0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10008 \label{eqn:rooti}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10009 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10010
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10011 Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10012 then the quantity in the braces must be zero. By reduction,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10013
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10014 \begin{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10015 \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10016 \left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10017 x^2 \equiv a \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10018 \end{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10019
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10020 As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10021 is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10022 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10023 0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10024 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10025 One of the terms on the right hand side must be zero. \textbf{QED}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10027 \subsection{Jacobi Symbol}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10028 The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10029 the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10031 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10032 \left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10033 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10034
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10035 By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10036 further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10037 following are true.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10038
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10039 \begin{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10040 \item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10041 \item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10042 \item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10043 \item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10044 \item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10045 $\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10046 \end{enumerate}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10048 Using these facts if $a = 2^k \cdot a'$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10049
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10050 \begin{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10051 \left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10052 = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right )
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10053 \label{eqn:jacobi}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10054 \end{eqnarray}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10055
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10056 By fact five,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10057
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10058 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10059 \left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10060 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10061
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10062 Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10063
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10064 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10065 \left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10066 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10068 By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10069
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10070 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10071 \left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10072 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10073
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10074 The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10075 $\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10076 factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10077 Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10078
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10079 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10080 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10081 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10082 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10083 \hline Algorithm \textbf{mp\_jacobi}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10084 \textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10085 \textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10086 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10087 1. If $a = 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10088 \hspace{3mm}1.1 $c \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10089 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10090 2. If $a = 1$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10091 \hspace{3mm}2.1 $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10092 \hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10093 3. $a' \leftarrow a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10094 4. $k \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10095 5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10096 \hspace{3mm}5.1 $k \leftarrow k + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10097 \hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10098 6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10099 \hspace{3mm}6.1 $s \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10100 7. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10101 \hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10102 \hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10103 \hspace{6mm}7.2.1 $s \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10104 \hspace{3mm}7.3 else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10105 \hspace{6mm}7.3.1 $s \leftarrow -1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10106 8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10107 \hspace{3mm}8.1 $s \leftarrow -s$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10108 9. If $a' \ne 1$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10109 \hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10110 \hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10111 10. $c \leftarrow s$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10112 11. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10113 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10114 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10115 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10116 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10117 \caption{Algorithm mp\_jacobi}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10118 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10119 \textbf{Algorithm mp\_jacobi.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10120 This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10121 is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10122
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10123 Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10124 input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10125 if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10126 the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10127 are congruent to one modulo four, otherwise it evaluates to negative one.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10128
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10129 By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10130 $\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10131
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10132 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10133 \hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10134 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10135 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10136 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10137 017 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10138 018 * HAC pp. 73 Algorithm 2.149
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10139 019 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10140 020 int mp_jacobi (mp_int * a, mp_int * p, int *c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10141 021 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10142 022 mp_int a1, p1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10143 023 int k, s, r, res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10144 024 mp_digit residue;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10145 025
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10146 026 /* if p <= 0 return MP_VAL */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10147 027 if (mp_cmp_d(p, 0) != MP_GT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10148 028 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10149 029 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10150 030
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10151 031 /* step 1. if a == 0, return 0 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10152 032 if (mp_iszero (a) == 1) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10153 033 *c = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10154 034 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10155 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10156 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10157 037 /* step 2. if a == 1, return 1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10158 038 if (mp_cmp_d (a, 1) == MP_EQ) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10159 039 *c = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10160 040 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10161 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10162 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10163 043 /* default */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10164 044 s = 0;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10165 045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10166 046 /* step 3. write a = a1 * 2**k */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10167 047 if ((res = mp_init_copy (&a1, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10168 048 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10169 049 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10170 050
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10171 051 if ((res = mp_init (&p1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10172 052 goto LBL_A1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10173 053 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10174 054
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10175 055 /* divide out larger power of two */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10176 056 k = mp_cnt_lsb(&a1);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10177 057 if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10178 058 goto LBL_P1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10179 059 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10180 060
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10181 061 /* step 4. if e is even set s=1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10182 062 if ((k & 1) == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10183 063 s = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10184 064 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10185 065 /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10186 066 residue = p->dp[0] & 7;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10187 067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10188 068 if (residue == 1 || residue == 7) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10189 069 s = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10190 070 \} else if (residue == 3 || residue == 5) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10191 071 s = -1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10192 072 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10193 073 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10194 074
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10195 075 /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10196 076 if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10197 077 s = -s;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10198 078 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10199 079
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10200 080 /* if a1 == 1 we're done */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10201 081 if (mp_cmp_d (&a1, 1) == MP_EQ) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10202 082 *c = s;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10203 083 \} else \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10204 084 /* n1 = n mod a1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10205 085 if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10206 086 goto LBL_P1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10207 087 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10208 088 if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10209 089 goto LBL_P1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10210 090 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10211 091 *c = s * r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10212 092 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10213 093
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10214 094 /* done */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10215 095 res = MP_OKAY;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10216 096 LBL_P1:mp_clear (&p1);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10217 097 LBL_A1:mp_clear (&a1);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10218 098 return res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10219 099 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10220 100 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10221 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10222 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10223
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10224 As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10225 variable name character.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10226
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10227 The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10228 has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10229 the values it may obtain are merely $-1$, $0$ and $1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10230
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10231 After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10232 bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10233 processor requirements and neither is faster than the other.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10234
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10235 Line 61 through 70 determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10236 $k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10237 $(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 75 through 73.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10238
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10239 Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10240
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10241 \textit{-- Comment about default $s$ and such...}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10242
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10243 \section{Modular Inverse}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10244 \label{sec:modinv}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10245 The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10246 exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10247 denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10248 fields of integers. However, the former will be the matter of discussion.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10249
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10250 The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10251 order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10252
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10253 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10254 ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10255 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10256
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10257 However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10258 requires all of the prime factors. This approach also is very slow as the size of $p$ grows.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10259
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10260 A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10261 Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10262
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10263 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10264 ab + pq = 1
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10265 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10266
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10267 Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10268 $a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10269 However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10270 binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10271 equation.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10272
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10273 \subsection{General Case}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10274 \newpage\begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10275 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10276 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10277 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10278 \hline Algorithm \textbf{mp\_invmod}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10279 \textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10280 \textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10281 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10282 1. If $b \le 0$ then return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10283 2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10284 3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10285 4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10286 5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10287 6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10288 \hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10289 \hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10290 \hspace{6mm}6.2.1 $A \leftarrow A + y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10291 \hspace{6mm}6.2.2 $B \leftarrow B - x$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10292 \hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10293 \hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10294 7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10295 \hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10296 \hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10297 \hspace{6mm}7.2.1 $C \leftarrow C + y$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10298 \hspace{6mm}7.2.2 $D \leftarrow D - x$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10299 \hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10300 \hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10301 8. If $u \ge v$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10302 \hspace{3mm}8.1 $u \leftarrow u - v$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10303 \hspace{3mm}8.2 $A \leftarrow A - C$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10304 \hspace{3mm}8.3 $B \leftarrow B - D$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10305 9. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10306 \hspace{3mm}9.1 $v \leftarrow v - u$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10307 \hspace{3mm}9.2 $C \leftarrow C - A$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10308 \hspace{3mm}9.3 $D \leftarrow D - B$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10309 10. If $u \ne 0$ goto step 6. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10310 11. If $v \ne 1$ return(\textit{MP\_VAL}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10311 12. While $C \le 0$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10312 \hspace{3mm}12.1 $C \leftarrow C + b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10313 13. While $C \ge b$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10314 \hspace{3mm}13.1 $C \leftarrow C - b$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10315 14. $c \leftarrow C$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10316 15. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10317 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10318 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10319 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10320 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10321 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10322 \textbf{Algorithm mp\_invmod.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10323 This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10324 extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10325 Diophantine solution.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10326
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10327 If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10328 inverse for $a$ and the error is reported.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10329
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10330 The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10331 the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10332
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10333 \begin{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10334 Ca + Db = v
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10335 \end{equation}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10336
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10337 If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10338 is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10339 within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10340 then only a couple of additions or subtractions will be required to adjust the inverse.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10341
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10342 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10343 \hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10344 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10345 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10346 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10347 017 /* hac 14.61, pp608 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10348 018 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10349 019 \{
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10350 020 /* b cannot be negative */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10351 021 if (b->sign == MP_NEG || mp_iszero(b) == 1) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10352 022 return MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10353 023 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10354 024
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10355 025 #ifdef BN_FAST_MP_INVMOD_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10356 026 /* if the modulus is odd we can use a faster routine instead */
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10357 027 if (mp_isodd (b) == 1) \{
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10358 028 return fast_mp_invmod (a, b, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10359 029 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10360 030 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10361 031
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10362 032 #ifdef BN_MP_INVMOD_SLOW_C
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10363 033 return mp_invmod_slow(a, b, c);
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10364 034 #endif
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10365 035
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10366 036 return MP_VAL;
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10367 037 \}
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10368 038 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10369 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10370 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10371
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10372 \subsubsection{Odd Moduli}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10373
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10374 When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10375 the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10376
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10377 The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10378 optimization will halve the time required to compute the modular inverse.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10379
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10380 \section{Primality Tests}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10381
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10382 A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10383 since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10384
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10385 Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10386 not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10387 probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10388 prime the algorithm may be incorrect.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10389
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10390 As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10391 well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10392
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10393 \subsection{Trial Division}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10394
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10395 Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10396 cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10397 would require a prohibitive amount of time as $n$ grows.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10398
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10399 Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10400 of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10401
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10402 The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10403 discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10404 $1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10405 $3 \le q \le 100$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10406
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10407 At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10408 be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10409 approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10410 array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10411
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10412 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10413 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10414 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10415 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10416 \hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10417 \textbf{Input}. mp\_int $a$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10418 \textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10419 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10420 1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10421 \hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10422 \hspace{3mm}1.2 If $d = 0$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10423 \hspace{6mm}1.2.1 $c \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10424 \hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10425 2. $c \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10426 3. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10427 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10428 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10429 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10430 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10431 \caption{Algorithm mp\_prime\_is\_divisible}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10432 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10433 \textbf{Algorithm mp\_prime\_is\_divisible.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10434 This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10435
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10436 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10437 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10438 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10439 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10440 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10441 017 /* determines if an integers is divisible by one
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10442 018 * of the first PRIME_SIZE primes or not
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10443 019 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10444 020 * sets result to 0 if not, 1 if yes
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10445 021 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10446 022 int mp_prime_is_divisible (mp_int * a, int *result)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10447 023 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10448 024 int err, ix;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10449 025 mp_digit res;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10450 026
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10451 027 /* default to not */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10452 028 *result = MP_NO;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10453 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10454 030 for (ix = 0; ix < PRIME_SIZE; ix++) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10455 031 /* what is a mod LBL_prime_tab[ix] */
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10456 032 if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) \{
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10457 033 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10458 034 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10459 035
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10460 036 /* is the residue zero? */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10461 037 if (res == 0) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10462 038 *result = MP_YES;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10463 039 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10464 040 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10465 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10466 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10467 043 return MP_OKAY;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10468 044 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10469 045 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10470 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10471 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10472
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10473 The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10474 mp\_digit. The table \_\_prime\_tab is defined in the following file.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10475
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10476 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10477 \hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10478 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10479 \begin{alltt}
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10480 016 const mp_digit ltm_prime_tab[] = \{
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10481 017 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10482 018 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10483 019 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10484 020 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10485 021 #ifndef MP_8BIT
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10486 022 0x0083,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10487 023 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10488 024 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10489 025 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10490 026 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10491 027
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10492 028 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10493 029 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10494 030 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10495 031 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10496 032 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10497 033 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10498 034 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10499 035 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10500 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10501 037 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10502 038 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10503 039 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10504 040 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10505 041 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10506 042 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10507 043 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10508 044 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10509 045
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10510 046 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10511 047 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10512 048 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10513 049 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10514 050 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10515 051 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10516 052 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10517 053 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10518 054 #endif
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10519 055 \};
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10520 056 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10521 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10522 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10523
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10524 Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10525 upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10526
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10527 \subsection{The Fermat Test}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10528 The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10529 fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10530 the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10531 $a^1 = a$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10532
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10533 If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10534 it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10535 of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10536 integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10537 in size.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10538
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10539 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10540 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10541 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10542 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10543 \hline Algorithm \textbf{mp\_prime\_fermat}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10544 \textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10545 \textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10546 \hline \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10547 1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10548 2. If $t = b$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10549 \hspace{3mm}2.1 $c = 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10550 3. else \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10551 \hspace{3mm}3.1 $c = 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10552 4. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10553 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10554 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10555 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10556 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10557 \caption{Algorithm mp\_prime\_fermat}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10558 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10559 \textbf{Algorithm mp\_prime\_fermat.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10560 This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10561 determine the result.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10562
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10563 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10564 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10565 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10566 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10567 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10568 017 /* performs one Fermat test.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10569 018 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10570 019 * If "a" were prime then b**a == b (mod a) since the order of
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10571 020 * the multiplicative sub-group would be phi(a) = a-1. That means
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10572 021 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10573 022 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10574 023 * Sets result to 1 if the congruence holds, or zero otherwise.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10575 024 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10576 025 int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10577 026 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10578 027 mp_int t;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10579 028 int err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10580 029
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10581 030 /* default to composite */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10582 031 *result = MP_NO;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10583 032
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10584 033 /* ensure b > 1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10585 034 if (mp_cmp_d(b, 1) != MP_GT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10586 035 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10587 036 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10588 037
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10589 038 /* init t */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10590 039 if ((err = mp_init (&t)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10591 040 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10592 041 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10593 042
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10594 043 /* compute t = b**a mod a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10595 044 if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10596 045 goto LBL_T;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10597 046 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10598 047
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10599 048 /* is it equal to b? */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10600 049 if (mp_cmp (&t, b) == MP_EQ) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10601 050 *result = MP_YES;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10602 051 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10603 052
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10604 053 err = MP_OKAY;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10605 054 LBL_T:mp_clear (&t);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10606 055 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10607 056 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10608 057 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10609 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10610 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10611
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10612 \subsection{The Miller-Rabin Test}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10613 The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10614 candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10615 value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10616 some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10617
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10618 \begin{figure}[!here]
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10619 \begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10620 \begin{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10621 \begin{tabular}{l}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10622 \hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10623 \textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10624 \textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10625 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10626 1. $a' \leftarrow a - 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10627 2. $r \leftarrow n1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10628 3. $c \leftarrow 0, s \leftarrow 0$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10629 4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10630 \hspace{3mm}4.1 $s \leftarrow s + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10631 \hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10632 5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10633 6. If $y \nequiv \pm 1$ then \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10634 \hspace{3mm}6.1 $j \leftarrow 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10635 \hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10636 \hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10637 \hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10638 \hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10639 \hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10640 7. $c \leftarrow 1$\\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10641 8. Return(\textit{MP\_OKAY}). \\
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10642 \hline
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10643 \end{tabular}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10644 \end{center}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10645 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10646 \caption{Algorithm mp\_prime\_miller\_rabin}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10647 \end{figure}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10648 \textbf{Algorithm mp\_prime\_miller\_rabin.}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10649 This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10650 if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10651
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10652 If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10653 square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10654 is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10655 composite then it is \textit{probably} prime.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10656
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10657 \vspace{+3mm}\begin{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10658 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10659 \vspace{-3mm}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10660 \begin{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10661 016
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10662 017 /* Miller-Rabin test of "a" to the base of "b" as described in
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10663 018 * HAC pp. 139 Algorithm 4.24
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10664 019 *
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10665 020 * Sets result to 0 if definitely composite or 1 if probably prime.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10666 021 * Randomly the chance of error is no more than 1/4 and often
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10667 022 * very much lower.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10668 023 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10669 024 int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10670 025 \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10671 026 mp_int n1, y, r;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10672 027 int s, j, err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10673 028
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10674 029 /* default */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10675 030 *result = MP_NO;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10676 031
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10677 032 /* ensure b > 1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10678 033 if (mp_cmp_d(b, 1) != MP_GT) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10679 034 return MP_VAL;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10680 035 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10681 036
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10682 037 /* get n1 = a - 1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10683 038 if ((err = mp_init_copy (&n1, a)) != MP_OKAY) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10684 039 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10685 040 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10686 041 if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10687 042 goto LBL_N1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10688 043 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10689 044
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10690 045 /* set 2**s * r = n1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10691 046 if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10692 047 goto LBL_N1;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10693 048 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10694 049
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10695 050 /* count the number of least significant bits
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10696 051 * which are zero
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10697 052 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10698 053 s = mp_cnt_lsb(&r);
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10699 054
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10700 055 /* now divide n - 1 by 2**s */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10701 056 if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10702 057 goto LBL_R;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10703 058 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10704 059
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10705 060 /* compute y = b**r mod a */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10706 061 if ((err = mp_init (&y)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10707 062 goto LBL_R;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10708 063 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10709 064 if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10710 065 goto LBL_Y;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10711 066 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10712 067
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10713 068 /* if y != 1 and y != n1 do */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10714 069 if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10715 070 j = 1;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10716 071 /* while j <= s-1 and y != n1 */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10717 072 while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) \{
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10718 073 if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10719 074 goto LBL_Y;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10720 075 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10721 076
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10722 077 /* if y == 1 then composite */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10723 078 if (mp_cmp_d (&y, 1) == MP_EQ) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10724 079 goto LBL_Y;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10725 080 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10726 081
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10727 082 ++j;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10728 083 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10729 084
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10730 085 /* if y != n1 then composite */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10731 086 if (mp_cmp (&y, &n1) != MP_EQ) \{
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10732 087 goto LBL_Y;
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10733 088 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10734 089 \}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10735 090
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10736 091 /* probably prime now */
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10737 092 *result = MP_YES;
190
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10738 093 LBL_Y:mp_clear (&y);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10739 094 LBL_R:mp_clear (&r);
d8254fc979e9 Initial import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents: 142
diff changeset
10740 095 LBL_N1:mp_clear (&n1);
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10741 096 return err;
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10742 097 \}
142
d29b64170cf0 import of libtommath 0.32
Matt Johnston <matt@ucc.asn.au>
parents: 19
diff changeset
10743 098 #endif
19
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10744 \end{alltt}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10745 \end{small}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10746
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10747
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10748
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10749
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10750 \backmatter
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10751 \appendix
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10752 \begin{thebibliography}{ABCDEF}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10753 \bibitem[1]{TAOCPV2}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10754 Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10755
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10756 \bibitem[2]{HAC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10757 A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10758
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10759 \bibitem[3]{ROSE}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10760 Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10761
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10762 \bibitem[4]{COMBA}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10763 Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10764
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10765 \bibitem[5]{KARA}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10766 A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10767
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10768 \bibitem[6]{KARAP}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10769 Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10770
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10771 \bibitem[7]{BARRETT}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10772 Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10773
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10774 \bibitem[8]{MONT}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10775 P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10776
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10777 \bibitem[9]{DRMET}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10778 Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10779
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10780 \bibitem[10]{MMB}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10781 J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10782
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10783 \bibitem[11]{RSAREF}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10784 R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10785
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10786 \bibitem[12]{DHREF}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10787 Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10788
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10789 \bibitem[13]{IEEE}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10790 IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10791
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10792 \bibitem[14]{GMP}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10793 GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10794
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10795 \bibitem[15]{MPI}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10796 Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10797
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10798 \bibitem[16]{OPENSSL}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10799 OpenSSL Cryptographic Toolkit, \url{http://openssl.org}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10800
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10801 \bibitem[17]{LIP}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10802 Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10803
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10804 \bibitem[18]{ISOC}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10805 JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10806
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10807 \bibitem[19]{JAVA}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10808 The Sun Java Website, \url{http://java.sun.com/}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10809
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10810 \end{thebibliography}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10811
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10812 \input{tommath.ind}
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10813
e1037a1e12e7 0.30 release of LibTomMath
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10814 \end{document}