annotate tommath.tex @ 388:fb54020f78e1 libtommath-dropbear

%s/ranlib/$(RANLIB)/
author Matt Johnston <matt@ucc.asn.au>
date Thu, 11 Jan 2007 03:13:43 +0000
parents 97db060d0ef5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1 \documentclass[b5paper]{book}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2 \usepackage{hyperref}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3 \usepackage{makeidx}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4 \usepackage{amssymb}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5 \usepackage{color}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6 \usepackage{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7 \usepackage{graphicx}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8 \usepackage{layout}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9 \def\union{\cup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10 \def\intersect{\cap}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
11 \def\getsrandom{\stackrel{\rm R}{\gets}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
12 \def\cross{\times}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
13 \def\cat{\hspace{0.5em} \| \hspace{0.5em}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
14 \def\catn{$\|$}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
15 \def\divides{\hspace{0.3em} | \hspace{0.3em}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
16 \def\nequiv{\not\equiv}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
17 \def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
18 \def\lcm{{\rm lcm}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
19 \def\gcd{{\rm gcd}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
20 \def\log{{\rm log}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
21 \def\ord{{\rm ord}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
22 \def\abs{{\mathit abs}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
23 \def\rep{{\mathit rep}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
24 \def\mod{{\mathit\ mod\ }}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
25 \renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
26 \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
27 \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
28 \def\Or{{\rm\ or\ }}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
29 \def\And{{\rm\ and\ }}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
30 \def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
31 \def\implies{\Rightarrow}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
32 \def\undefined{{\rm ``undefined"}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
33 \def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
34 \let\oldphi\phi
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
35 \def\phi{\varphi}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
36 \def\Pr{{\rm Pr}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
37 \newcommand{\str}[1]{{\mathbf{#1}}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
38 \def\F{{\mathbb F}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
39 \def\N{{\mathbb N}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
40 \def\Z{{\mathbb Z}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
41 \def\R{{\mathbb R}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
42 \def\C{{\mathbb C}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
43 \def\Q{{\mathbb Q}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
44 \definecolor{DGray}{gray}{0.5}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
45 \newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
46 \def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
47 \def\gap{\vspace{0.5ex}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
48 \makeindex
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
49 \begin{document}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
50 \frontmatter
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
51 \pagestyle{empty}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
52 \title{Multi--Precision Math}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
53 \author{\mbox{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
54 %\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
55 \begin{tabular}{c}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
56 Tom St Denis \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
57 Algonquin College \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
58 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
59 Mads Rasmussen \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
60 Open Communications Security \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
61 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
62 Greg Rose \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
63 QUALCOMM Australia \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
64 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
65 %\end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
66 }
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
67 }
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
68 \maketitle
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
69 This text has been placed in the public domain. This text corresponds to the v0.39 release of the
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
70 LibTomMath project.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
71
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
72 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
73 Tom St Denis
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
74 111 Banning Rd
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
75 Ottawa, Ontario
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
76 K2L 1C3
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
77 Canada
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
78
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
79 Phone: 1-613-836-3160
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
80 Email: [email protected]
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
81 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
82
91fbc376f010 Import of libtommath 0.35
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{}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
84 {\em book} macro package and the Perl {\em booker} package.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
85
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
86 \tableofcontents
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
87 \listoffigures
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
88 \chapter*{Prefaces}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
89 When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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.''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
94 back to society in the form of tools and knowledge that can help others in their endeavours.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
95
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
98 explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
99 itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
100 of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
101 from relatively straightforward algebra and I hope that this book can be a valuable learning asset.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
102
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
104 of kind people donating their time, resources and kind words to help support my work. Writing a text of significant
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
105 length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
109
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
111 honour your kind gestures with this project.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
112
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
113 Open Source. Open Academia. Open Minds.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
114
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
115 \begin{flushright} Tom St Denis \end{flushright}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
117 \newpage
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
120
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
123 the layout and language used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
124
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
126 practical aspects of cryptography.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
127
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
131 reductions, for example, become painfully slow.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
132
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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?''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
135
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
136 \begin{flushright}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
137 Mads Rasmussen
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
139 S\~{a}o Paulo - SP
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
140
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
141 Brazil
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
142 \end{flushright}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
143
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
144 \newpage
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
148
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
153
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
157 and I'm pleased to be involved with it.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
158
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
159 \begin{flushright}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
160 Greg Rose, Sydney, Australia, June 2003.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
161 \end{flushright}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
162
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
163 \mainmatter
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
164 \pagestyle{headings}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
165 \chapter{Introduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
166 \section{Multiple Precision Arithmetic}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
167
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
168 \subsection{What is Multiple Precision Arithmetic?}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
174 of algorithms can be designed to accomodate them.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
175
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
177 the decimal system with fixed precision $6 \cdot 7 = 2$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
178
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
180 schools to manually add, subtract, multiply and divide.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
181
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
182 \subsection{The Need for Multiple Precision Arithmetic}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
188
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
189 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
190 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
191 \begin{tabular}{|r|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
192 \hline \textbf{Data Type} & \textbf{Range} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
193 \hline char & $-128 \ldots 127$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
194 \hline short & $-32768 \ldots 32767$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
195 \hline long & $-2147483648 \ldots 2147483647$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
196 \hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
197 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
198 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
199 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
200 \caption{Typical Data Types for the C Programming Language}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
201 \label{fig:ISOC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
202 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
203
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
204 The largest data type guaranteed to be provided by the ISO C programming
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
210 extending the range of representable integers while using single precision data types.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
211
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
216 deployment of efficient algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
217
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
219 Another auxiliary use of multiple precision integers is high precision floating point data types.
91fbc376f010 Import of libtommath 0.35
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$.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
225 scientific applications must minimize the total output error over long calculations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
226
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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$).
91fbc376f010 Import of libtommath 0.35
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.}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
229
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
230 \subsection{Benefits of Multiple Precision Arithmetic}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
231 \index{precision}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
232 The benefit of multiple precision representations over single or fixed precision representations is that
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
236 would truncate excess bits to maintain a fixed level of precision.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
237
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
244
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
250 be written and tested once.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
251
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
252 \section{Purpose of This Text}
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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''
91fbc376f010 Import of libtommath 0.35
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}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
257 regarding the practical implementation aspects.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
258
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
261 algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
265
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
268 any form of useful performance in non-trivial applications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
269
91fbc376f010 Import of libtommath 0.35
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
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
271 package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used
282
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
274 discusses a very large portion of the inner workings of the library.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
275
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
278 algorithm in other programming languages as the reader sees fit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
279
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
283 \section{Discussion and Notation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
284 \subsection{Notation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
287 of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
288 $1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
289
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
290 \index{mp\_int}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
298 $a.length = 5$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
299
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
305 precision algorithm to solve the same problem.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
306
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
307 \subsection{Precision Notation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
308 The variable $\beta$ represents the radix of a single digit of a multiple precision integer and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
310 the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
311 $0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
312 carry. Since all modern computers are binary, it is assumed that $q$ is two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
313
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
314 \index{mp\_digit} \index{mp\_word}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
322 precision data type.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
323
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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$.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
329 in a single precision data type and as a result $c \ne \hat c$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
330
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
331 \subsection{Algorithm Inputs and Outputs}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
335
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
336 \subsection{Mathematical Expressions}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
342 fraction a real value division is implied, for example ${5 \over 2} = 2.5$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
343
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
346
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
347 \subsection{Work Effort}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
348 \index{big-Oh}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.}.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
353
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
357 would both be said to be equivalent to $O(n^2)$. However,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
360
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
363 various optimizations will help pay off in the long run.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
364
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
365 \section{Exercises}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
370 subject material.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
371
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
373 are encouraged to verify they can answer the problems correctly before moving on.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
374
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
378 scoring system used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
379
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
380 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
381 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
382 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
383 \begin{tabular}{|c|l|}
91fbc376f010 Import of libtommath 0.35
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 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
385 & minutes to solve. Usually does not involve much computer time \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
386 & to solve. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
387 \hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
388 & time usage. Usually requires a program to be written to \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
389 & solve the problem. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
390 \hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
391 & of work. Usually involves trivial research and development of \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
392 & new theory from the perspective of a student. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
393 \hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
394 & of work and research, the solution to which will demonstrate \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
395 & a higher mastery of the subject matter. \\
91fbc376f010 Import of libtommath 0.35
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 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
397 & novice to solve. Solutions to these problems will demonstrate a \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
398 & complete mastery of the given subject. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
399 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
400 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
401 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
402 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
403 \caption{Exercise Scoring System}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
404 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
405
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
409 two levels are essentially entry level questions.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
410
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
414 answer these questions will feel comfortable with the concepts behind the topic at hand.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
415
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
418 the exact details of the answer until a subsequent chapter.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
419
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
420 Problems at the fifth level are meant to be the hardest
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
422 mastery of the subject matter at hand.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
423
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
426
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
427 \section{Introduction to LibTomMath}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
428
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
429 \subsection{What is LibTomMath?}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
432 any given platform.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
433
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
437 as public key cryptosystems and still maintain a relatively small footprint.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
438
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
439 \subsection{Goals of LibTomMath}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
440
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
444 processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
445 exponentiation and Montgomery reduction have been provided to make the library more efficient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
446
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
451 based on the magnitude of the inputs and the configuration of the library.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
452
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
457 passing conventions, it has been written from scratch by Tom St Denis.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
458
91fbc376f010 Import of libtommath 0.35
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''
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
462
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
463 \section{Choice of LibTomMath}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
467 reasons that will be explained in the following sub-sections.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
468
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
469 \subsection{Code Base}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
473 what conditional code will be used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
474
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
478 very hard. GMP has many conditional code segments which also hinder tracing.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
479
91fbc376f010 Import of libtommath 0.35
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.}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
482 $50$KiB) but LibTomMath is also much faster and more complete than MPI.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
483
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
484 \subsection{API Simplicity}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
488 which is an extremely valuable benefit for the student and developer alike.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
489
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
491 illegible short hand. LibTomMath does not share this characteristic.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
492
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
496 undersireable in many situations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
497
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
498 \subsection{Optimizations}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
503 only had Barrett and Montgomery modular reduction algorithms.}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
504
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
508
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
509 \subsection{Portability and Stability}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
514
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
516 development and are very stable across a variety of platforms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
517
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
518 \subsection{Choice}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
522
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
523 \chapter{Getting Started}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
524 \section{Library Basics}
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
528 as portable source code that is reasonably efficient across several different computer platforms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
529
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
532 before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
535 has a small footprint and updates are easy to perform.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
536
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
546
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
547 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
548 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
549 \includegraphics{pics/design_process.ps}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
550 \caption{Design Flow of the First Few Original LibTomMath Functions.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
551 \label{pic:design_process}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
552 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
553 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
554
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
557
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
560
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
561 \section{What is a Multiple Precision Integer?}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
565 that are very large.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
566
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
572 precision computer words with the exception that a different radix is used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
573
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
579
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
584 integer or mp\_int for short.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
585
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
586 \subsection{The mp\_int Structure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
587 \label{sec:MPINT}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
590 used within LibTomMath.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
591
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
592 \index{mp\_int}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
593 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
594 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
595 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
596 %\begin{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
597 \begin{tabular}{|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
598 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
599 typedef struct \{ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
600 \hspace{3mm}int used, alloc, sign;\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
601 \hspace{3mm}mp\_digit *dp;\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
602 \} \textbf{mp\_int}; \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
603 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
604 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
605 %\end{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
606 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
607 \caption{The mp\_int Structure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
608 \label{fig:mpint}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
609 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
610 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
611
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
612 The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
613
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
614 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
617
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
618 \item The \textbf{alloc} parameter denotes how
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
621 array to accommodate the precision of the result.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
622
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
628 it would represent the integer $a + b\beta + c\beta^2 + \ldots$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
629
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
630 \index{MP\_ZPOS} \index{MP\_NEG}
91fbc376f010 Import of libtommath 0.35
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}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
632 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
633
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
634 \subsubsection{Valid mp\_int Structures}
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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().
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
637
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
638 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
640 array of digits.
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
643 leading zero digits in the most significant positions must be trimmed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
644 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
646 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
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;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
648 this represents the mp\_int value of zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
649 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
650
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
651 \section{Argument Passing}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
656 Consider the following examples.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
657
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
658 \begin{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
659 mp_mul(&a, &b, &c); /* c = a * b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
660 mp_add(&a, &b, &a); /* a = a + b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
661 mp_sqr(&a, &b); /* b = a * a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
662 \end{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
663
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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''.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
666
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
670 adopted.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
671
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
676 source is fully read.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
677
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
678 \section{Return Values}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
682 fault by dereferencing memory not owned by the application.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
683
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
687 \textbf{int} data type with one of the following values (fig \ref{fig:errcodes}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
688
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
689 \index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
690 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
691 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
692 \begin{tabular}{|l|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
693 \hline \textbf{Value} & \textbf{Meaning} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
694 \hline \textbf{MP\_OKAY} & The function was successful \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
695 \hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
696 \hline \textbf{MP\_MEM} & The function ran out of heap memory \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
697 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
698 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
699 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
700 \caption{LibTomMath Error Codes}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
701 \label{fig:errcodes}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
702 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
703
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
706 function was called. Error checking with this style of API is fairly simple.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
707
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
708 \begin{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
709 int err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
710 if ((err = mp_add(&a, &b, &c)) != MP_OKAY) {
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
711 printf("Error: %s\n", mp_error_to_string(err));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
712 exit(EXIT_FAILURE);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
713 }
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
714 \end{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
715
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
718
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
719 \section{Initialization and Clearing}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
722
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
728 memory and become unmanageable.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
729
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
733
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
734 \subsection{Initializing an mp\_int}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
737
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
738 \index{mp\_init}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
739 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
740 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
741 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
742 \hline Algorithm \textbf{mp\_init}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
743 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
744 \textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
745 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
746 1. Allocate memory for \textbf{MP\_PREC} digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
747 2. If the allocation failed return(\textit{MP\_MEM}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
748 3. for $n$ from $0$ to $MP\_PREC - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
749 \hspace{3mm}3.1 $a_n \leftarrow 0$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
750 4. $a.sign \leftarrow MP\_ZPOS$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
751 5. $a.used \leftarrow 0$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
752 6. $a.alloc \leftarrow MP\_PREC$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
753 7. Return(\textit{MP\_OKAY})\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
754 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
755 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
756 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
757 \caption{Algorithm mp\_init}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
758 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
759
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
760 \textbf{Algorithm mp\_init.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
761 The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
762 manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
763 a valid assumption if the input resides on the stack.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
764
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
765 Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
766 the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
767 name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
768 used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
769 precision number you'll be working with.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
770
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
772 heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
773 memory and the number of heap operations will be trivial.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
774
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
776 \textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
777 of the original condition of the input.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
778
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
779 \textbf{Remark.}
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
785 decrementally.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
786
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
787 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
788 \hspace{-5.1mm}{\bf File}: bn\_mp\_init.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
789 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
790 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
791 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
792 017 /* init a new mp_int */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
793 018 int mp_init (mp_int * a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
794 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
795 020 int i;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
796 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
797 022 /* allocate memory required and clear it */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
798 023 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
799 024 if (a->dp == NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
800 025 return MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
801 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
802 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
803 028 /* set the digits to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
804 029 for (i = 0; i < MP_PREC; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
805 030 a->dp[i] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
806 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
807 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
808 033 /* set the used to zero, allocated digits to the default precision
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
809 034 * and sign to positive */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
810 035 a->used = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
811 036 a->alloc = MP_PREC;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
812 037 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
813 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
814 039 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
815 040 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
816 041 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
817 042
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
818 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
819 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
820
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
821 One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
822 is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
823 call to mp\_init() is used only to initialize the members of the structure to a known default state.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
824
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
825 Here we see (line 23) the memory allocation is performed first. This allows us to exit cleanly and quickly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
826 if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
827 was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
828 but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
829 memory allocation routine.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
830
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
831 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
832 accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
833 portable fashion you have to actually assign the value. The for loop (line 29) performs this required
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
834 operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
835
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
836 After the memory has been successfully initialized the remainder of the members are initialized
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
837 (lines 33 through 34) to their respective default states. At this point the algorithm has succeeded and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
838 a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
839 mp\_int structure has been properly initialized and is safe to use with other functions within the library.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
840
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
841 \subsection{Clearing an mp\_int}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
842 When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
843 returned to the application's memory pool with the mp\_clear algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
844
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
845 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
846 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
847 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
848 \hline Algorithm \textbf{mp\_clear}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
849 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
850 \textbf{Output}. The memory for $a$ shall be deallocated. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
851 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
852 1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
853 2. for $n$ from 0 to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
854 \hspace{3mm}2.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
855 3. Free the memory allocated for the digits of $a$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
856 4. $a.used \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
857 5. $a.alloc \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
858 6. $a.sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
859 7. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
860 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
861 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
862 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
863 \caption{Algorithm mp\_clear}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
864 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
865
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
866 \textbf{Algorithm mp\_clear.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
867 This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
868 if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
869 is to free the allocated memory.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
870
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
871 The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
872 algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
873 digit pointer \textbf{dp} setting.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
874
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
875 Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
876 with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
877
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
878 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
879 \hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
880 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
881 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
882 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
883 017 /* clear one (frees) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
884 018 void
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
885 019 mp_clear (mp_int * a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
886 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
887 021 int i;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
888 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
889 023 /* only do anything if a hasn't been freed previously */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
890 024 if (a->dp != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
891 025 /* first zero the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
892 026 for (i = 0; i < a->used; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
893 027 a->dp[i] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
894 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
895 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
896 030 /* free ram */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
897 031 XFREE(a->dp);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
898 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
899 033 /* reset members to make debugging easier */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
900 034 a->dp = NULL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
901 035 a->alloc = a->used = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
902 036 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
903 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
904 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
905 039 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
906 040
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
907 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
908 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
909
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
910 The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line 24)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
911 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
912 \textbf{NULL} in which case the if statement will evaluate to true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
913
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
914 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()
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
915 the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
916
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
917 The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
918 a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
919 still has to be reset to \textbf{NULL} manually (line 34).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
920
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
921 Now that the digits have been cleared and deallocated the other members are set to their final values (lines 35 and 36).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
922
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
923 \section{Maintenance Algorithms}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
924
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
925 The previous sections describes how to initialize and clear an mp\_int structure. To further support operations
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
926 that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
927 able to augment the precision of an mp\_int and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
928 initialize mp\_ints with differing initial conditions.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
929
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
930 These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
931 algorithms such as addition, multiplication and modular exponentiation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
932
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
933 \subsection{Augmenting an mp\_int's Precision}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
934 When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
935 result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
936 is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
937 must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
938
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
939 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
940 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
941 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
942 \hline Algorithm \textbf{mp\_grow}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
943 \textbf{Input}. An mp\_int $a$ and an integer $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
944 \textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
945 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
946 1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
947 2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
948 3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
949 4. Re-allocate the array of digits $a$ to size $v$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
950 5. If the allocation failed then return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
951 6. for n from a.alloc to $v - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
952 \hspace{+3mm}6.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
953 7. $a.alloc \leftarrow v$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
954 8. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
955 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
956 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
957 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
958 \caption{Algorithm mp\_grow}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
959 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
960
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
961 \textbf{Algorithm mp\_grow.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
962 It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
963 prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
964
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
965 The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
966 This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
967
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
968 It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
969 akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
970 assumed to contain undefined values they are initially set to zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
971
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
972 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
973 \hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
974 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
975 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
976 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
977 017 /* grow as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
978 018 int mp_grow (mp_int * a, int size)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
979 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
980 020 int i;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
981 021 mp_digit *tmp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
982 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
983 023 /* if the alloc size is smaller alloc more ram */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
984 024 if (a->alloc < size) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
985 025 /* ensure there are always at least MP_PREC digits extra on top */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
986 026 size += (MP_PREC * 2) - (size % MP_PREC);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
987 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
988 028 /* reallocate the array a->dp
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
989 029 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
990 030 * We store the return in a temporary variable
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
991 031 * in case the operation failed we don't want
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
992 032 * to overwrite the dp member of a.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
993 033 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
994 034 tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
995 035 if (tmp == NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
996 036 /* reallocation failed but "a" is still valid [can be freed] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
997 037 return MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
998 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
999 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1000 040 /* reallocation succeeded so set a->dp */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1001 041 a->dp = tmp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1002 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1003 043 /* zero excess digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1004 044 i = a->alloc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1005 045 a->alloc = size;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1006 046 for (; i < a->alloc; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1007 047 a->dp[i] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1008 048 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1009 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1010 050 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1011 051 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1012 052 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1013 053
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1014 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1015 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1017 A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line 24) checks
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1018 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1019 the function skips the re-allocation part thus saving time.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1020
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1021 When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1022 padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 26). The XREALLOC function is used
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1023 to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1024 function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1025 the re-allocation. All that is left is to clear the newly allocated digits and return.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1027 Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1028 an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1029 result in a memory leak if XREALLOC ever failed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1031 \subsection{Initializing Variable Precision mp\_ints}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1032 Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1033 of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1034 will allocate \textit{at least} a specified number of digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1036 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1037 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1038 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1039 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1040 \hline Algorithm \textbf{mp\_init\_size}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1041 \textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1042 \textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1043 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1044 1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1045 2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1046 3. Allocate $v$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1047 4. for $n$ from $0$ to $v - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1048 \hspace{3mm}4.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1049 5. $a.sign \leftarrow MP\_ZPOS$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1050 6. $a.used \leftarrow 0$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1051 7. $a.alloc \leftarrow v$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1052 8. Return(\textit{MP\_OKAY})\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1053 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1054 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1055 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1056 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1057 \caption{Algorithm mp\_init\_size}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1058 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1060 \textbf{Algorithm mp\_init\_size.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1061 This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1062 digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1063 multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1064 allocations from becoming a bottleneck in the rest of the algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1065
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1066 Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1067 particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1068 correct no further memory re-allocations are required to work with the mp\_int.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1070 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1071 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1072 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1073 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1074 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1075 017 /* init an mp_init for a given size */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1076 018 int mp_init_size (mp_int * a, int size)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1077 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1078 020 int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1079 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1080 022 /* pad size so there are always extra digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1081 023 size += (MP_PREC * 2) - (size % MP_PREC);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1082 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1083 025 /* alloc mem */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1084 026 a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1085 027 if (a->dp == NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1086 028 return MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1087 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1088 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1089 031 /* set the members */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1090 032 a->used = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1091 033 a->alloc = size;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1092 034 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1093 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1094 036 /* zero the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1095 037 for (x = 0; x < size; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1096 038 a->dp[x] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1097 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1098 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1099 041 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1100 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1101 043 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1102 044
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1103 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1104 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1105
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1106 The number of digits $b$ requested is padded (line 23) by first augmenting it to the next multiple of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1107 \textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1108 mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1109 returned (line 28).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1111 The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1112 \textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1113 to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 32, 33 and 34). If the function
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1114 returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1115 functions to work with.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1117 \subsection{Multiple Integer Initializations and Clearings}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1118 Occasionally a function will require a series of mp\_int data types to be made available simultaneously.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1119 The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1120 statement. It is essentially a shortcut to multiple initializations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1121
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1122 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1123 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1124 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1125 \hline Algorithm \textbf{mp\_init\_multi}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1126 \textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1127 \textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1128 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1129 1. for $n$ from 0 to $k - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1130 \hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1131 \hspace{+3mm}1.2. If initialization failed then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1132 \hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1133 \hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1134 \hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1135 2. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1136 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1137 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1138 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1139 \caption{Algorithm mp\_init\_multi}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1140 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1141
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1142 \textbf{Algorithm mp\_init\_multi.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1143 The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1144 (\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1145 initialization which allows for quick recovery from runtime errors.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1146
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1147 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1148 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1149 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1150 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1151 016 #include <stdarg.h>
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1152 017
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1153 018 int mp_init_multi(mp_int *mp, ...)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1154 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1155 020 mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1156 021 int n = 0; /* Number of ok inits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1157 022 mp_int* cur_arg = mp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1158 023 va_list args;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1159 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1160 025 va_start(args, mp); /* init args to next argument from caller */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1161 026 while (cur_arg != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1162 027 if (mp_init(cur_arg) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1163 028 /* Oops - error! Back-track and mp_clear what we already
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1164 029 succeeded in init-ing, then return error.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1165 030 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1166 031 va_list clean_args;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1167 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1168 033 /* end the current list */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1169 034 va_end(args);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1170 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1171 036 /* now start cleaning up */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1172 037 cur_arg = mp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1173 038 va_start(clean_args, mp);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1174 039 while (n--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1175 040 mp_clear(cur_arg);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1176 041 cur_arg = va_arg(clean_args, mp_int*);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1177 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1178 043 va_end(clean_args);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1179 044 res = MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1180 045 break;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1181 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1182 047 n++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1183 048 cur_arg = va_arg(args, mp_int*);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1184 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1185 050 va_end(args);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1186 051 return res; /* Assumed ok, if error flagged above. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1187 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1188 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1189 054 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1190 055
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1191 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1192 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1193
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1194 This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1195 structures in an actual C array they are simply passed as arguments to the function. This function makes use of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1196 ``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1197 appended on the right.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1198
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1199 The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1200 $n$ of succesfully initialized mp\_int structures is maintained (line 47) such that if a failure does occur,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1201 the algorithm can backtrack and free the previously initialized structures (lines 27 to 46).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1202
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1203
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1204 \subsection{Clamping Excess Digits}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1205 When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1206 the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1207 $j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1208 though, with no final carry into the last position. However, suppose the destination had to be first expanded
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1209 (\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1210 That would be a considerable waste of time since heap operations are relatively slow.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1211
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1212 The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1213 terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1214 there would be an excess high order zero digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1215
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1216 For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1217 will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1218 accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1219 low the representation is excessively large.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1220
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1221 The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1222 \textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1223 positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1224 \textbf{MP\_ZPOS}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1225
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1226 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1227 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1228 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1229 \hline Algorithm \textbf{mp\_clamp}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1230 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1231 \textbf{Output}. Any excess leading zero digits of $a$ are removed \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1232 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1233 1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1234 \hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1235 2. if $a.used = 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1236 \hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1237 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1238 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1239 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1240 \caption{Algorithm mp\_clamp}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1241 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1242
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1243 \textbf{Algorithm mp\_clamp.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1244 As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1245 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1246 when all of the digits are zero to ensure that the mp\_int is valid at all times.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1247
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1248 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1249 \hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1250 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1251 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1252 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1253 017 /* trim unused digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1254 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1255 019 * This is used to ensure that leading zero digits are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1256 020 * trimed and the leading "used" digit will be non-zero
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1257 021 * Typically very fast. Also fixes the sign if there
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1258 022 * are no more leading digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1259 023 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1260 024 void
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1261 025 mp_clamp (mp_int * a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1262 026 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1263 027 /* decrease used while the most significant digit is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1264 028 * zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1265 029 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1266 030 while (a->used > 0 && a->dp[a->used - 1] == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1267 031 --(a->used);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1268 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1269 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1270 034 /* reset the sign flag if used == 0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1271 035 if (a->used == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1272 036 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1273 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1274 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1275 039 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1276 040
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1277 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1278 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1279
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1280 Note on line 27 how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1281 language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1282 important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1283 undesirable. The parenthesis on line 30 is used to make sure the \textbf{used} count is decremented and not
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1284 the pointer ``a''.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1285
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1286 \section*{Exercises}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1287 \begin{tabular}{cl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1288 $\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1289 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1290 $\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1291 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1292 $\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1293 & encryption when $\beta = 2^{28}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1294 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1295 $\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1296 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1297 $\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1298 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1299 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1300
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1301
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1302 %%%
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1303 % CHAPTER FOUR
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1304 %%%
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1305
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1306 \chapter{Basic Operations}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1307
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1308 \section{Introduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1309 In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1310 mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1311 level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1312 work before proceeding since these algorithms will be used almost intrinsically in the following chapters.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1313
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1314 The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1315 mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1316 represent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1317
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1318 \section{Assigning Values to mp\_int Structures}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1319 \subsection{Copying an mp\_int}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1320 Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1321 a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1322 value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1323
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1324 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1325 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1326 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1327 \hline Algorithm \textbf{mp\_copy}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1328 \textbf{Input}. An mp\_int $a$ and $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1329 \textbf{Output}. Store a copy of $a$ in $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1330 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1331 1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1332 2. for $n$ from 0 to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1333 \hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1334 3. for $n$ from $a.used$ to $b.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1335 \hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1336 4. $b.used \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1337 5. $b.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1338 6. return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1339 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1340 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1341 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1342 \caption{Algorithm mp\_copy}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1343 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1344
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1345 \textbf{Algorithm mp\_copy.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1346 This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1347 represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1348 mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1349
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1350 If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1351 algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1352 and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1353 $b$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1354
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1355 \textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1356 text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1357 step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1358 limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1359 the error code itself. However, the C code presented will demonstrate all of the error handling logic required to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1360 implement the pseudo-code.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1361
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1362 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1363 \hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1364 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1365 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1366 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1367 017 /* copy, b = a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1368 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1369 019 mp_copy (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1370 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1371 021 int res, n;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1372 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1373 023 /* if dst == src do nothing */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1374 024 if (a == b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1375 025 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1376 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1377 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1378 028 /* grow dest */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1379 029 if (b->alloc < a->used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1380 030 if ((res = mp_grow (b, a->used)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1381 031 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1382 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1383 033 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1384 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1385 035 /* zero b and copy the parameters over */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1386 036 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1387 037 register mp_digit *tmpa, *tmpb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1388 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1389 039 /* pointer aliases */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1390 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1391 041 /* source */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1392 042 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1393 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1394 044 /* destination */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1395 045 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1396 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1397 047 /* copy all the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1398 048 for (n = 0; n < a->used; n++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1399 049 *tmpb++ = *tmpa++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1400 050 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1401 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1402 052 /* clear high digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1403 053 for (; n < b->used; n++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1404 054 *tmpb++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1405 055 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1406 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1407 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1408 058 /* copy used count and sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1409 059 b->used = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1410 060 b->sign = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1411 061 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1412 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1413 063 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1414 064
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1415 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1416 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1417
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1418 Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1419 mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1420 copying digits (line 24).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1421
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1422 The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1423 $a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 29 to 33). In order to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1424 simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1425 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1426 mp\_int pointers and then subsequently the pointer to the digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1427
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1428 After the aliases are established the digits from $a$ are copied into $b$ (lines 48 to 50) and then the excess
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1429 digits of $b$ are set to zero (lines 53 to 55). Both ``for'' loops make use of the pointer aliases and in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1430 fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1431 allows the alias to stay in a machine register fairly easy between the two loops.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1432
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1433 \textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1434 be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1435 number of pointer dereferencing operations required to access data. For example, a for loop may resemble
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1436
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1437 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1438 for (x = 0; x < 100; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1439 a->num[4]->dp[x] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1440 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1441 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1442
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1443 This could be re-written using aliases as
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1444
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1445 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1446 mp_digit *tmpa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1447 a = a->num[4]->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1448 for (x = 0; x < 100; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1449 *a++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1450 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1451 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1452
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1453 In this case an alias is used to access the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1454 array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1455 as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1456
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1457 The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1458 may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1459 work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1460 aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1461 stands a better chance of being faster.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1462
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1463 The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1464 loop of the function mp\_copy() re-written to not use pointer aliases.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1465
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1466 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1467 /* copy all the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1468 for (n = 0; n < a->used; n++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1469 b->dp[n] = a->dp[n];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1470 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1471 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1472
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1473 Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1474 complicated as there are four variables within the statement instead of just two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1475
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1476 \subsubsection{Nested Statements}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1477 Another commonly used technique in the source routines is that certain sections of code are nested. This is used in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1478 particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1479 will typically have three different phases. First the temporaries are initialized, then the columns calculated and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1480 finally the carries are propagated. In this example the middle column production phase will typically be nested as it
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1481 uses temporary variables and aliases the most.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1482
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1483 The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1484 the various temporary variables required do not propagate into other sections of code.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1485
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1486
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1487 \subsection{Creating a Clone}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1488 Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1489 and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1490 useful within functions that need to modify an argument but do not wish to actually modify the original copy. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1491 mp\_init\_copy algorithm has been designed to help perform this task.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1492
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1493 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1494 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1495 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1496 \hline Algorithm \textbf{mp\_init\_copy}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1497 \textbf{Input}. An mp\_int $a$ and $b$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1498 \textbf{Output}. $a$ is initialized to be a copy of $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1499 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1500 1. Init $a$. (\textit{mp\_init}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1501 2. Copy $b$ to $a$. (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1502 3. Return the status of the copy operation. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1503 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1504 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1505 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1506 \caption{Algorithm mp\_init\_copy}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1507 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1508
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1509 \textbf{Algorithm mp\_init\_copy.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1510 This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1511 such this algorithm will perform two operations in one step.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1512
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1513 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1514 \hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1515 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1516 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1517 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1518 017 /* creates "a" then copies b into it */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1519 018 int mp_init_copy (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1520 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1521 020 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1522 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1523 022 if ((res = mp_init (a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1524 023 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1525 024 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1526 025 return mp_copy (b, a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1527 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1528 027 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1529 028
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1530 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1531 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1532
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1533 This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1534 \textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1535 and \textbf{a} will be left intact.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1536
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1537 \section{Zeroing an Integer}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1538 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1539 perform this task.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1540
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1541 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1542 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1543 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1544 \hline Algorithm \textbf{mp\_zero}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1545 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1546 \textbf{Output}. Zero the contents of $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1547 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1548 1. $a.used \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1549 2. $a.sign \leftarrow$ MP\_ZPOS \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1550 3. for $n$ from 0 to $a.alloc - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1551 \hspace{3mm}3.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1552 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1553 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1554 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1555 \caption{Algorithm mp\_zero}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1556 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1557
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1558 \textbf{Algorithm mp\_zero.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1559 This algorithm simply resets a mp\_int to the default state.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1560
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1561 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1562 \hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1563 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1564 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1565 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1566 017 /* set to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1567 018 void mp_zero (mp_int * a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1568 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1569 020 int n;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1570 021 mp_digit *tmp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1571 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1572 023 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1573 024 a->used = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1574 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1575 026 tmp = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1576 027 for (n = 0; n < a->alloc; n++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1577 028 *tmp++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1578 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1579 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1580 031 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1581 032
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1582 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1583 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1584
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1585 After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1586 \textbf{sign} variable is set to \textbf{MP\_ZPOS}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1587
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1588 \section{Sign Manipulation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1589 \subsection{Absolute Value}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1590 With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1591 the absolute value of an mp\_int.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1592
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1593 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1594 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1595 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1596 \hline Algorithm \textbf{mp\_abs}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1597 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1598 \textbf{Output}. Computes $b = \vert a \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1599 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1600 1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1601 2. If the copy failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1602 3. $b.sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1603 4. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1604 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1605 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1606 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1607 \caption{Algorithm mp\_abs}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1608 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1609
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1610 \textbf{Algorithm mp\_abs.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1611 This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1612 algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1613 for instance, the developer to pass the same mp\_int as the source and destination to this function without addition
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1614 logic to handle it.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1615
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1616 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1617 \hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1618 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1619 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1620 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1621 017 /* b = |a|
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1622 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1623 019 * Simple function copies the input and fixes the sign to positive
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1624 020 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1625 021 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1626 022 mp_abs (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1627 023 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1628 024 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1629 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1630 026 /* copy a to b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1631 027 if (a != b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1632 028 if ((res = mp_copy (a, b)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1633 029 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1634 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1635 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1636 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1637 033 /* force the sign of b to positive */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1638 034 b->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1639 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1640 036 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1641 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1642 038 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1643 039
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1644 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1645 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1646
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1647 This fairly trivial algorithm first eliminates non--required duplications (line 27) and then sets the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1648 \textbf{sign} flag to \textbf{MP\_ZPOS}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1649
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1650 \subsection{Integer Negation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1651 With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1652 the negative of an mp\_int input.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1653
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1654 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1655 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1656 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1657 \hline Algorithm \textbf{mp\_neg}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1658 \textbf{Input}. An mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1659 \textbf{Output}. Computes $b = -a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1660 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1661 1. Copy $a$ to $b$. (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1662 2. If the copy failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1663 3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1664 4. If $a.sign = MP\_ZPOS$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1665 \hspace{3mm}4.1 $b.sign = MP\_NEG$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1666 5. else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1667 \hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1668 6. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1669 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1670 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1671 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1672 \caption{Algorithm mp\_neg}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1673 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1674
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1675 \textbf{Algorithm mp\_neg.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1676 This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1677 the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1678 $a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1679 zero as negative.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1680
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1681 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1682 \hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1683 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1684 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1685 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1686 017 /* b = -a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1687 018 int mp_neg (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1688 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1689 020 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1690 021 if (a != b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1691 022 if ((res = mp_copy (a, b)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1692 023 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1693 024 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1694 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1695 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1696 027 if (mp_iszero(b) != MP_YES) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1697 028 b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1698 029 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1699 030 b->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1700 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1701 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1702 033 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1703 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1704 035 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1705 036
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1706 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1707 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1708
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1709 Like mp\_abs() this function avoids non--required duplications (line 21) and then sets the sign. We
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1710 have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1711 than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1712
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1713 \section{Small Constants}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1714 \subsection{Setting Small Constants}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1715 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1716
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1717 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1718 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1719 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1720 \hline Algorithm \textbf{mp\_set}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1721 \textbf{Input}. An mp\_int $a$ and a digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1722 \textbf{Output}. Make $a$ equivalent to $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1723 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1724 1. Zero $a$ (\textit{mp\_zero}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1725 2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1726 3. $a.used \leftarrow \left \lbrace \begin{array}{ll}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1727 1 & \mbox{if }a_0 > 0 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1728 0 & \mbox{if }a_0 = 0
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1729 \end{array} \right .$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1730 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1731 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1732 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1733 \caption{Algorithm mp\_set}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1734 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1735
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1736 \textbf{Algorithm mp\_set.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1737 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1738 single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1739
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1740 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1741 \hspace{-5.1mm}{\bf File}: bn\_mp\_set.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1742 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1743 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1744 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1745 017 /* set to a digit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1746 018 void mp_set (mp_int * a, mp_digit b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1747 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1748 020 mp_zero (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1749 021 a->dp[0] = b & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1750 022 a->used = (a->dp[0] != 0) ? 1 : 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1751 023 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1752 024 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1753 025
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1754 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1755 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1756
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1757 First we zero (line 20) the mp\_int to make sure that the other members are initialized for a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1758 small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1759 is zero. Next we set the digit and reduce it modulo $\beta$ (line 21). After this step we have to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1760 check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1761 to zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1762
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1763 We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1764 $2^k - 1$ will perform the same operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1765
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1766 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1767 this function should take that into account. Only trivially small constants can be set using this function.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1768
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1769 \subsection{Setting Large Constants}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1770 To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1771 data type as input and will always treat it as a 32-bit integer.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1772
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1773 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1774 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1775 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1776 \hline Algorithm \textbf{mp\_set\_int}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1777 \textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1778 \textbf{Output}. Make $a$ equivalent to $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1779 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1780 1. Zero $a$ (\textit{mp\_zero}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1781 2. for $n$ from 0 to 7 do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1782 \hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1783 \hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1784 \hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1785 \hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1786 3. Clamp excess used digits (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1787 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1788 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1789 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1790 \caption{Algorithm mp\_set\_int}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1791 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1792
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1793 \textbf{Algorithm mp\_set\_int.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1794 The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1795 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1796 next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1797 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1798 zero digits used and the newly added four bits would be ignored.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1799
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1800 Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1801
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1802 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1803 \hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1804 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1805 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1806 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1807 017 /* set a 32-bit const */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1808 018 int mp_set_int (mp_int * a, unsigned long b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1809 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1810 020 int x, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1811 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1812 022 mp_zero (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1813 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1814 024 /* set four bits at a time */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1815 025 for (x = 0; x < 8; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1816 026 /* shift the number up four bits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1817 027 if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1818 028 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1819 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1820 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1821 031 /* OR in the top four bits of the source */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1822 032 a->dp[0] |= (b >> 28) & 15;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1823 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1824 034 /* shift the source up to the next four bits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1825 035 b <<= 4;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1826 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1827 037 /* ensure that digits are not clamped off */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1828 038 a->used += 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1829 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1830 040 mp_clamp (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1831 041 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1832 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1833 043 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1834 044
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1835 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1836 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1837
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1838 This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1839 addition on line 38 ensures that the newly added in bits are added to the number of digits. While it may not
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1840 seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 27
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1841 as well as the call to mp\_clamp() on line 40. Both functions will clamp excess leading digits which keeps
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1842 the number of used digits low.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1843
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1844 \section{Comparisons}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1845 \subsection{Unsigned Comparisions}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1846 Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1847 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1848 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1849 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1850
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1851 The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1852 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1853 signs are known to agree in advance.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1854
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1855 To facilitate working with the results of the comparison functions three constants are required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1856
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1857 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1858 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1859 \begin{tabular}{|r|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1860 \hline \textbf{Constant} & \textbf{Meaning} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1861 \hline \textbf{MP\_GT} & Greater Than \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1862 \hline \textbf{MP\_EQ} & Equal To \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1863 \hline \textbf{MP\_LT} & Less Than \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1864 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1865 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1866 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1867 \caption{Comparison Return Codes}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1868 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1869
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1870 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1871 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1872 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1873 \hline Algorithm \textbf{mp\_cmp\_mag}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1874 \textbf{Input}. Two mp\_ints $a$ and $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1875 \textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1876 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1877 1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1878 2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1879 3. for n from $a.used - 1$ to 0 do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1880 \hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1881 \hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1882 4. Return(\textit{MP\_EQ}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1883 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1884 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1885 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1886 \caption{Algorithm mp\_cmp\_mag}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1887 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1888
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1889 \textbf{Algorithm mp\_cmp\_mag.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1890 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1891 \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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1892 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1893 If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1894
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1895 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1896 the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1897
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1898 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1899 \hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1900 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1901 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1902 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1903 017 /* compare maginitude of two ints (unsigned) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1904 018 int mp_cmp_mag (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1905 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1906 020 int n;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1907 021 mp_digit *tmpa, *tmpb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1908 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1909 023 /* compare based on # of non-zero digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1910 024 if (a->used > b->used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1911 025 return MP_GT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1912 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1913 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1914 028 if (a->used < b->used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1915 029 return MP_LT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1916 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1917 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1918 032 /* alias for a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1919 033 tmpa = a->dp + (a->used - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1920 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1921 035 /* alias for b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1922 036 tmpb = b->dp + (a->used - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1923 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1924 038 /* compare based on digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1925 039 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1926 040 if (*tmpa > *tmpb) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1927 041 return MP_GT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1928 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1929 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1930 044 if (*tmpa < *tmpb) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1931 045 return MP_LT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1932 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1933 047 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1934 048 return MP_EQ;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1935 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1936 050 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
1937 051
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1938 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1939 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1940
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1941 The two if statements (lines 24 and 28) compare the number of digits in the two inputs. These two are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1942 performed before all of the digits are compared since it is a very cheap test to perform and can potentially save
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1943 considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1944 smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1945
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1946
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1947
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1948 \subsection{Signed Comparisons}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1949 Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1950 comparison a trivial signed comparison algorithm can be written.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1951
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1952 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1953 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1954 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1955 \hline Algorithm \textbf{mp\_cmp}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1956 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1957 \textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1958 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1959 1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1960 2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1961 3. if $a.sign = MP\_NEG$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1962 \hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1963 4 Otherwise \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1964 \hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1965 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1966 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1967 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1968 \caption{Algorithm mp\_cmp}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1969 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1970
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1971 \textbf{Algorithm mp\_cmp.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1972 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1973 comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1974 three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1975 $\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1976
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1977 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1978 \hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1979 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1980 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1981 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1982 017 /* compare two ints (signed)*/
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1983 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1984 019 mp_cmp (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1985 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1986 021 /* compare based on sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1987 022 if (a->sign != b->sign) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1988 023 if (a->sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1989 024 return MP_LT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1990 025 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1991 026 return MP_GT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1992 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1993 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1994 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1995 030 /* compare digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1996 031 if (a->sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1997 032 /* if negative compare opposite direction */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1998 033 return mp_cmp_mag(b, a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
1999 034 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2000 035 return mp_cmp_mag(a, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2001 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2002 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2003 038 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2004 039
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2005 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2006 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2007
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2008 The two if statements (lines 22 and 23) perform the initial sign comparison. If the signs are not the equal then which ever
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2009 has the positive sign is larger. The inputs are compared (line 31) based on magnitudes. If the signs were both
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2010 negative then the unsigned comparison is performed in the opposite direction (line 33). Otherwise, the signs are assumed to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2011 be both positive and a forward direction unsigned comparison is performed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2012
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2013 \section*{Exercises}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2014 \begin{tabular}{cl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2015 $\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2016 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2017 $\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2018 & of two random digits (of equal magnitude) before a difference is found. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2019 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2020 $\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2021 & on the observations made in the previous problem. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2022 &
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2023 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2025 \chapter{Basic Arithmetic}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2026 \section{Introduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2027 At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2028 established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2029 algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2030 that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2031 which easily places them at $O(n^2)$ or even $O(n^3)$ work levels.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2033 All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2034 logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2035 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$}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2036 Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2037 For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2039 One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2040 from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2041 result is $110_2$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2043 \section{Addition and Subtraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2044 In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2045 $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{)}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2046 As a result subtraction can be performed with a trivial series of logical operations and an addition.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2048 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2049 sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2050 subtraction algorithms with the sign fixed up appropriately.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2052 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2053 the integers respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2055 \subsection{Low Level Addition}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2056 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2057 trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2058 Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2060 \newpage
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2061 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2062 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2063 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2064 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2065 \hline Algorithm \textbf{s\_mp\_add}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2066 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2067 \textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2068 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2069 1. if $a.used > b.used$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2070 \hspace{+3mm}1.1 $min \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2071 \hspace{+3mm}1.2 $max \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2072 \hspace{+3mm}1.3 $x \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2073 2. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2074 \hspace{+3mm}2.1 $min \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2075 \hspace{+3mm}2.2 $max \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2076 \hspace{+3mm}2.3 $x \leftarrow b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2077 3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2078 4. $oldused \leftarrow c.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2079 5. $c.used \leftarrow max + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2080 6. $u \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2081 7. for $n$ from $0$ to $min - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2082 \hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2083 \hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2084 \hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2085 8. if $min \ne max$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2086 \hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2087 \hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2088 \hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2089 \hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2090 9. $c_{max} \leftarrow u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2091 10. if $olduse > max$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2092 \hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2093 \hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2094 11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2095 12. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2096 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2097 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2098 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2099 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2100 \caption{Algorithm s\_mp\_add}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2101 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2102
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2103 \textbf{Algorithm s\_mp\_add.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2104 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2105 Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2106 MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2107
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2108 The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2109 will simply add all of the smallest input to the largest input and store that first part of the result in the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2110 destination. Then it will apply a simpler addition loop to excess digits of the larger input.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2111
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2112 The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2113 inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2114 same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2115 of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2117 At this point the first addition loop will go through as many digit positions that both inputs have. The carry
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2118 variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2119 one digit of the summand. First
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2120 two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2121 in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2122
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2123 Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2124 for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2125 and the carry to the destination.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2126
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2127 The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2128
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2129
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2130 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2131 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2132 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2133 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2134 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2135 017 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2136 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2137 019 s_mp_add (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2138 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2139 021 mp_int *x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2140 022 int olduse, res, min, max;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2141 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2142 024 /* find sizes, we let |a| <= |b| which means we have to sort
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2143 025 * them. "x" will point to the input with the most digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2144 026 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2145 027 if (a->used > b->used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2146 028 min = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2147 029 max = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2148 030 x = a;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2149 031 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2150 032 min = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2151 033 max = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2152 034 x = b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2153 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2154 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2155 037 /* init result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2156 038 if (c->alloc < max + 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2157 039 if ((res = mp_grow (c, max + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2158 040 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2159 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2160 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2161 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2162 044 /* get old used digit count and set new one */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2163 045 olduse = c->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2164 046 c->used = max + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2165 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2166 048 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2167 049 register mp_digit u, *tmpa, *tmpb, *tmpc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2168 050 register int i;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2169 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2170 052 /* alias for digit pointers */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2171 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2172 054 /* first input */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2173 055 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2174 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2175 057 /* second input */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2176 058 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2177 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2178 060 /* destination */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2179 061 tmpc = c->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2180 062
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2181 063 /* zero the carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2182 064 u = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2183 065 for (i = 0; i < min; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2184 066 /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2185 067 *tmpc = *tmpa++ + *tmpb++ + u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2186 068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2187 069 /* U = carry bit of T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2188 070 u = *tmpc >> ((mp_digit)DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2189 071
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2190 072 /* take away carry bit from T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2191 073 *tmpc++ &= MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2192 074 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2193 075
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2194 076 /* now copy higher words if any, that is in A+B
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2195 077 * if A or B has more digits add those in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2196 078 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2197 079 if (min != max) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2198 080 for (; i < max; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2199 081 /* T[i] = X[i] + U */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2200 082 *tmpc = x->dp[i] + u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2201 083
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2202 084 /* U = carry bit of T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2203 085 u = *tmpc >> ((mp_digit)DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2204 086
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2205 087 /* take away carry bit from T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2206 088 *tmpc++ &= MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2207 089 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2208 090 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2209 091
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2210 092 /* add carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2211 093 *tmpc++ = u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2212 094
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2213 095 /* clear digits above oldused */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2214 096 for (i = c->used; i < olduse; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2215 097 *tmpc++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2216 098 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2217 099 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2218 100
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2219 101 mp_clamp (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2220 102 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2221 103 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2222 104 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2223 105
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2224 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2225 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2226
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2227 We first sort (lines 27 to 35) the inputs based on magnitude and determine the $min$ and $max$ variables.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2228 Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2229 grow the destination (37 to 42) ensure that it can accomodate the result of the addition.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2230
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2231 Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2232 lines 55, 58 and 61 represent the two inputs and destination variables respectively. These aliases are used to ensure the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2233 compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2234
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2235 The initial carry $u$ will be cleared (line 64), note that $u$ is of type mp\_digit which ensures type
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2236 compatibility within the implementation. The initial addition (line 65 to 74) adds digits from
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2237 both inputs until the smallest input runs out of digits. Similarly the conditional addition loop
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2238 (line 80 to 90) adds the remaining digits from the larger of the two inputs. The addition is finished
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2239 with the final carry being stored in $tmpc$ (line 93). Note the ``++'' operator within the same expression.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2240 After line 93, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2241 for the next loop (line 96 to 99) which set any old upper digits to zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2242
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2243 \subsection{Low Level Subtraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2244 The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2245 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2246 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2247 This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2248
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2249
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2250 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2251 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2252 this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2253 mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2254
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2255 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''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2256 data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2257
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2258 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2259 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2260 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2261 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2262 \hline Algorithm \textbf{s\_mp\_sub}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2263 \textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2264 \textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2265 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2266 1. $min \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2267 2. $max \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2268 3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2269 4. $oldused \leftarrow c.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2270 5. $c.used \leftarrow max$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2271 6. $u \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2272 7. for $n$ from $0$ to $min - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2273 \hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2274 \hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2275 \hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2276 8. if $min < max$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2277 \hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2278 \hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2279 \hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2280 \hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2281 9. if $oldused > max$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2282 \hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2283 \hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2284 10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2285 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2286 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2287 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2288 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2289 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2290 \caption{Algorithm s\_mp\_sub}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2291 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2292
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2293 \textbf{Algorithm s\_mp\_sub.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2294 This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2295 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2296 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2297 of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2298
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2299 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2300 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2301 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2302 set to the maximal count for the operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2303
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2304 The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2305 subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2306 loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2307
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2308 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2309 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2310 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2311 way to the most significant bit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2312
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2313 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2314 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2315 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2316 carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2317
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2318 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2319 10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2320
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2321 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2322 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2323 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2324 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2325 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2326 017 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2327 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2328 019 s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2329 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2330 021 int olduse, res, min, max;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2331 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2332 023 /* find sizes */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2333 024 min = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2334 025 max = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2335 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2336 027 /* init result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2337 028 if (c->alloc < max) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2338 029 if ((res = mp_grow (c, max)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2339 030 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2340 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2341 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2342 033 olduse = c->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2343 034 c->used = max;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2344 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2345 036 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2346 037 register mp_digit u, *tmpa, *tmpb, *tmpc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2347 038 register int i;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2348 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2349 040 /* alias for digit pointers */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2350 041 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2351 042 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2352 043 tmpc = c->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2353 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2354 045 /* set carry to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2355 046 u = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2356 047 for (i = 0; i < min; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2357 048 /* T[i] = A[i] - B[i] - U */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2358 049 *tmpc = *tmpa++ - *tmpb++ - u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2359 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2360 051 /* U = carry bit of T[i]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2361 052 * Note this saves performing an AND operation since
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2362 053 * if a carry does occur it will propagate all the way to the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2363 054 * MSB. As a result a single shift is enough to get the carry
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2364 055 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2365 056 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2366 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2367 058 /* Clear carry from T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2368 059 *tmpc++ &= MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2369 060 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2370 061
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2371 062 /* now copy higher words if any, e.g. if A has more digits than B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2372 063 for (; i < max; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2373 064 /* T[i] = A[i] - U */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2374 065 *tmpc = *tmpa++ - u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2375 066
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2376 067 /* U = carry bit of T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2377 068 u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2378 069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2379 070 /* Clear carry from T[i] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2380 071 *tmpc++ &= MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2381 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2382 073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2383 074 /* clear digits above used (since we may not have grown result above) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2384
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2385 075 for (i = c->used; i < olduse; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2386 076 *tmpc++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2387 077 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2388 078 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2389 079
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2390 080 mp_clamp (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2391 081 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2392 082 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2393 083
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2394 084 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2395 085
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2396 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2397 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2398
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2399 Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2400 (lines 24 and 25). In reality the $min$ and $max$ variables are only aliases and are only
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2401 used to make the source code easier to read. Again the pointer alias optimization is used
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2402 within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2403 (lines 41, 42 and 43) for $a$, $b$ and $c$ respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2404
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2405 The first subtraction loop (lines 46 through 60) subtract digits from both inputs until the smaller of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2406 the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2407 method of extracting the carry (line 56). The traditional method for extracting the carry would be to shift
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2408 by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2409 the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2410 extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2411 most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2412 optimization only works on twos compliment machines which is a safe assumption to make.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2413
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2414 If $a$ has a larger magnitude than $b$ an additional loop (lines 63 through 72) is required to propagate
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2415 the carry through $a$ and copy the result to $c$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2416
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2417 \subsection{High Level Addition}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2418 Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2419 established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2420 types.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2421
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2422 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2423 flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2424
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2425 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2426 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2427 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2428 \hline Algorithm \textbf{mp\_add}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2429 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2430 \textbf{Output}. The signed addition $c = a + b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2431 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2432 1. if $a.sign = b.sign$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2433 \hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2434 \hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2435 2. else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2436 \hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2437 \hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2438 \hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2439 \hspace{3mm}2.2 else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2440 \hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2441 \hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2442 3. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2443 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2444 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2445 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2446 \caption{Algorithm mp\_add}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2447 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2448
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2449 \textbf{Algorithm mp\_add.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2450 This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2451 either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2452 straightforward but restricted since subtraction can only produce positive results.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2453
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2454 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2455 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2456 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2457 \begin{tabular}{|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2458 \hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2459 \hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2460 \hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2461 \hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2462 \hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2463 \hline &&&&\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2464
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2465 \hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2466 \hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2467
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2468 \hline &&&&\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2469
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2470 \hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2471 \hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2472
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2473 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2474 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2475 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2476 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2477 \caption{Addition Guide Chart}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2478 \label{fig:AddChart}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2479 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2480
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2481 Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2482 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2483 forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2484 follows how the implementation actually was achieved.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2485
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2486 Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2487 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2488 to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2489
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2490 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2491 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2492 within algorithm s\_mp\_add will force $-0$ to become $0$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2493
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2494 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2495 \hspace{-5.1mm}{\bf File}: bn\_mp\_add.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2496 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2497 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2498 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2499 017 /* high level addition (handles signs) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2500 018 int mp_add (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2501 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2502 020 int sa, sb, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2503 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2504 022 /* get sign of both inputs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2505 023 sa = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2506 024 sb = b->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2507 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2508 026 /* handle two cases, not four */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2509 027 if (sa == sb) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2510 028 /* both positive or both negative */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2511 029 /* add their magnitudes, copy the sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2512 030 c->sign = sa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2513 031 res = s_mp_add (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2514 032 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2515 033 /* one positive, the other negative */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2516 034 /* subtract the one with the greater magnitude from */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2517 035 /* the one of the lesser magnitude. The result gets */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2518 036 /* the sign of the one with the greater magnitude. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2519 037 if (mp_cmp_mag (a, b) == MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2520 038 c->sign = sb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2521 039 res = s_mp_sub (b, a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2522 040 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2523 041 c->sign = sa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2524 042 res = s_mp_sub (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2525 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2526 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2527 045 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2528 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2529 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2530 048 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2531 049
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2532 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2533 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2534
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2535 The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2536 is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2537 explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2538 level functions do so. Returning their return code is sufficient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2539
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2540 \subsection{High Level Subtraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2541 The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2542
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2543 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2544 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2545 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2546 \hline Algorithm \textbf{mp\_sub}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2547 \textbf{Input}. Two mp\_ints $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2548 \textbf{Output}. The signed subtraction $c = a - b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2549 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2550 1. if $a.sign \ne b.sign$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2551 \hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2552 \hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2553 2. else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2554 \hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2555 \hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2556 \hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2557 \hspace{3mm}2.2 else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2558 \hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2559 MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2560 MP\_NEG & \mbox{otherwise} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2561 \end{array} \right .$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2562 \hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2563 3. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2564 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2565 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2566 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2567 \caption{Algorithm mp\_sub}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2568 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2569
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2570 \textbf{Algorithm mp\_sub.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2571 This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2572 \cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2573 the operations required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2574
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2575 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2576 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2577 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2578 \begin{tabular}{|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2579 \hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2580 \hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2581 \hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2582 \hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2583 \hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2584 \hline &&&& \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2585 \hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2586 \hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2587 \hline &&&& \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2588 \hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2589 \hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2590 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2591 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2592 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2593 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2594 \caption{Subtraction Guide Chart}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2595 \label{fig:SubChart}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2596 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2597
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2598 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2599 algorithm from producing $-a - -a = -0$ as a result.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2600
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2601 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2602 \hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2603 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2604 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2605 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2606 017 /* high level subtraction (handles signs) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2607 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2608 019 mp_sub (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2609 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2610 021 int sa, sb, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2611 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2612 023 sa = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2613 024 sb = b->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2614 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2615 026 if (sa != sb) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2616 027 /* subtract a negative from a positive, OR */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2617 028 /* subtract a positive from a negative. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2618 029 /* In either case, ADD their magnitudes, */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2619 030 /* and use the sign of the first number. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2620 031 c->sign = sa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2621 032 res = s_mp_add (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2622 033 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2623 034 /* subtract a positive from a positive, OR */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2624 035 /* subtract a negative from a negative. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2625 036 /* First, take the difference between their */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2626 037 /* magnitudes, then... */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2627 038 if (mp_cmp_mag (a, b) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2628 039 /* Copy the sign from the first */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2629 040 c->sign = sa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2630 041 /* The first has a larger or equal magnitude */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2631 042 res = s_mp_sub (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2632 043 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2633 044 /* The result has the *opposite* sign from */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2634 045 /* the first number. */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2635 046 c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2636 047 /* The second has a larger magnitude */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2637 048 res = s_mp_sub (b, a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2638 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2639 050 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2640 051 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2641 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2642 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2643 054 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2644 055
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2645 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2646 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2647
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2648 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2649 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2650 ``greater than or equal to'' comparison.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2651
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2652 \section{Bit and Digit Shifting}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2653 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2654 This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2655
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2656 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2657 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2658 are on radix-$\beta$ digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2659
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2660 \subsection{Multiplication by Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2661
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2662 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2663 operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2664
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2665 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2666 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2667 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2668 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2669 \hline Algorithm \textbf{mp\_mul\_2}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2670 \textbf{Input}. One mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2671 \textbf{Output}. $b = 2a$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2672 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2673 1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2674 2. $oldused \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2675 3. $b.used \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2676 4. $r \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2677 5. for $n$ from 0 to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2678 \hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2679 \hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2680 \hspace{3mm}5.3 $r \leftarrow rr$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2681 6. If $r \ne 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2682 \hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2683 \hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2684 7. If $b.used < oldused - 1$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2685 \hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2686 \hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2687 8. $b.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2688 9. Return(\textit{MP\_OKAY}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2689 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2690 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2691 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2692 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2693 \caption{Algorithm mp\_mul\_2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2694 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2695
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2696 \textbf{Algorithm mp\_mul\_2.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2697 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2698 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2699 it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2700
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2701 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2702 is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2703
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2704 Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2705 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2706 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2707 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2708 forwarding the carry to the next iteration.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2709
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2710 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2711 Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2712
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2713 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2714 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2715 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2716 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2717 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2718 017 /* b = a*2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2719 018 int mp_mul_2(mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2720 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2721 020 int x, res, oldused;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2722 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2723 022 /* grow to accomodate result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2724 023 if (b->alloc < a->used + 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2725 024 if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2726 025 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2727 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2728 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2729 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2730 029 oldused = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2731 030 b->used = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2732 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2733 032 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2734 033 register mp_digit r, rr, *tmpa, *tmpb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2735 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2736 035 /* alias for source */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2737 036 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2738 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2739 038 /* alias for dest */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2740 039 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2741 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2742 041 /* carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2743 042 r = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2744 043 for (x = 0; x < a->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2745 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2746 045 /* get what will be the *next* carry bit from the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2747 046 * MSB of the current digit
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2748 047 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2749 048 rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2750 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2751 050 /* now shift up this digit, add in the carry [from the previous] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2752 051 *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2753 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2754 053 /* copy the carry that would be from the source
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2755 054 * digit into the next iteration
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2756 055 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2757 056 r = rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2758 057 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2759 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2760 059 /* new leading digit? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2761 060 if (r != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2762 061 /* add a MSB which is always 1 at this point */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2763 062 *tmpb = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2764 063 ++(b->used);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2765 064 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2766 065
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2767 066 /* now zero any excess digits on the destination
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2768 067 * that we didn't write to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2769 068 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2770 069 tmpb = b->dp + b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2771 070 for (x = b->used; x < oldused; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2772 071 *tmpb++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2773 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2774 073 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2775 074 b->sign = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2776 075 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2777 076 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2778 077 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2779 078
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2780 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2781 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2782
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2783 This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2784 is the use of the logical shift operator on line 51 to perform a single precision doubling.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2785
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2786 \subsection{Division by Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2787 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2788
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2789 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2790 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2791 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2792 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2793 \hline Algorithm \textbf{mp\_div\_2}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2794 \textbf{Input}. One mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2795 \textbf{Output}. $b = a/2$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2796 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2797 1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2798 2. If the reallocation failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2799 3. $oldused \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2800 4. $b.used \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2801 5. $r \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2802 6. for $n$ from $b.used - 1$ to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2803 \hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2804 \hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2805 \hspace{3mm}6.3 $r \leftarrow rr$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2806 7. If $b.used < oldused - 1$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2807 \hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2808 \hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2809 8. $b.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2810 9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2811 10. Return(\textit{MP\_OKAY}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2812 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2813 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2814 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2815 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2816 \caption{Algorithm mp\_div\_2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2817 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2818
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2819 \textbf{Algorithm mp\_div\_2.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2820 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2821 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2822 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2823 reading past the end of the array of digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2824
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2825 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2826 least significant bit not the most significant bit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2827
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2828 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2829 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2830 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2831 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2832 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2833 017 /* b = a/2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2834 018 int mp_div_2(mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2835 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2836 020 int x, res, oldused;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2837 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2838 022 /* copy */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2839 023 if (b->alloc < a->used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2840 024 if ((res = mp_grow (b, a->used)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2841 025 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2842 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2843 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2844 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2845 029 oldused = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2846 030 b->used = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2847 031 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2848 032 register mp_digit r, rr, *tmpa, *tmpb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2849 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2850 034 /* source alias */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2851 035 tmpa = a->dp + b->used - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2852 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2853 037 /* dest alias */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2854 038 tmpb = b->dp + b->used - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2855 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2856 040 /* carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2857 041 r = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2858 042 for (x = b->used - 1; x >= 0; x--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2859 043 /* get the carry for the next iteration */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2860 044 rr = *tmpa & 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2861 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2862 046 /* shift the current digit, add in carry and store */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2863 047 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2864 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2865 049 /* forward carry to next iteration */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2866 050 r = rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2867 051 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2868 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2869 053 /* zero excess digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2870 054 tmpb = b->dp + b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2871 055 for (x = b->used; x < oldused; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2872 056 *tmpb++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2873 057 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2874 058 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2875 059 b->sign = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2876 060 mp_clamp (b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2877 061 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2878 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2879 063 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
2880 064
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2881 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2882 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2883
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2884 \section{Polynomial Basis Operations}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2885 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2886 the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2887 place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2888 division and Karatsuba multiplication.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2889
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2890 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2891 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2892 polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2893
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2894 \subsection{Multiplication by $x$}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2895
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2896 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2897 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2898 multiplying by the integer $\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2899
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2900 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2901 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2902 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2903 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2904 \hline Algorithm \textbf{mp\_lshd}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2905 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2906 \textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2907 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2908 1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2909 2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2910 3. If the reallocation failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2911 4. $a.used \leftarrow a.used + b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2912 5. $i \leftarrow a.used - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2913 6. $j \leftarrow a.used - 1 - b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2914 7. for $n$ from $a.used - 1$ to $b$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2915 \hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2916 \hspace{3mm}7.2 $i \leftarrow i - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2917 \hspace{3mm}7.3 $j \leftarrow j - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2918 8. for $n$ from 0 to $b - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2919 \hspace{3mm}8.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2920 9. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2921 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2922 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2923 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2924 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2925 \caption{Algorithm mp\_lshd}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2926 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2927
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2928 \textbf{Algorithm mp\_lshd.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2929 This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2930 from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2931 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2932 different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2933 typically used on values where the original value is no longer required. The algorithm will return success immediately if
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2934 $b \le 0$ since the rest of algorithm is only valid when $b > 0$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2935
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2936 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2937 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}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2938 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2939 step 8 sets the lower $b$ digits to zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2940
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2941 \newpage
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2942 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2943 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2944 \includegraphics{pics/sliding_window.ps}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2945 \caption{Sliding Window Movement}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2946 \label{pic:sliding_window}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2947 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2948 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2949
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2950 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2951 \hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2952 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2953 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2954 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2955 017 /* shift left a certain amount of digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2956 018 int mp_lshd (mp_int * a, int b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2957 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2958 020 int x, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2959 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2960 022 /* if its less than zero return */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2961 023 if (b <= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2962 024 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2963 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2964 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2965 027 /* grow to fit the new digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2966 028 if (a->alloc < a->used + b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2967 029 if ((res = mp_grow (a, a->used + b)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2968 030 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2969 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2970 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2971 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2972 034 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2973 035 register mp_digit *top, *bottom;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2974 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2975 037 /* increment the used by the shift amount then copy upwards */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2976 038 a->used += b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2977 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2978 040 /* top */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2979 041 top = a->dp + a->used - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2980 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2981 043 /* base */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2982 044 bottom = a->dp + a->used - 1 - b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2983 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2984 046 /* much like mp_rshd this is implemented using a sliding window
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2985 047 * except the window goes the otherway around. Copying from
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2986 048 * the bottom to the top. see bn_mp_rshd.c for more info.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2987 049 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2988 050 for (x = a->used - 1; x >= b; x--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2989 051 *top-- = *bottom--;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2990 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2991 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2992 054 /* zero the lower digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2993 055 top = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2994 056 for (x = 0; x < b; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2995 057 *top++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2996 058 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2997 059 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2998 060 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
2999 061 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3000 062 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3001 063
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3002 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3003 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3004
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3005 The if statement (line 23) ensures that the $b$ variable is greater than zero since we do not interpret negative
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3006 shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3007 the need for an additional variable in the for loop. The variable $top$ (line 41) is an alias
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3008 for the leading digit while $bottom$ (line 44) is an alias for the trailing edge. The aliases form a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3009 window of exactly $b$ digits over the input.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3010
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3011 \subsection{Division by $x$}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3012
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3013 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3014
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3015 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3016 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3017 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3018 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3019 \hline Algorithm \textbf{mp\_rshd}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3020 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3021 \textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3022 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3023 1. If $b \le 0$ then return. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3024 2. If $a.used \le b$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3025 \hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3026 \hspace{3mm}2.2 Return. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3027 3. $i \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3028 4. $j \leftarrow b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3029 5. for $n$ from 0 to $a.used - b - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3030 \hspace{3mm}5.1 $a_i \leftarrow a_j$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3031 \hspace{3mm}5.2 $i \leftarrow i + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3032 \hspace{3mm}5.3 $j \leftarrow j + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3033 6. for $n$ from $a.used - b$ to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3034 \hspace{3mm}6.1 $a_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3035 7. $a.used \leftarrow a.used - b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3036 8. Return. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3037 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3038 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3039 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3040 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3041 \caption{Algorithm mp\_rshd}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3042 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3044 \textbf{Algorithm mp\_rshd.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3045 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3046 it does not require single precision division. This algorithm does not actually return an error code as it cannot fail.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3048 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3049 to the shift count $b$ then it will simply zero the input and return.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3051 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3052 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3053 Also the digits are copied from the leading to the trailing edge.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3055 Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3057 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3058 \hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3059 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3060 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3061 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3062 017 /* shift right a certain amount of digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3063 018 void mp_rshd (mp_int * a, int b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3064 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3065 020 int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3066 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3067 022 /* if b <= 0 then ignore it */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3068 023 if (b <= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3069 024 return;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3070 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3071 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3072 027 /* if b > used then simply zero it and return */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3073 028 if (a->used <= b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3074 029 mp_zero (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3075 030 return;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3076 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3077 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3078 033 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3079 034 register mp_digit *bottom, *top;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3080 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3081 036 /* shift the digits down */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3082 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3083 038 /* bottom */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3084 039 bottom = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3085 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3086 041 /* top [offset into digits] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3087 042 top = a->dp + b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3088 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3089 044 /* this is implemented as a sliding window where
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3090 045 * the window is b-digits long and digits from
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3091 046 * the top of the window are copied to the bottom
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3092 047 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3093 048 * e.g.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3094 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3095 050 b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3096 051 /\symbol{92} | ---->
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3097 052 \symbol{92}-------------------/ ---->
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3098 053 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3099 054 for (x = 0; x < (a->used - b); x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3100 055 *bottom++ = *top++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3101 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3102 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3103 058 /* zero the top digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3104 059 for (; x < a->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3105 060 *bottom++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3106 061 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3107 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3108 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3109 064 /* remove excess digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3110 065 a->used -= b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3111 066 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3112 067 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3113 068
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3114 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3115 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3117 The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3118 form a sliding window except we copy in the other direction. After the window (line 59) we then zero
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3119 the upper digits of the input to make sure the result is correct.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3120
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3121 \section{Powers of Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3122
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3123 Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3124 example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3125 shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3126
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3127 \subsection{Multiplication by Power of Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3128
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3129 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3130 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3131 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3132 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3133 \hline Algorithm \textbf{mp\_mul\_2d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3134 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3135 \textbf{Output}. $c \leftarrow a \cdot 2^b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3136 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3137 1. $c \leftarrow a$. (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3138 2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3139 3. If the reallocation failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3140 4. If $b \ge lg(\beta)$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3141 \hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3142 \hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3143 5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3144 6. If $d \ne 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3145 \hspace{3mm}6.1 $mask \leftarrow 2^d$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3146 \hspace{3mm}6.2 $r \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3147 \hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3148 \hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3149 \hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3150 \hspace{6mm}6.3.3 $r \leftarrow rr$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3151 \hspace{3mm}6.4 If $r > 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3152 \hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3153 \hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3154 7. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3155 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3156 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3157 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3158 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3159 \caption{Algorithm mp\_mul\_2d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3160 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3161
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3162 \textbf{Algorithm mp\_mul\_2d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3163 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3164 quickly compute the product.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3165
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3166 First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3167 $\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}$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3168 left.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3169
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3170 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3171 required. If it is non-zero a modified shift loop is used to calculate the remaining product.
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3172 Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3173 variable is used to extract the upper $d$ bits to form the carry for the next iteration.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3174
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3175 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3176 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3177
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3178 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3179 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3180 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3181 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3182 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3183 017 /* shift left by a certain bit count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3184 018 int mp_mul_2d (mp_int * a, int b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3185 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3186 020 mp_digit d;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3187 021 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3188 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3189 023 /* copy */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3190 024 if (a != c) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3191 025 if ((res = mp_copy (a, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3192 026 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3193 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3194 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3195 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3196 030 if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3197 031 if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3198 032 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3199 033 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3200 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3201 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3202 036 /* shift by as many digits in the bit count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3203 037 if (b >= (int)DIGIT_BIT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3204 038 if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3205 039 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3206 040 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3207 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3208 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3209 043 /* shift any bit count < DIGIT_BIT */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3210 044 d = (mp_digit) (b % DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3211 045 if (d != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3212 046 register mp_digit *tmpc, shift, mask, r, rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3213 047 register int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3214 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3215 049 /* bitmask for carries */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3216 050 mask = (((mp_digit)1) << d) - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3217 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3218 052 /* shift for msbs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3219 053 shift = DIGIT_BIT - d;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3220 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3221 055 /* alias */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3222 056 tmpc = c->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3223 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3224 058 /* carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3225 059 r = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3226 060 for (x = 0; x < c->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3227 061 /* get the higher bits of the current word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3228 062 rr = (*tmpc >> shift) & mask;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3229 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3230 064 /* shift the current word and OR in the carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3231 065 *tmpc = ((*tmpc << d) | r) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3232 066 ++tmpc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3233 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3234 068 /* set the carry to the carry bits of the current word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3235 069 r = rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3236 070 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3237 071
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3238 072 /* set final carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3239 073 if (r != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3240 074 c->dp[(c->used)++] = r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3241 075 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3242 076 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3243 077 mp_clamp (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3244 078 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3245 079 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3246 080 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3247 081
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3248 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3249 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3250
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3251 The shifting is performed in--place which means the first step (line 24) is to copy the input to the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3252 destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3253 has to be grown (line 31) to accomodate the result.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3254
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3255 If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3256 of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3257 loop (lines 45 to 76) we make use of pre--computed values $shift$ and $mask$. These are used to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3258 extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3259 chain between consecutive iterations to propagate the carry.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3260
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3261 \subsection{Division by Power of Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3262
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3263 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3264 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3265 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3266 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3267 \hline Algorithm \textbf{mp\_div\_2d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3268 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3269 \textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3270 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3271 1. If $b \le 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3272 \hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3273 \hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3274 \hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3275 2. $c \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3276 3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3277 4. If $b \ge lg(\beta)$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3278 \hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3279 5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3280 6. If $k \ne 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3281 \hspace{3mm}6.1 $mask \leftarrow 2^k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3282 \hspace{3mm}6.2 $r \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3283 \hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3284 \hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3285 \hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3286 \hspace{6mm}6.3.3 $r \leftarrow rr$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3287 7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3288 8. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3289 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3290 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3291 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3292 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3293 \caption{Algorithm mp\_div\_2d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3294 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3295
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3296 \textbf{Algorithm mp\_div\_2d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3297 This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3298 mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3299 by using algorithm mp\_mod\_2d.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3300
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3301 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3302 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3303 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3304 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3305 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3306 017 /* shift right by a certain bit count (store quotient in c, optional remaind
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3307 er in d) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3308 018 int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3309 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3310 020 mp_digit D, r, rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3311 021 int x, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3312 022 mp_int t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3313 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3314 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3315 025 /* if the shift count is <= 0 then we do no work */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3316 026 if (b <= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3317 027 res = mp_copy (a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3318 028 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3319 029 mp_zero (d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3320 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3321 031 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3322 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3323 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3324 034 if ((res = mp_init (&t)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3325 035 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3326 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3327 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3328 038 /* get the remainder */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3329 039 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3330 040 if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3331 041 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3332 042 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3333 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3334 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3335 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3336 046 /* copy */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3337 047 if ((res = mp_copy (a, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3338 048 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3339 049 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3340 050 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3341 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3342 052 /* shift by as many digits in the bit count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3343 053 if (b >= (int)DIGIT_BIT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3344 054 mp_rshd (c, b / DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3345 055 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3346 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3347 057 /* shift any bit count < DIGIT_BIT */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3348 058 D = (mp_digit) (b % DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3349 059 if (D != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3350 060 register mp_digit *tmpc, mask, shift;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3351 061
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3352 062 /* mask */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3353 063 mask = (((mp_digit)1) << D) - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3354 064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3355 065 /* shift for lsb */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3356 066 shift = DIGIT_BIT - D;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3357 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3358 068 /* alias */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3359 069 tmpc = c->dp + (c->used - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3360 070
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3361 071 /* carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3362 072 r = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3363 073 for (x = c->used - 1; x >= 0; x--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3364 074 /* get the lower bits of this word in a temp */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3365 075 rr = *tmpc & mask;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3366 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3367 077 /* shift the current word and mix in the carry bits from the previous
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3368 word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3369 078 *tmpc = (*tmpc >> D) | (r << shift);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3370 079 --tmpc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3371 080
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3372 081 /* set the carry to the carry bits of the current word found above */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3373 082 r = rr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3374 083 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3375 084 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3376 085 mp_clamp (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3377 086 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3378 087 mp_exch (&t, d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3379 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3380 089 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3381 090 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3382 091 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3383 092 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3384 093
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3385 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3386 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3387
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3388 The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3389 ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3390 result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3391 the quotient is obtained.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3392
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3393 The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3394 the direction of the shifts.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3395
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3396 \subsection{Remainder of Division by Power of Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3397
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3398 The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3399 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3400
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3401 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3402 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3403 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3404 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3405 \hline Algorithm \textbf{mp\_mod\_2d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3406 \textbf{Input}. One mp\_int $a$ and an integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3407 \textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3408 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3409 1. If $b \le 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3410 \hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3411 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3412 2. If $b > a.used \cdot lg(\beta)$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3413 \hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3414 \hspace{3mm}2.2 Return the result of step 2.1. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3415 3. $c \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3416 4. If step 3 failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3417 5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3418 \hspace{3mm}5.1 $c_n \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3419 6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3420 7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3421 8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3422 9. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3423 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3424 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3425 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3426 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3427 \caption{Algorithm mp\_mod\_2d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3428 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3429
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3430 \textbf{Algorithm mp\_mod\_2d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3431 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3432 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3433 is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3434
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3435 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3436 \hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3437 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3438 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3439 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3440 017 /* calc a value mod 2**b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3441 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3442 019 mp_mod_2d (mp_int * a, int b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3443 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3444 021 int x, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3445 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3446 023 /* if b is <= 0 then zero the int */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3447 024 if (b <= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3448 025 mp_zero (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3449 026 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3450 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3451 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3452 029 /* if the modulus is larger than the value than return */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3453 030 if (b >= (int) (a->used * DIGIT_BIT)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3454 031 res = mp_copy (a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3455 032 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3456 033 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3457 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3458 035 /* copy */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3459 036 if ((res = mp_copy (a, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3460 037 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3461 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3462 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3463 040 /* zero digits above the last digit of the modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3464 041 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x+
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3465 +) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3466 042 c->dp[x] = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3467 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3468 044 /* clear the digit that is not completely outside/inside the modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3469 045 c->dp[b / DIGIT_BIT] &=
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3470 046 (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digi
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3471 t) 1));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3472 047 mp_clamp (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3473 048 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3474 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3475 050 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3476 051
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3477 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3478 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3479
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3480 We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3481 than the input we just mp\_copy() the input and return right away. After this point we know we must actually
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3482 perform some work to produce the remainder.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3483
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3484 Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3485 the number. First we zero any digits above the last digit in $2^b$ (line 41). Next we reduce the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3486 leading digit of both (line 45) and then mp\_clamp().
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3487
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3488 \section*{Exercises}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3489 \begin{tabular}{cl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3490 $\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3491 & in $O(n)$ time. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3492 &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3493 $\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3494 & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3495 & upto $64$ with a hamming weight less than three. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3496 &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3497 $\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3498 & $2^k - 1$ as well. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3499 &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3500 $\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3501 & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3502 & any $n$-bit input. Note that the time of addition is ignored in the \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3503 & calculation. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3504 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3505 $\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3506 & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3507 & the cost of addition. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3508 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3509 $\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3510 & for $n = 64 \ldots 1024$ in steps of $64$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3511 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3512 $\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3513 & calculating the result of a signed comparison. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3514 &
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3515 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3516
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3517 \chapter{Multiplication and Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3518 \section{The Multipliers}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3519 For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3520 algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3521 where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3522 and squaring, leaving modular reductions for the subsequent chapter.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3523
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3524 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3525 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3526 exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3527 35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3528 multiplications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3529
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3530 For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3531 against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3532 overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3533 1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3534 This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3535
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3536 \section{Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3537 \subsection{The Baseline Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3538 \label{sec:basemult}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3539 \index{baseline multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3540 Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3541 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3542 multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3543 simplify most discussions, it will be assumed that the inputs have comparable number of digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3544
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3545 The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3546 used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3547 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3548 modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3549 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3550
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3551 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3552 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3553 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}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3554
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3555 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3556 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3557 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3558 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3559 \hline Algorithm \textbf{s\_mp\_mul\_digs}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3560 \textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3561 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3562 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3563 1. If min$(a.used, b.used) < \delta$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3564 \hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3565 \hspace{3mm}1.2 Return the result of step 1.1 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3566 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3567 Allocate and initialize a temporary mp\_int. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3568 2. Init $t$ to be of size $digs$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3569 3. If step 2 failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3570 4. $t.used \leftarrow digs$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3571 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3572 Compute the product. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3573 5. for $ix$ from $0$ to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3574 \hspace{3mm}5.1 $u \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3575 \hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3576 \hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3577 \hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3578 \hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3579 \hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3580 \hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3581 \hspace{3mm}5.5 if $ix + pb < digs$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3582 \hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3583 6. Clamp excess digits of $t$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3584 7. Swap $c$ with $t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3585 8. Clear $t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3586 9. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3587 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3588 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3589 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3590 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3591 \caption{Algorithm s\_mp\_mul\_digs}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3592 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3593
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3594 \textbf{Algorithm s\_mp\_mul\_digs.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3595 This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3596 a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3597 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}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3598 Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3599 inputs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3600
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3601 The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3602 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3603 temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3604 compute products when either $a = c$ or $b = c$ without overwriting the inputs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3605
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3606 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3607 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3608 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3609 innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3610
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3611 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3612 visualized in the following table.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3613
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3614 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3615 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3616 \begin{tabular}{|c|c|c|c|c|c|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3617 \hline && & 5 & 7 & 6 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3618 \hline $\times$&& & 2 & 4 & 1 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3619 \hline &&&&&&\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3620 && & 5 & 7 & 6 & $10^0(1)(576)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3621 &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3622 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3623 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3624 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3625 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3626 \caption{Long-Hand Multiplication Diagram}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3627 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3628
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3629 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3630 count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3631
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3632 Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3633 is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3634 double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3635 5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3636 $t_{ix+iy}$ and the result would be lost.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3637
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3638 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3639 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3640 exceed the precision requested.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3641
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3642 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3643 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3644 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3645 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3646 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3647 017 /* multiplies |a| * |b| and only computes upto digs digits of result
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3648 018 * HAC pp. 595, Algorithm 14.12 Modified so you can control how
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3649 019 * many digits of output are created.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3650 020 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3651 021 int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3652 022 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3653 023 mp_int t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3654 024 int res, pa, pb, ix, iy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3655 025 mp_digit u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3656 026 mp_word r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3657 027 mp_digit tmpx, *tmpt, *tmpy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3658 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3659 029 /* can we use the fast multiplier? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3660 030 if (((digs) < MP_WARRAY) &&
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3661 031 MIN (a->used, b->used) <
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3662 032 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3663 033 return fast_s_mp_mul_digs (a, b, c, digs);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3664 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3665 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3666 036 if ((res = mp_init_size (&t, digs)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3667 037 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3668 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3669 039 t.used = digs;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3670 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3671 041 /* compute the digits of the product directly */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3672 042 pa = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3673 043 for (ix = 0; ix < pa; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3674 044 /* set the carry to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3675 045 u = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3676 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3677 047 /* limit ourselves to making digs digits of output */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3678 048 pb = MIN (b->used, digs - ix);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3679 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3680 050 /* setup some aliases */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3681 051 /* copy of the digit from a used within the nested loop */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3682 052 tmpx = a->dp[ix];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3683 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3684 054 /* an alias for the destination shifted ix places */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3685 055 tmpt = t.dp + ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3686 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3687 057 /* an alias for the digits of b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3688 058 tmpy = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3689 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3690 060 /* compute the columns of the output and propagate the carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3691 061 for (iy = 0; iy < pb; iy++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3692 062 /* compute the column as a mp_word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3693 063 r = ((mp_word)*tmpt) +
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3694 064 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3695 065 ((mp_word) u);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3696 066
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3697 067 /* the new column is the lower part of the result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3698 068 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3699 069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3700 070 /* get the carry word from the result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3701 071 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3702 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3703 073 /* set carry if it is placed below digs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3704 074 if (ix + iy < digs) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3705 075 *tmpt = u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3706 076 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3707 077 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3708 078
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3709 079 mp_clamp (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3710 080 mp_exch (&t, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3711 081
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3712 082 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3713 083 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3714 084 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3715 085 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3716 086
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3717 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3718 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3719
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3720 First we determine (line 30) if the Comba method can be used first since it's faster. The conditions for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3721 sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3722 \textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3723 set to $\delta$ but can be reduced when memory is at a premium.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3724
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3725 If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3726 $t$ (line 36) to the exact size of the output to avoid further re--allocations. At this point we now
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3727 begin the $O(n^2)$ loop.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3728
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3729 This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3730 digits as output. In each iteration of the outer loop the $pb$ variable is set (line 48) to the maximum
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3731 number of inner loop iterations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3732
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3733 Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3734 carry from the previous iteration. A particularly important observation is that most modern optimizing
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3735 C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3736 is required for the product. In x86 terms for example, this means using the MUL instruction.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3737
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3738 Each digit of the product is stored in turn (line 68) and the carry propagated (line 71) to the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3739 next iteration.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3740
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3741 \subsection{Faster Multiplication by the ``Comba'' Method}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3742
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3743 One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3744 computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3745 in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3746 Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3747 interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3748 five years before.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3749
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3750 At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3751 twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3752 are produced then added together to form the final result. In the baseline algorithm the columns are added together
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3753 after each iteration to get the result instantaneously.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3754
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3755 In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3756 the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3757 after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3758 the product vector $\vec x$ as follows.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3759
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3760 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3761 \vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3762 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3763
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3764 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3765 of $576$ and $241$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3766
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3767 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3768 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3769 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3770 \begin{tabular}{|c|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3771 \hline & & 5 & 7 & 6 & First Input\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3772 \hline $\times$ & & 2 & 4 & 1 & Second Input\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3773 \hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3774 & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3775 $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3776 \hline 10 & 34 & 45 & 31 & 6 & Final Result \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3777 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3778 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3779 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3780 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3781 \caption{Comba Multiplication Diagram}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3782 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3783
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3784 At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3785 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3786 congruent to adding a leading zero digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3787
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3788 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3789 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3790 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3791 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3792 \hline Algorithm \textbf{Comba Fixup}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3793 \textbf{Input}. Vector $\vec x$ of dimension $k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3794 \textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3795 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3796 1. for $n$ from $0$ to $k - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3797 \hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3798 \hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3799 2. Return($\vec x$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3800 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3801 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3802 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3803 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3804 \caption{Algorithm Comba Fixup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3805 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3806
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3807 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3808 $241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3809 efficient than the baseline algorithm why not simply always use this algorithm?
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3810
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3811 \subsubsection{Column Weight.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3812 At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3813 independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3814 the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3815 three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3816 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3817 min$(m, n)$ which is fairly obvious.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3818
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3819 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3820 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3821 two quantities we must not violate the following
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3822
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3823 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3824 k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3825 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3826
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3827 Which reduces to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3828
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3829 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3830 k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3831 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3832
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3833 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3834 found.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3835
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3836 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3837 k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3838 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3839
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3840 The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3841 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3842 $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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3843
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3844 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3845 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3846 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3847 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3848 \hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3849 \textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3850 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3851 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3852 Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3853 1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3854 2. If step 1 failed return(\textit{MP\_MEM}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3855 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3856 3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3857 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3858 4. $\_ \hat W \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3859 5. for $ix$ from 0 to $pa - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3860 \hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3861 \hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3862 \hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3863 \hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3864 \hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3865 \hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3866 \hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3867 \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3868 6. $oldused \leftarrow c.used$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3869 7. $c.used \leftarrow digs$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3870 8. for $ix$ from $0$ to $pa$ do \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3871 \hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3872 9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3873 \hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3874 \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3875 10. Clamp $c$. \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3876 11. Return MP\_OKAY. \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3877 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3878 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3879 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3880 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3881 \caption{Algorithm fast\_s\_mp\_mul\_digs}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3882 \label{fig:COMBAMULT}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3883 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3884
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3885 \textbf{Algorithm fast\_s\_mp\_mul\_digs.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3886 This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3887
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3888 The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3889 loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3890 reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3891
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3892 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3893 $b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3894 $ix$ is. This is used for the immediately subsequent statement where we find $iy$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3895
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3896 The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3897 means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3898 pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3899 move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3900 $tx \ge a.used$ or $ty < 0$ occurs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3901
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3902 After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3903 into the next round by dividing $\_ \hat W$ by $\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3904
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3905 To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3906 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3907 $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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3908 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3909 and addition operations in the nested loop in parallel.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3910
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3911 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3912 \hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3913 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3914 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3915 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3916 017 /* Fast (comba) multiplier
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3917 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3918 019 * This is the fast column-array [comba] multiplier. It is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3919 020 * designed to compute the columns of the product first
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3920 021 * then handle the carries afterwards. This has the effect
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3921 022 * of making the nested loops that compute the columns very
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3922 023 * simple and schedulable on super-scalar processors.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3923 024 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3924 025 * This has been modified to produce a variable number of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3925 026 * digits of output so if say only a half-product is required
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3926 027 * you don't have to compute the upper half (a feature
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3927 028 * required for fast Barrett reduction).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3928 029 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3929 030 * Based on Algorithm 14.12 on pp.595 of HAC.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3930 031 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3931 032 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3932 033 int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3933 034 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3934 035 int olduse, res, pa, ix, iz;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3935 036 mp_digit W[MP_WARRAY];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3936 037 register mp_word _W;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3937 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3938 039 /* grow the destination as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3939 040 if (c->alloc < digs) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3940 041 if ((res = mp_grow (c, digs)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3941 042 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3942 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3943 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3944 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3945 046 /* number of output digits to produce */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3946 047 pa = MIN(digs, a->used + b->used);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3947 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3948 049 /* clear the carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3949 050 _W = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3950 051 for (ix = 0; ix < pa; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3951 052 int tx, ty;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3952 053 int iy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3953 054 mp_digit *tmpx, *tmpy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3954 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3955 056 /* get offsets into the two bignums */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3956 057 ty = MIN(b->used-1, ix);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3957 058 tx = ix - ty;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3958 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3959 060 /* setup temp aliases */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3960 061 tmpx = a->dp + tx;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3961 062 tmpy = b->dp + ty;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3962 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3963 064 /* this is the number of times the loop will iterrate, essentially
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3964 065 while (tx++ < a->used && ty-- >= 0) \{ ... \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3965 066 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3966 067 iy = MIN(a->used-tx, ty+1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3967 068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3968 069 /* execute loop */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3969 070 for (iz = 0; iz < iy; ++iz) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
3970 071 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3971 072
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3972 073 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3973 074
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3974 075 /* store term */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3975 076 W[ix] = ((mp_digit)_W) & MP_MASK;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3976 077
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3977 078 /* make next carry */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3978 079 _W = _W >> ((mp_word)DIGIT_BIT);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3979 080 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3980 081
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3981 082 /* setup dest */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3982 083 olduse = c->used;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3983 084 c->used = pa;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3984 085
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3985 086 \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3986 087 register mp_digit *tmpc;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3987 088 tmpc = c->dp;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3988 089 for (ix = 0; ix < pa+1; ix++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3989 090 /* now extract the previous digit [below the carry] */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3990 091 *tmpc++ = W[ix];
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3991 092 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3992 093
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3993 094 /* clear unused digits [that existed in the old copy of c] */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3994 095 for (; ix < olduse; ix++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3995 096 *tmpc++ = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3996 097 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3997 098 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3998 099 mp_clamp (c);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
3999 100 return MP_OKAY;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4000 101 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4001 102 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4002 103
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4003 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4004 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4005
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4006 As per the pseudo--code we first calculate $pa$ (line 47) as the number of digits to output. Next we begin the outer loop
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4007 to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines 61, 62) to point
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4008 inside the two multiplicands quickly.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4009
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4010 The inner loop (lines 70 to 73) of this implementation is where the tradeoff come into play. Originally this comba
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4011 implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4012 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4013 one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4014 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4015 slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4016 compiler has aliased $\_ \hat W$ to a CPU register.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4017
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4018 After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 76, 79) to forward it as
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4019 a carry for the next pass. After the outer loop we use the final carry (line 76) as the last digit of the product.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4020
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4021 \subsection{Polynomial Basis Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4022 To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4023 the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4024 $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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4026 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4027 directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4028 requires $O(n^2)$ time and would in practice be slower than the Comba technique.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4030 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4031 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4032 Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4033 effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4035 The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4036 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4037 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4038 by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4040 When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4041 is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4042 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4043 simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4044 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4045 points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4047 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4048 $\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4049 $\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4050 example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4052 \begin{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4053 \zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4054 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)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4055 \end{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4057 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4058 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4060 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4061 multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4062 $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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4063 summarizes the exponents for various values of $n$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4065 \begin{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4066 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4067 \begin{tabular}{|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4068 \hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4069 \hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4070 \hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4071 \hline $4$ & $1.403677461$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4072 \hline $5$ & $1.365212389$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4073 \hline $10$ & $1.278753601$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4074 \hline $100$ & $1.149426538$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4075 \hline $1000$ & $1.100270931$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4076 \hline $10000$ & $1.075252070$ &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4077 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4078 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4079 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4080 \caption{Asymptotic Running Time of Polynomial Basis Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4081 \label{fig:exponent}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4082 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4083
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4084 At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4085 of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4086 numbers.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4087
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4088 \subsubsection{Cutoff Point}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4089 The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4090 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4091 polynomial basis approach more costly to use with small inputs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4092
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4093 Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4094 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4095 when $m > y$ the Comba methods are slower than the polynomial basis algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4096
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4097 The exact location of $y$ depends on several key architectural elements of the computer platform in question.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4098
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4099 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4100 \item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4101 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4102 the cutoff point $y$ will be.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4103
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4104 \item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4105 grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4106 directly reflects on the ratio previous mentioned.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4107
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4108 \item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4109 influence over the cutoff point.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4111 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4112
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4113 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4114 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4115 a high resolution timer is available.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4117 \subsection{Karatsuba Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4118 Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4119 general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4120 light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4121
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4122 \begin{equation}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4123 f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4124 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4125
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4126 Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4127 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4128 out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4129 $\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4130
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4131 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4132 \begin{tabular}{rcrcrcrc}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4133 $\zeta_{0}$ & $=$ & & & & & $w_0$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4134 $\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4135 $\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4136 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4137 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4139 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4140 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.}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4141 making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4142
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4143 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4144 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4145 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4146 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4147 \hline Algorithm \textbf{mp\_karatsuba\_mul}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4148 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4149 \textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4150 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4151 1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4152 2. If step 2 failed then return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4153 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4154 Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4155 3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4156 4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4157 5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4158 6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4159 7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4160 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4161 Calculate the three products. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4162 8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4163 9. $x1y1 \leftarrow x1 \cdot y1$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4164 10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4165 11. $x0 \leftarrow y1 + y0$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4166 12. $t1 \leftarrow t1 \cdot x0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4167 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4168 Calculate the middle term. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4169 13. $x0 \leftarrow x0y0 + x1y1$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4170 14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4171 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4172 Calculate the final product. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4173 15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4174 16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4175 17. $t1 \leftarrow x0y0 + t1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4176 18. $c \leftarrow t1 + x1y1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4177 19. Clear all of the temporary variables. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4178 20. Return(\textit{MP\_OKAY}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4179 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4180 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4181 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4182 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4183 \caption{Algorithm mp\_karatsuba\_mul}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4184 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4185
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4186 \textbf{Algorithm mp\_karatsuba\_mul.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4187 This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4188 from Knuth \cite[pp. 294-295]{TAOCPV2}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4189
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4190 \index{radix point}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4191 In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4192 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4193 smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4194 compute the lower halves. Step 6 and 7 computer the upper halves.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4195
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4196 After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4197 $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
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4198 of an additional temporary variable, the algorithm can avoid an addition memory allocation operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4199
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4200 The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4201
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4202 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4203 \hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4204 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4205 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4206 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4207 017 /* c = |a| * |b| using Karatsuba Multiplication using
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4208 018 * three half size multiplications
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4209 019 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4210 020 * Let B represent the radix [e.g. 2**DIGIT_BIT] and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4211 021 * let n represent half of the number of digits in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4212 022 * the min(a,b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4213 023 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4214 024 * a = a1 * B**n + a0
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4215 025 * b = b1 * B**n + b0
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4216 026 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4217 027 * Then, a * b =>
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4218 028 a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4219 029 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4220 030 * Note that a1b1 and a0b0 are used twice and only need to be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4221 031 * computed once. So in total three half size (half # of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4222 032 * digit) multiplications are performed, a0b0, a1b1 and
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4223 033 * (a1+b1)(a0+b0)
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4224 034 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4225 035 * Note that a multiplication of half the digits requires
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4226 036 * 1/4th the number of single precision multiplications so in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4227 037 * total after one call 25% of the single precision multiplications
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4228 038 * are saved. Note also that the call to mp_mul can end up back
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4229 039 * in this function if the a0, a1, b0, or b1 are above the threshold.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4230 040 * This is known as divide-and-conquer and leads to the famous
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4231 041 * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4232 042 * the standard O(N**2) that the baseline/comba methods use.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4233 043 * Generally though the overhead of this method doesn't pay off
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4234 044 * until a certain size (N ~ 80) is reached.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4235 045 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4236 046 int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4237 047 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4238 048 mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4239 049 int B, err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4240 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4241 051 /* default the return code to an error */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4242 052 err = MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4243 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4244 054 /* min # of digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4245 055 B = MIN (a->used, b->used);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4246 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4247 057 /* now divide in two */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4248 058 B = B >> 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4249 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4250 060 /* init copy all the temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4251 061 if (mp_init_size (&x0, B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4252 062 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4253 063 if (mp_init_size (&x1, a->used - B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4254 064 goto X0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4255 065 if (mp_init_size (&y0, B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4256 066 goto X1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4257 067 if (mp_init_size (&y1, b->used - B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4258 068 goto Y0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4259 069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4260 070 /* init temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4261 071 if (mp_init_size (&t1, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4262 072 goto Y1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4263 073 if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4264 074 goto T1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4265 075 if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4266 076 goto X0Y0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4267 077
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4268 078 /* now shift the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4269 079 x0.used = y0.used = B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4270 080 x1.used = a->used - B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4271 081 y1.used = b->used - B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4272 082
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4273 083 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4274 084 register int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4275 085 register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4276 086
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4277 087 /* we copy the digits directly instead of using higher level functions
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4278 088 * since we also need to shift the digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4279 089 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4280 090 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4281 091 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4282 092
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4283 093 tmpx = x0.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4284 094 tmpy = y0.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4285 095 for (x = 0; x < B; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4286 096 *tmpx++ = *tmpa++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4287 097 *tmpy++ = *tmpb++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4288 098 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4289 099
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4290 100 tmpx = x1.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4291 101 for (x = B; x < a->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4292 102 *tmpx++ = *tmpa++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4293 103 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4294 104
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4295 105 tmpy = y1.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4296 106 for (x = B; x < b->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4297 107 *tmpy++ = *tmpb++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4298 108 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4299 109 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4300 110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4301 111 /* only need to clamp the lower words since by definition the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4302 112 * upper words x1/y1 must have a known number of digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4303 113 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4304 114 mp_clamp (&x0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4305 115 mp_clamp (&y0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4306 116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4307 117 /* now calc the products x0y0 and x1y1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4308 118 /* after this x0 is no longer required, free temp [x0==t2]! */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4309 119 if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4310 120 goto X1Y1; /* x0y0 = x0*y0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4311 121 if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4312 122 goto X1Y1; /* x1y1 = x1*y1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4313 123
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4314 124 /* now calc x1+x0 and y1+y0 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4315 125 if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4316 126 goto X1Y1; /* t1 = x1 - x0 */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4317 127 if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4318 128 goto X1Y1; /* t2 = y1 - y0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4319 129 if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4320 130 goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4321 131
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4322 132 /* add x0y0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4323 133 if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4324 134 goto X1Y1; /* t2 = x0y0 + x1y1 */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4325 135 if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4326 136 goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4327 137
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4328 138 /* shift by B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4329 139 if (mp_lshd (&t1, B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4330 140 goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4331 141 if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4332 142 goto X1Y1; /* x1y1 = x1y1 << 2*B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4333 143
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4334 144 if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4335 145 goto X1Y1; /* t1 = x0y0 + t1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4336 146 if (mp_add (&t1, &x1y1, c) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4337 147 goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4338 148
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4339 149 /* Algorithm succeeded set the return code to MP_OKAY */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4340 150 err = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4341 151
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4342 152 X1Y1:mp_clear (&x1y1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4343 153 X0Y0:mp_clear (&x0y0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4344 154 T1:mp_clear (&t1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4345 155 Y1:mp_clear (&y1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4346 156 Y0:mp_clear (&y0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4347 157 X1:mp_clear (&x1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4348 158 X0:mp_clear (&x0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4349 159 ERR:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4350 160 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4351 161 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4352 162 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4353 163
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4354 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4355 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4356
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4357 The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4358 wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4359 to handle error recovery with a single piece of code. Lines 61 to 75 handle initializing all of the temporary variables
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4360 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4361 the temporaries that have been successfully allocated so far.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4362
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4363 The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4364 additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4365 number of digits for the next section of code.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4366
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4367 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4368 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4369 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4370 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4371 $y1$ respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4372
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4373 By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4374
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4375 When line 150 is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4376 the same code that handles errors can be used to clear the temporary variables and return.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4377
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4378 \subsection{Toom-Cook $3$-Way Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4379 Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4380 chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4381 $16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4382 of the $W(x)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4383
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4384 With the five relations that Toom-Cook specifies, the following system of equations is formed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4385
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4386 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4387 \begin{tabular}{rcrcrcrcrcr}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4388 $\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4389 $16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4390 $\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4391 $\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4392 $\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4393 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4394 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4395
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4396 A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4397 of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4398 the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4399 (\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4400
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4401 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4402 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4403 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4404 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4405 \hline Algorithm \textbf{mp\_toom\_mul}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4406 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4407 \textbf{Output}. $c \leftarrow a \cdot b $ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4408 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4409 Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4410 1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4411 2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4412 3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4413 4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4414 5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4415 6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4416 7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4417 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4418 Find the five equations for $w_0, w_1, ..., w_4$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4419 8. $w_0 \leftarrow a_0 \cdot b_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4420 9. $w_4 \leftarrow a_2 \cdot b_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4421 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4422 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4423 12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4424 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4425 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4426 15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4427 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4428 17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4429 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4430 Continued on the next page.\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4431 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4432 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4433 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4434 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4435 \caption{Algorithm mp\_toom\_mul}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4436 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4437
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4438 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4439 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4440 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4441 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4442 \hline Algorithm \textbf{mp\_toom\_mul} (continued). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4443 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4444 \textbf{Output}. $c \leftarrow a \cdot b $ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4445 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4446 Now solve the system of equations. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4447 18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4448 19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4449 20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4450 21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4451 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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4452 23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4453 24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4454 25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4455 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4456 Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4457 26. for $n$ from $1$ to $4$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4458 \hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4459 27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4460 28. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4461 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4462 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4463 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4464 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4465 \caption{Algorithm mp\_toom\_mul (continued)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4466 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4467
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4468 \textbf{Algorithm mp\_toom\_mul.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4469 This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4470 algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4471 description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4472 any given step.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4473
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4474 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4475 integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4476
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4477 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4478 to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4479 $f(y)$ and $g(y)$ which significantly speeds up the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4480
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4481 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4482 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4483 the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4484 that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4485
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4486 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4487 result $a \cdot b$ is produced.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4488
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4489 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4490 \hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4491 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4492 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4493 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4494 017 /* multiplication using the Toom-Cook 3-way algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4495 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4496 019 * Much more complicated than Karatsuba but has a lower
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4497 020 * asymptotic running time of O(N**1.464). This algorithm is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4498 021 * only particularly useful on VERY large inputs
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4499 022 * (we're talking 1000s of digits here...).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4500 023 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4501 024 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4502 025 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4503 026 mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4504 027 int res, B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4505 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4506 029 /* init temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4507 030 if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4508 031 &a0, &a1, &a2, &b0, &b1,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4509 032 &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4510 033 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4511 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4512 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4513 036 /* B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4514 037 B = MIN(a->used, b->used) / 3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4515 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4516 039 /* a = a2 * B**2 + a1 * B + a0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4517 040 if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4518 041 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4519 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4520 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4521 044 if ((res = mp_copy(a, &a1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4522 045 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4523 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4524 047 mp_rshd(&a1, B);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4525 048 mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4526 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4527 050 if ((res = mp_copy(a, &a2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4528 051 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4529 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4530 053 mp_rshd(&a2, B*2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4531 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4532 055 /* b = b2 * B**2 + b1 * B + b0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4533 056 if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4534 057 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4535 058 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4536 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4537 060 if ((res = mp_copy(b, &b1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4538 061 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4539 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4540 063 mp_rshd(&b1, B);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4541 064 mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4542 065
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4543 066 if ((res = mp_copy(b, &b2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4544 067 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4545 068 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4546 069 mp_rshd(&b2, B*2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4547 070
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4548 071 /* w0 = a0*b0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4549 072 if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4550 073 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4551 074 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4552 075
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4553 076 /* w4 = a2 * b2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4554 077 if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4555 078 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4556 079 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4557 080
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4558 081 /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4559 082 if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4560 083 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4561 084 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4562 085 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4563 086 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4564 087 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4565 088 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4566 089 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4567 090 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4568 091 if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4569 092 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4570 093 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4571 094
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4572 095 if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4573 096 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4574 097 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4575 098 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4576 099 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4577 100 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4578 101 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4579 102 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4580 103 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4581 104 if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4582 105 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4583 106 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4584 107
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4585 108 if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4586 109 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4587 110 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4588 111
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4589 112 /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4590 113 if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4591 114 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4592 115 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4593 116 if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4594 117 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4595 118 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4596 119 if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4597 120 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4598 121 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4599 122 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4600 123 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4601 124 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4602 125
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4603 126 if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4604 127 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4605 128 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4606 129 if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4607 130 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4608 131 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4609 132 if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4610 133 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4611 134 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4612 135 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4613 136 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4614 137 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4615 138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4616 139 if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4617 140 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4618 141 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4619 142
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4620 143
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4621 144 /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4622 145 if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4623 146 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4624 147 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4625 148 if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4626 149 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4627 150 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4628 151 if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4629 152 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4630 153 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4631 154 if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4632 155 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4633 156 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4634 157 if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4635 158 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4636 159 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4637 160
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4638 161 /* now solve the matrix
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4639 162
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4640 163 0 0 0 0 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4641 164 1 2 4 8 16
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4642 165 1 1 1 1 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4643 166 16 8 4 2 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4644 167 1 0 0 0 0
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4645 168
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4646 169 using 12 subtractions, 4 shifts,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4647 170 2 small divisions and 1 small multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4648 171 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4649 172
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4650 173 /* r1 - r4 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4651 174 if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4652 175 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4653 176 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4654 177 /* r3 - r0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4655 178 if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4656 179 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4657 180 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4658 181 /* r1/2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4659 182 if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4660 183 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4661 184 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4662 185 /* r3/2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4663 186 if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4664 187 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4665 188 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4666 189 /* r2 - r0 - r4 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4667 190 if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4668 191 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4669 192 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4670 193 if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4671 194 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4672 195 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4673 196 /* r1 - r2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4674 197 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4675 198 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4676 199 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4677 200 /* r3 - r2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4678 201 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4679 202 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4680 203 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4681 204 /* r1 - 8r0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4682 205 if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4683 206 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4684 207 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4685 208 if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4686 209 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4687 210 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4688 211 /* r3 - 8r4 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4689 212 if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4690 213 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4691 214 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4692 215 if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4693 216 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4694 217 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4695 218 /* 3r2 - r1 - r3 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4696 219 if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4697 220 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4698 221 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4699 222 if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4700 223 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4701 224 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4702 225 if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4703 226 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4704 227 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4705 228 /* r1 - r2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4706 229 if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4707 230 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4708 231 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4709 232 /* r3 - r2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4710 233 if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4711 234 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4712 235 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4713 236 /* r1/3 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4714 237 if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4715 238 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4716 239 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4717 240 /* r3/3 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4718 241 if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4719 242 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4720 243 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4721 244
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4722 245 /* at this point shift W[n] by B*n */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4723 246 if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4724 247 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4725 248 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4726 249 if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4727 250 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4728 251 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4729 252 if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4730 253 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4731 254 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4732 255 if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4733 256 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4734 257 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4735 258
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4736 259 if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4737 260 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4738 261 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4739 262 if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4740 263 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4741 264 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4742 265 if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4743 266 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4744 267 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4745 268 if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4746 269 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4747 270 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4748 271
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4749 272 ERR:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4750 273 mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4751 274 &a0, &a1, &a2, &b0, &b1,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4752 275 &b2, &tmp1, &tmp2, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4753 276 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4754 277 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4755 278
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4756 279 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4757 280
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4758 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4759 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4760
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4761 The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4762 large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4763 Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4764 algorithm is not practical as Karatsuba has a much lower cutoff point.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4765
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4766 First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines 40 to 69) with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4767 combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4768 for $b$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4769
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4770 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4771 we get those out of the way first (lines 72 and 77). Next we compute $w1, w2$ and $w3$ using Horners method.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4772
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4773 After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4774 straight forward.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4775
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4776 \subsection{Signed Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4777 Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4778 of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4779
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4780 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4781 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4782 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4783 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4784 \hline Algorithm \textbf{mp\_mul}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4785 \textbf{Input}. mp\_int $a$ and mp\_int $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4786 \textbf{Output}. $c \leftarrow a \cdot b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4787 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4788 1. If $a.sign = b.sign$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4789 \hspace{3mm}1.1 $sign = MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4790 2. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4791 \hspace{3mm}2.1 $sign = MP\_ZNEG$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4792 3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4793 \hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4794 4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4795 \hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4796 5. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4797 \hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4798 \hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4799 \hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4800 \hspace{3mm}5.3 else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4801 \hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4802 6. $c.sign \leftarrow sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4803 7. Return the result of the unsigned multiplication performed. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4804 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4805 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4806 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4807 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4808 \caption{Algorithm mp\_mul}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4809 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4810
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4811 \textbf{Algorithm mp\_mul.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4812 This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4813 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4814 s\_mp\_mul\_digs will clear it.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4815
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4816 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4817 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4818 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4819 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4820 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4821 017 /* high level multiplication (handles sign) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4822 018 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4823 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4824 020 int res, neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4825 021 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4826 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4827 023 /* use Toom-Cook? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4828 024 #ifdef BN_MP_TOOM_MUL_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4829 025 if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4830 026 res = mp_toom_mul(a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4831 027 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4832 028 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4833 029 #ifdef BN_MP_KARATSUBA_MUL_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4834 030 /* use Karatsuba? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4835 031 if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4836 032 res = mp_karatsuba_mul (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4837 033 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4838 034 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4839 035 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4840 036 /* can we use the fast multiplier?
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4841 037 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4842 038 * The fast multiplier can be used if the output will
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4843 039 * have less than MP_WARRAY digits and the number of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4844 040 * digits won't affect carry propagation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4845 041 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4846 042 int digs = a->used + b->used + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4847 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4848 044 #ifdef BN_FAST_S_MP_MUL_DIGS_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4849 045 if ((digs < MP_WARRAY) &&
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4850 046 MIN(a->used, b->used) <=
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4851 047 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4852 048 res = fast_s_mp_mul_digs (a, b, c, digs);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4853 049 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4854 050 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4855 051 #ifdef BN_S_MP_MUL_DIGS_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4856 052 res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4857 053 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4858 054 res = MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4859 055 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4860 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4861 057 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4862 058 c->sign = (c->used > 0) ? neg : MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4863 059 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4864 060 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4865 061 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
4866 062
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4867 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4868 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4869
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4870 The implementation is rather simplistic and is not particularly noteworthy. Line 23 computes the sign of the result using the ``?''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4871 operator from the C programming language. Line 47 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4872
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4873 \section{Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4874 \label{sec:basesquare}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4875
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4876 Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4877 available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4878 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4879 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$,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4880 $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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4881 and $3 \cdot 1 = 1 \cdot 3$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4882
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4883 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4884 required for multiplication. The following diagram gives an example of the operations required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4885
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4886 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4887 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4888 \begin{tabular}{ccccc|c}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4889 &&1&2&3&\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4890 $\times$ &&1&2&3&\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4891 \hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4892 & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4893 $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4894 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4895 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4896 \caption{Squaring Optimization Diagram}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4897 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4898
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4899 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4900 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4901
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4902 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4903 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4904 products and at most one square (\textit{see the exercise section}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4905
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4906 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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4907 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4908 Column two of row one is a square and column three is the first unique column.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4909
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4910 \subsection{The Baseline Squaring Algorithm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4911 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4912 will not handle.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4913
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4914 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4915 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4916 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4917 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4918 \hline Algorithm \textbf{s\_mp\_sqr}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4919 \textbf{Input}. mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4920 \textbf{Output}. $b \leftarrow a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4921 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4922 1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4923 2. If step 1 failed return(\textit{MP\_MEM}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4924 3. $t.used \leftarrow 2 \cdot a.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4925 4. For $ix$ from 0 to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4926 \hspace{3mm}Calculate the square. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4927 \hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4928 \hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4929 \hspace{3mm}Calculate the double products after the square. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4930 \hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4931 \hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4932 \hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4933 \hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4934 \hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4935 \hspace{3mm}Set the last carry. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4936 \hspace{3mm}4.5 While $u > 0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4937 \hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4938 \hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4939 \hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4940 \hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4941 5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4942 6. Exchange $b$ and $t$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4943 7. Clear $t$ (\textit{mp\_clear}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4944 8. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4945 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4946 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4947 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4948 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4949 \caption{Algorithm s\_mp\_sqr}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4950 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4951
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4952 \textbf{Algorithm s\_mp\_sqr.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4953 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4954 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4955 destination mp\_int to be the same as the source mp\_int.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4956
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4957 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4958 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4959 the carry and compute the double products.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4960
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4961 The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4962 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4963 when it is multiplied by two, it can be properly represented by a mp\_word.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4964
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4965 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4966 results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4967
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4968 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4969 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4970 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4971 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4972 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4973 017 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4974 018 int s_mp_sqr (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4975 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4976 020 mp_int t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4977 021 int res, ix, iy, pa;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4978 022 mp_word r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4979 023 mp_digit u, tmpx, *tmpt;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4980 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4981 025 pa = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4982 026 if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4983 027 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4984 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4985 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4986 030 /* default used is maximum possible size */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4987 031 t.used = 2*pa + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4988 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4989 033 for (ix = 0; ix < pa; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4990 034 /* first calculate the digit at 2*ix */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4991 035 /* calculate double precision result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4992 036 r = ((mp_word) t.dp[2*ix]) +
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4993 037 ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4994 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4995 039 /* store lower part in result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4996 040 t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4997 041
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4998 042 /* get the carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
4999 043 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5000 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5001 045 /* left hand side of A[ix] * A[iy] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5002 046 tmpx = a->dp[ix];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5003 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5004 048 /* alias for where to store the results */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5005 049 tmpt = t.dp + (2*ix + 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5006 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5007 051 for (iy = ix + 1; iy < pa; iy++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5008 052 /* first calculate the product */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5009 053 r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5010 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5011 055 /* now calculate the double precision result, note we use
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5012 056 * addition instead of *2 since it's easier to optimize
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5013 057 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5014 058 r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5015 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5016 060 /* store lower part */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5017 061 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5018 062
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5019 063 /* get carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5020 064 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5021 065 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5022 066 /* propagate upwards */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5023 067 while (u != ((mp_digit) 0)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5024 068 r = ((mp_word) *tmpt) + ((mp_word) u);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5025 069 *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5026 070 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5027 071 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5028 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5029 073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5030 074 mp_clamp (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5031 075 mp_exch (&t, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5032 076 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5033 077 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5034 078 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5035 079 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5036 080
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5037 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5038 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5040 Inside the outer loop (line 33) the square term is calculated on line 36. The carry (line 43) has been
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5041 extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5042 (lines 46 and 49) to simplify the inner loop. The doubling is performed using two
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5043 additions (line 58) since it is usually faster than shifting, if not at least as fast.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5045 The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5046 get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5047 square a number.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5049 \subsection{Faster Squaring by the ``Comba'' Method}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5050 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5051 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5052 performance hazards.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5054 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5055 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5056 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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5057 $ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5059 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5060 mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5061 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5062
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5063 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5064 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5065 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5066 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5067 \hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5068 \textbf{Input}. mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5069 \textbf{Output}. $b \leftarrow a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5070 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5071 Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5072 1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5073 2. If step 1 failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5074 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5075 3. $pa \leftarrow 2 \cdot a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5076 4. $\hat W1 \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5077 5. for $ix$ from $0$ to $pa - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5078 \hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5079 \hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5080 \hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5081 \hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5082 \hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5083 \hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5084 \hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5085 \hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5086 \hspace{3mm}5.8 if $ix$ is even then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5087 \hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5088 \hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5089 \hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5090 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5091 6. $oldused \leftarrow b.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5092 7. $b.used \leftarrow 2 \cdot a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5093 8. for $ix$ from $0$ to $pa - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5094 \hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5095 9. for $ix$ from $pa$ to $oldused - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5096 \hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5097 10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5098 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5099 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5100 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5101 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5102 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5103 \caption{Algorithm fast\_s\_mp\_sqr}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5104 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5105
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5106 \textbf{Algorithm fast\_s\_mp\_sqr.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5107 This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5108 s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5109 This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5111 First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5112 products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5113 addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5114 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5115 of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5116 fewer multiplications and the routine ends up being faster.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5117
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5118 Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5119 only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5120
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5121 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5122 \hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5123 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5124 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5125 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5126 017 /* the jist of squaring...
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5127 018 * you do like mult except the offset of the tmpx [one that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5128 019 * starts closer to zero] can't equal the offset of tmpy.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5129 020 * So basically you set up iy like before then you min it with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5130 021 * (ty-tx) so that it never happens. You double all those
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5131 022 * you add in the inner loop
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5132 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5133 024 After that loop you do the squares and add them in.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5134 025 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5135 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5136 027 int fast_s_mp_sqr (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5137 028 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5138 029 int olduse, res, pa, ix, iz;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5139 030 mp_digit W[MP_WARRAY], *tmpx;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5140 031 mp_word W1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5141 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5142 033 /* grow the destination as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5143 034 pa = a->used + a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5144 035 if (b->alloc < pa) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5145 036 if ((res = mp_grow (b, pa)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5146 037 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5147 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5148 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5149 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5150 041 /* number of output digits to produce */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5151 042 W1 = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5152 043 for (ix = 0; ix < pa; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5153 044 int tx, ty, iy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5154 045 mp_word _W;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5155 046 mp_digit *tmpy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5156 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5157 048 /* clear counter */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5158 049 _W = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5159 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5160 051 /* get offsets into the two bignums */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5161 052 ty = MIN(a->used-1, ix);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5162 053 tx = ix - ty;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5163 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5164 055 /* setup temp aliases */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5165 056 tmpx = a->dp + tx;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5166 057 tmpy = a->dp + ty;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5167 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5168 059 /* this is the number of times the loop will iterrate, essentially
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5169 060 while (tx++ < a->used && ty-- >= 0) \{ ... \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5170 061 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5171 062 iy = MIN(a->used-tx, ty+1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5172 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5173 064 /* now for squaring tx can never equal ty
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5174 065 * we halve the distance since they approach at a rate of 2x
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5175 066 * and we have to round because odd cases need to be executed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5176 067 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5177 068 iy = MIN(iy, (ty-tx+1)>>1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5178 069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5179 070 /* execute loop */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5180 071 for (iz = 0; iz < iy; iz++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5181 072 _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5182 073 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5183 074
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5184 075 /* double the inner product and add carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5185 076 _W = _W + _W + W1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5186 077
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5187 078 /* even columns have the square term in them */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5188 079 if ((ix&1) == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5189 080 _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5190 081 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5191 082
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5192 083 /* store it */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5193 084 W[ix] = (mp_digit)(_W & MP_MASK);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5194 085
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5195 086 /* make next carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5196 087 W1 = _W >> ((mp_word)DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5197 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5198 089
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5199 090 /* setup dest */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5200 091 olduse = b->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5201 092 b->used = a->used+a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5202 093
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5203 094 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5204 095 mp_digit *tmpb;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5205 096 tmpb = b->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5206 097 for (ix = 0; ix < pa; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5207 098 *tmpb++ = W[ix] & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5208 099 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5209 100
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5210 101 /* clear unused digits [that existed in the old copy of c] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5211 102 for (; ix < olduse; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5212 103 *tmpb++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5213 104 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5214 105 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5215 106 mp_clamp (b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5216 107 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5217 108 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5218 109 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5219 110
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5220 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5221 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5222
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5223 This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5224 the special case of squaring.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5225
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5226 \subsection{Polynomial Basis Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5227 The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5228 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5229 multiplications to find the $\zeta$ relations, squaring operations are performed instead.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5230
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5231 \subsection{Karatsuba Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5232 Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5233 Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5234 number with the following equation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5235
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5236 \begin{equation}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5237 h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5238 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5239
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5240 Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5241 Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5242 $O \left ( n^{lg(3)} \right )$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5243
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5244 If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5245 instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5246 time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5247 point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5248
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5249 Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5250 The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5251 were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5252
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5253 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5254 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5255 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5256 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5257 \hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5258 \textbf{Input}. mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5259 \textbf{Output}. $b \leftarrow a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5260 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5261 1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5262 2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5263 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5264 Split the input. e.g. $a = x1\beta^B + x0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5265 3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5266 4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5267 5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5268 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5269 Calculate the three squares. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5270 6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5271 7. $x1x1 \leftarrow x1^2$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5272 8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5273 9. $t1 \leftarrow t1^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5274 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5275 Compute the middle term. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5276 10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5277 11. $t1 \leftarrow t1 - t2$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5278 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5279 Compute final product. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5280 12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5281 13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5282 14. $t1 \leftarrow t1 + x0x0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5283 15. $b \leftarrow t1 + x1x1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5284 16. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5285 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5286 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5287 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5288 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5289 \caption{Algorithm mp\_karatsuba\_sqr}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5290 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5291
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5292 \textbf{Algorithm mp\_karatsuba\_sqr.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5293 This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5294 multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5295
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5296 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5297 placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5298 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5299
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5300 By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5301 Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5302 this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5303
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5304 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5305 machine clock cycles.}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5306
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5307 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5308 5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5309 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5310
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5311 For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5312 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5313 \begin{tabular}{rcl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5314 ${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5315 ${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5316 ${13 \over 9}$ & $<$ & $n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5317 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5318 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5319
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5320 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5321 where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5322 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5323 ratio of 1:7. } than simpler operations such as addition.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5324
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5325 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5326 \hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5327 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5328 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5329 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5330 017 /* Karatsuba squaring, computes b = a*a using three
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5331 018 * half size squarings
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5332 019 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5333 020 * See comments of karatsuba_mul for details. It
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5334 021 * is essentially the same algorithm but merely
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5335 022 * tuned to perform recursive squarings.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5336 023 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5337 024 int mp_karatsuba_sqr (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5338 025 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5339 026 mp_int x0, x1, t1, t2, x0x0, x1x1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5340 027 int B, err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5341 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5342 029 err = MP_MEM;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5343 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5344 031 /* min # of digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5345 032 B = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5346 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5347 034 /* now divide in two */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5348 035 B = B >> 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5349 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5350 037 /* init copy all the temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5351 038 if (mp_init_size (&x0, B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5352 039 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5353 040 if (mp_init_size (&x1, a->used - B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5354 041 goto X0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5355 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5356 043 /* init temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5357 044 if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5358 045 goto X1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5359 046 if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5360 047 goto T1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5361 048 if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5362 049 goto T2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5363 050 if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5364 051 goto X0X0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5365 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5366 053 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5367 054 register int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5368 055 register mp_digit *dst, *src;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5369 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5370 057 src = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5371 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5372 059 /* now shift the digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5373 060 dst = x0.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5374 061 for (x = 0; x < B; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5375 062 *dst++ = *src++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5376 063 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5377 064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5378 065 dst = x1.dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5379 066 for (x = B; x < a->used; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5380 067 *dst++ = *src++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5381 068 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5382 069 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5383 070
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5384 071 x0.used = B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5385 072 x1.used = a->used - B;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5386 073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5387 074 mp_clamp (&x0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5388 075
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5389 076 /* now calc the products x0*x0 and x1*x1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5390 077 if (mp_sqr (&x0, &x0x0) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5391 078 goto X1X1; /* x0x0 = x0*x0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5392 079 if (mp_sqr (&x1, &x1x1) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5393 080 goto X1X1; /* x1x1 = x1*x1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5394 081
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5395 082 /* now calc (x1+x0)**2 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5396 083 if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5397 084 goto X1X1; /* t1 = x1 - x0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5398 085 if (mp_sqr (&t1, &t1) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5399 086 goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5400 087
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5401 088 /* add x0y0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5402 089 if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5403 090 goto X1X1; /* t2 = x0x0 + x1x1 */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5404 091 if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5405 092 goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5406 093
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5407 094 /* shift by B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5408 095 if (mp_lshd (&t1, B) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5409 096 goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5410 097 if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5411 098 goto X1X1; /* x1x1 = x1x1 << 2*B */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5412 099
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5413 100 if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5414 101 goto X1X1; /* t1 = x0x0 + t1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5415 102 if (mp_add (&t1, &x1x1, b) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5416 103 goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5417 104
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5418 105 err = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5419 106
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5420 107 X1X1:mp_clear (&x1x1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5421 108 X0X0:mp_clear (&x0x0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5422 109 T2:mp_clear (&t2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5423 110 T1:mp_clear (&t1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5424 111 X1:mp_clear (&x1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5425 112 X0:mp_clear (&x0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5426 113 ERR:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5427 114 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5428 115 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5429 116 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5430 117
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5431 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5432 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5433
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5434 This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5435 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5436 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5437 to the respective halves as if mp\_rshd and mp\_mod\_2d had been used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5438
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5439 By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5440 is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5441 it is actually below the Comba limit (\textit{at 110 digits}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5442
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5443 This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5444 redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5445 mp\_clears are executed normally.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5446
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5447 \subsection{Toom-Cook Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5448 The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5449 instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5450 derive their own Toom-Cook squaring algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5451
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5452 \subsection{High Level Squaring}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5453 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5454 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5455 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5456 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5457 \hline Algorithm \textbf{mp\_sqr}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5458 \textbf{Input}. mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5459 \textbf{Output}. $b \leftarrow a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5460 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5461 1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5462 \hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5463 2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5464 \hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5465 3. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5466 \hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5467 \hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5468 \hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5469 \hspace{3mm}3.3 else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5470 \hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5471 4. $b.sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5472 5. Return the result of the unsigned squaring performed. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5473 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5474 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5475 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5476 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5477 \caption{Algorithm mp\_sqr}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5478 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5479
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5480 \textbf{Algorithm mp\_sqr.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5481 This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5482 \textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5483 neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5484
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5485 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5486 \hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5487 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5488 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5489 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5490 017 /* computes b = a*a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5491 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5492 019 mp_sqr (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5493 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5494 021 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5495 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5496 023 #ifdef BN_MP_TOOM_SQR_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5497 024 /* use Toom-Cook? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5498 025 if (a->used >= TOOM_SQR_CUTOFF) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5499 026 res = mp_toom_sqr(a, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5500 027 /* Karatsuba? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5501 028 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5502 029 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5503 030 #ifdef BN_MP_KARATSUBA_SQR_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5504 031 if (a->used >= KARATSUBA_SQR_CUTOFF) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5505 032 res = mp_karatsuba_sqr (a, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5506 033 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5507 034 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5508 035 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5509 036 #ifdef BN_FAST_S_MP_SQR_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5510 037 /* can we use the fast comba multiplier? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5511 038 if ((a->used * 2 + 1) < MP_WARRAY &&
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5512 039 a->used <
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5513 040 (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5514 041 res = fast_s_mp_sqr (a, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5515 042 \} else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5516 043 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5517 044 #ifdef BN_S_MP_SQR_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5518 045 res = s_mp_sqr (a, b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5519 046 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5520 047 res = MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5521 048 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5522 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5523 050 b->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5524 051 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5525 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5526 053 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5527 054
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5528 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5529 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5530
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5531 \section*{Exercises}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5532 \begin{tabular}{cl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5533 $\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5534 & that have different number of digits in Karatsuba multiplication. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5535 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5536 $\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5537 & of double products and at most one square is stated. Prove this statement. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5538 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5539 $\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5540 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5541 $\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5542 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5543 $\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5544 & required for equation $6.7$ to be true. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5545 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5546 $\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5547 & compute subsets of the columns in each thread. Determine a cutoff point where \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5548 & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5549 &\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5550 $\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5551 & increase the throughput of mp\_exptmod() for random odd moduli in the range \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5552 & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5553 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5554 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5555
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5556 \chapter{Modular Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5557 \section{Basics of Modular Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5558 \index{modular residue}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5559 Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5560 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5561 modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5562 in~\ref{sec:division}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5563
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5564 Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5565 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5566 ``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5567 other forms of residues.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5568
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5569 Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5570 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5571 RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5572 elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5573 exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5574 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5575 algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5576
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5577 \section{The Barrett Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5578 The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5579 division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5580
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5581 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5582 c = a - b \cdot \lfloor a/b \rfloor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5583 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5584
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5585 Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5586 targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5587 DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5588 It would take another common optimization to optimize the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5589
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5590 \subsection{Fixed Point Arithmetic}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5591 The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5592 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5593 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5594 integer and a $q$-bit fraction part (\textit{where $p+q = k$}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5595
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5596 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5597 value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5598 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5599 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5600 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)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5601
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5602 This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5603 of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5604 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5605 $a$ by another integer $b$ can be achieved with the following expression.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5606
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5607 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5608 \lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5609 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5610
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5611 The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5612 modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5613 are considerably faster than division on most processors.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5614
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5615 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5616 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5617 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5618 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5619 to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5620
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5621 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5622 c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5623 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5624
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5625 Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5626 variable also helps re-inforce the idea that it is meant to be computed once and re-used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5627
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5628 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5629 c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5630 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5631
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5632 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5633 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5634 precision.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5635
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5636 Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5637 another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5638 reduce the number.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5639
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5640 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5641 $a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5642 By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5643
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5644 \subsection{Choosing a Radix Point}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5645 Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5646 that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5647 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5648 the initial multiplication that finds the quotient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5649
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5650 Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5651 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5652 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5653 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5654 express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5655 ${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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5656 is bound by $0 \le {a' \over b} < 1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5657
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5658 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5659 ``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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5660 with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5661
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5662 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5663 c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5664 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5665
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5666 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5667 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5668 would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5669 $\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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5670 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5671 can be off by an additional value of one for a total of at most two. This implies that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5672 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5673 $b$ once or twice the residue is found.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5674
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5675 The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5676 precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5677 This is considerably faster than the original attempt.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5678
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5679 For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5680 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5681 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5682 $\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{)}$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5683 is found.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5684
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5685 \subsection{Trimming the Quotient}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5686 So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5687 it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5688 optimization.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5689
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5690 After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5691 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5692 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5693 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5694
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5695 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5696 multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5697 of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5698
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5699 \subsection{Trimming the Residue}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5700 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5701 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5702 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5703 implicitly zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5704
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5705 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5706 $O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5707 be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5708 only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5709
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5710 With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5711 is considerably faster than the straightforward $3m^2$ method.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5712
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5713 \subsection{The Barrett Algorithm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5714 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5715 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5716 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5717 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5718 \hline Algorithm \textbf{mp\_reduce}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5719 \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)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5720 \textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5721 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5722 Let $m$ represent the number of digits in $b$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5723 1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5724 2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5725 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5726 Produce the quotient. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5727 3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5728 4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5729 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5730 Subtract the multiple of modulus from the input. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5731 5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5732 6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5733 7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5734 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5735 Add $\beta^{m+1}$ if a carry occured. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5736 8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5737 \hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5738 \hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5739 \hspace{3mm}8.3 $a \leftarrow a + q$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5740 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5741 Now subtract the modulus if the residue is too large (e.g. quotient too small). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5742 9. While $a \ge b$ do (\textit{mp\_cmp}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5743 \hspace{3mm}9.1 $c \leftarrow a - b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5744 10. Clear $q$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5745 11. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5746 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5747 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5748 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5749 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5750 \caption{Algorithm mp\_reduce}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5751 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5752
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5753 \textbf{Algorithm mp\_reduce.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5754 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5755 \cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5756 be adhered to for the algorithm to work.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5757
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5758 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5759 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5760 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5761 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5762 algorithm and is assumed to be calculated and stored before the algorithm is used.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5763
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5764 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5765 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5766 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5767 of digits in $b$ is very much smaller than $\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5768
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5769 While it is known that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5770 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5771 ``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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5772 fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5773
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5774 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5775 performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5776
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5777 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5778 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5779 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5780 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5781 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5782 017 /* reduces x mod m, assumes 0 < x < m**2, mu is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5783 018 * precomputed via mp_reduce_setup.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5784 019 * From HAC pp.604 Algorithm 14.42
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5785 020 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5786 021 int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5787 022 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5788 023 mp_int q;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5789 024 int res, um = m->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5790 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5791 026 /* q = x */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5792 027 if ((res = mp_init_copy (&q, x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5793 028 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5794 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5795 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5796 031 /* q1 = x / b**(k-1) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5797 032 mp_rshd (&q, um - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5798 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5799 034 /* according to HAC this optimization is ok */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5800 035 if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5801 036 if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5802 037 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5803 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5804 039 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5805 040 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5806 041 if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5807 042 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5808 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5809 044 #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5810 045 if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5811 046 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5812 047 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5813 048 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5814 049 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5815 050 res = MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5816 051 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5817 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5818 053 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5819 054 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5820 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5821 056 /* q3 = q2 / b**(k+1) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5822 057 mp_rshd (&q, um + 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5823 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5824 059 /* x = x mod b**(k+1), quick (no division) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5825 060 if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5826 061 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5827 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5828 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5829 064 /* q = q * m mod b**(k+1), quick (no division) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5830 065 if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5831 066 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5832 067 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5833 068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5834 069 /* x = x - q */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5835 070 if ((res = mp_sub (x, &q, x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5836 071 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5837 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5838 073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5839 074 /* If x < 0, add b**(k+1) to it */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5840 075 if (mp_cmp_d (x, 0) == MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5841 076 mp_set (&q, 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5842 077 if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5843 078 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5844 079 if ((res = mp_add (x, &q, x)) != MP_OKAY)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5845 080 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5846 081 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5847 082
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5848 083 /* Back off if it's too big */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5849 084 while (mp_cmp (x, m) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5850 085 if ((res = s_mp_sub (x, m, x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5851 086 goto CLEANUP;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5852 087 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5853 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5854 089
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5855 090 CLEANUP:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5856 091 mp_clear (&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5857 092
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5858 093 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5859 094 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5860 095 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5861 096
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5862 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5863 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5864
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5865 The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5866 the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5867 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5868 safe to do so.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5869
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5870 \subsection{The Barrett Setup Algorithm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5871 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5872 future use so that the Barrett algorithm can be used without delay.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5873
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5874 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5875 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5876 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5877 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5878 \hline Algorithm \textbf{mp\_reduce\_setup}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5879 \textbf{Input}. mp\_int $a$ ($a > 1$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5880 \textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5881 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5882 1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5883 2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5884 3. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5885 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5886 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5887 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5888 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5889 \caption{Algorithm mp\_reduce\_setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5890 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5891
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5892 \textbf{Algorithm mp\_reduce\_setup.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5893 This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5894 is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5895
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5896 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5897 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5898 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5899 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5900 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5901 017 /* pre-calculate the value required for Barrett reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5902 018 * For a given modulus "b" it calulates the value required in "a"
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5903 019 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5904 020 int mp_reduce_setup (mp_int * a, mp_int * b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5905 021 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5906 022 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5907 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5908 024 if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5909 025 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5910 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5911 027 return mp_div (a, b, a, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5912 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5913 029 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5914 030
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5915 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5916 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5917
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5918 This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5919 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5920 remainder to be passed as NULL meaning to ignore the value.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5921
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5922 \section{The Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5923 Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5924 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5925 residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5926
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5927 Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5928 $n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5929 is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5930
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5931 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5932 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5933
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5934 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5935 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5936 multiplication by $k^{-1}$ modulo $n$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5937
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5938 From these two simple facts the following simple algorithm can be derived.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5939
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5940 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5941 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5942 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5943 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5944 \hline Algorithm \textbf{Montgomery Reduction}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5945 \textbf{Input}. Integer $x$, $n$ and $k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5946 \textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5947 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5948 1. for $t$ from $1$ to $k$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5949 \hspace{3mm}1.1 If $x$ is odd then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5950 \hspace{6mm}1.1.1 $x \leftarrow x + n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5951 \hspace{3mm}1.2 $x \leftarrow x/2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5952 2. Return $x$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5953 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5954 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5955 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5956 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5957 \caption{Algorithm Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5958 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5959
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5960 The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5961 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5962 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5963 final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5964 $0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5965
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5966 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5967 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5968 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5969 \begin{tabular}{|c|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5970 \hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5971 \hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5972 \hline $2$ & $x/2 = 1453$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5973 \hline $3$ & $x + n = 1710$, $x/2 = 855$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5974 \hline $4$ & $x + n = 1112$, $x/2 = 556$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5975 \hline $5$ & $x/2 = 278$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5976 \hline $6$ & $x/2 = 139$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5977 \hline $7$ & $x + n = 396$, $x/2 = 198$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5978 \hline $8$ & $x/2 = 99$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5979 \hline $9$ & $x + n = 356$, $x/2 = 178$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5980 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5981 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5982 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5983 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5984 \caption{Example of Montgomery Reduction (I)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5985 \label{fig:MONT1}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5986 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5987
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5988 Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
5989 the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5990 $r \equiv 158$ is produced.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5991
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5992 Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5993 and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5994 Fortunately there exists an alternative representation of the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5995
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5996 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5997 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5998 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
5999 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6000 \hline Algorithm \textbf{Montgomery Reduction} (modified I). \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6001 \textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6002 \textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6003 \hline \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6004 1. for $t$ from $1$ to $k$ do \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6005 \hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6006 \hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6007 2. Return $x/2^k$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6008 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6009 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6010 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6011 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6012 \caption{Algorithm Montgomery Reduction (modified I)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6013 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6014
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6015 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6016 precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6017
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6018 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6019 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6020 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6021 \begin{tabular}{|c|l|r|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6022 \hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6023 \hline -- & $5555$ & $1010110110011$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6024 \hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6025 \hline $2$ & $5812$ & $1011010110100$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6026 \hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6027 \hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6028 \hline $5$ & $8896$ & $10001011000000$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6029 \hline $6$ & $8896$ & $10001011000000$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6030 \hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6031 \hline $8$ & $25344$ & $110001100000000$ \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6032 \hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6033 \hline -- & $x/2^k = 178$ & \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6034 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6035 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6036 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6037 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6038 \caption{Example of Montgomery Reduction (II)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6039 \label{fig:MONT2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6040 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6041
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6042 Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6043 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6044 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6045 zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6047 \subsection{Digit Based Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6048 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6049 previous algorithm re-written to compute the Montgomery reduction in this new fashion.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6051 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6052 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6053 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6054 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6055 \hline Algorithm \textbf{Montgomery Reduction} (modified II). \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6056 \textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6057 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6058 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6059 1. for $t$ from $0$ to $k - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6060 \hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6061 2. Return $x/\beta^k$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6062 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6063 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6064 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6065 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6066 \caption{Algorithm Montgomery Reduction (modified II)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6067 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6069 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6070 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6071 problem breaks down to solving the following congruency.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6072
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6073 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6074 \begin{tabular}{rcl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6075 $x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6076 $\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6077 $\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6078 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6079 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6080
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6081 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6082 extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6083
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6084 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6085 represent the value to reduce.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6086
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6087 \newpage\begin{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6088 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6089 \begin{tabular}{|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6090 \hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6091 \hline -- & $33$ & --\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6092 \hline $0$ & $33 + \mu n = 50$ & $1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6093 \hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6094 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6095 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6096 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6097 \caption{Example of Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6098 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6099
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6100 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{)}$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6101 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6102 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6103 the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6104
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6105 \subsection{Baseline Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6106 The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6107 Montgomery reductions.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6108
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6109 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6110 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6111 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6112 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6113 \hline Algorithm \textbf{mp\_montgomery\_reduce}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6114 \textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6115 \hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6116 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6117 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6118 1. $digs \leftarrow 2n.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6119 2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6120 \hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6121 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6122 Setup $x$ for the reduction. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6123 3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6124 4. $x.used \leftarrow digs$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6125 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6126 Eliminate the lower $k$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6127 5. For $ix$ from $0$ to $k - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6128 \hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6129 \hspace{3mm}5.2 $u \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6130 \hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6131 \hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6132 \hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6133 \hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6134 \hspace{3mm}5.4 While $u > 0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6135 \hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6136 \hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6137 \hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6138 \hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6139 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6140 Divide by $\beta^k$ and fix up as required. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6141 6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6142 7. If $x \ge n$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6143 \hspace{3mm}7.1 $x \leftarrow x - n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6144 8. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6145 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6146 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6147 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6148 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6149 \caption{Algorithm mp\_montgomery\_reduce}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6150 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6151
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6152 \textbf{Algorithm mp\_montgomery\_reduce.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6153 This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6154 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6155 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6156 for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6157 advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6158
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6159 Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6160 the size of the input. This algorithm is discussed in sub-section 6.3.3.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6161
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6162 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6163 calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6164 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6165
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6166 Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6167 in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6168 multiplications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6169
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6170 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6171 \hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6172 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6173 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6174 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6175 017 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6176 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6177 019 mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6178 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6179 021 int ix, res, digs;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6180 022 mp_digit mu;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6181 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6182 024 /* can the fast reduction [comba] method be used?
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6183 025 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6184 026 * Note that unlike in mul you're safely allowed *less*
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6185 027 * than the available columns [255 per default] since carries
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6186 028 * are fixed up in the inner loop.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6187 029 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6188 030 digs = n->used * 2 + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6189 031 if ((digs < MP_WARRAY) &&
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6190 032 n->used <
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6191 033 (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6192 034 return fast_mp_montgomery_reduce (x, n, rho);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6193 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6194 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6195 037 /* grow the input as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6196 038 if (x->alloc < digs) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6197 039 if ((res = mp_grow (x, digs)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6198 040 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6199 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6200 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6201 043 x->used = digs;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6202 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6203 045 for (ix = 0; ix < n->used; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6204 046 /* mu = ai * rho mod b
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6205 047 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6206 048 * The value of rho must be precalculated via
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6207 049 * montgomery_setup() such that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6208 050 * it equals -1/n0 mod b this allows the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6209 051 * following inner loop to reduce the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6210 052 * input one digit at a time
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6211 053 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6212 054 mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6213 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6214 056 /* a = a + mu * m * b**i */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6215 057 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6216 058 register int iy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6217 059 register mp_digit *tmpn, *tmpx, u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6218 060 register mp_word r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6219 061
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6220 062 /* alias for digits of the modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6221 063 tmpn = n->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6222 064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6223 065 /* alias for the digits of x [the input] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6224 066 tmpx = x->dp + ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6225 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6226 068 /* set the carry to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6227 069 u = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6228 070
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6229 071 /* Multiply and add in place */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6230 072 for (iy = 0; iy < n->used; iy++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6231 073 /* compute product and sum */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6232 074 r = ((mp_word)mu) * ((mp_word)*tmpn++) +
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6233 075 ((mp_word) u) + ((mp_word) * tmpx);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6234 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6235 077 /* get carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6236 078 u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6237 079
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6238 080 /* fix digit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6239 081 *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6240 082 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6241 083 /* At this point the ix'th digit of x should be zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6242 084
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6243 085
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6244 086 /* propagate carries upwards as required*/
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6245 087 while (u) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6246 088 *tmpx += u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6247 089 u = *tmpx >> DIGIT_BIT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6248 090 *tmpx++ &= MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6249 091 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6250 092 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6251 093 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6252 094
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6253 095 /* at this point the n.used'th least
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6254 096 * significant digits of x are all zero
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6255 097 * which means we can shift x to the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6256 098 * right by n.used digits and the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6257 099 * residue is unchanged.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6258 100 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6259 101
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6260 102 /* x = x/b**n.used */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6261 103 mp_clamp(x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6262 104 mp_rshd (x, n->used);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6263 105
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6264 106 /* if x >= n then x = x - n */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6265 107 if (mp_cmp_mag (x, n) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6266 108 return s_mp_sub (x, n, x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6267 109 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6268 110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6269 111 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6270 112 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6271 113 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6272 114
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6273 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6274 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6275
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6276 This is the baseline implementation of the Montgomery reduction algorithm. Lines 30 to 35 determine if the Comba based
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6277 routine can be used instead. Line 48 computes the value of $\mu$ for that particular iteration of the outer loop.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6278
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6279 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6280 the alias $tmpn$ refers to the modulus $n$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6281
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6282 \subsection{Faster ``Comba'' Montgomery Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6283
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6284 The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6285 nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6286 technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6287 a $k \times 1$ product $k$ times.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6288
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6289 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6290 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6291 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6292
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6293 With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6294 the speed of the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6295
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6296 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6297 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6298 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6299 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6300 \hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6301 \textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6302 \hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6303 \textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6304 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6305 Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6306 1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6307 Copy the digits of $x$ into the array $\hat W$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6308 2. For $ix$ from $0$ to $x.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6309 \hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6310 3. For $ix$ from $x.used$ to $2n.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6311 \hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6312 Elimiate the lower $k$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6313 4. for $ix$ from $0$ to $n.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6314 \hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6315 \hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6316 \hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6317 \hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6318 Propagate carries upwards. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6319 5. for $ix$ from $n.used$ to $2n.used + 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6320 \hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6321 Shift right and reduce modulo $\beta$ simultaneously. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6322 6. for $ix$ from $0$ to $n.used + 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6323 \hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6324 Zero excess digits and fixup $x$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6325 7. if $x.used > n.used + 1$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6326 \hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6327 \hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6328 8. $x.used \leftarrow n.used + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6329 9. Clamp excessive digits of $x$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6330 10. If $x \ge n$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6331 \hspace{3mm}10.1 $x \leftarrow x - n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6332 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6333 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6334 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6335 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6336 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6337 \caption{Algorithm fast\_mp\_montgomery\_reduce}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6338 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6339
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6340 \textbf{Algorithm fast\_mp\_montgomery\_reduce.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6341 This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6342 faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6343 on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6344 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6345 a modulus of at most $3,556$ bits in length.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6346
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6347 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6348 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6349 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6350 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6351 a single precision multiplication instead half the amount of time is spent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6352
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6353 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6354 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6355 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6356 point.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6357
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6358 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6359 stored in the destination $x$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6360
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6361 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6362 \hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6363 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6364 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6365 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6366 017 /* computes xR**-1 == x (mod N) via Montgomery Reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6367 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6368 019 * This is an optimized implementation of montgomery_reduce
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6369 020 * which uses the comba method to quickly calculate the columns of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6370 021 * reduction.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6371 022 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6372 023 * Based on Algorithm 14.32 on pp.601 of HAC.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6373 024 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6374 025 int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6375 026 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6376 027 int ix, res, olduse;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6377 028 mp_word W[MP_WARRAY];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6378 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6379 030 /* get old used count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6380 031 olduse = x->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6381 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6382 033 /* grow a as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6383 034 if (x->alloc < n->used + 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6384 035 if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6385 036 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6386 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6387 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6388 039
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6389 040 /* first we have to get the digits of the input into
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6390 041 * an array of double precision words W[...]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6391 042 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6392 043 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6393 044 register mp_word *_W;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6394 045 register mp_digit *tmpx;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6395 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6396 047 /* alias for the W[] array */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6397 048 _W = W;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6398 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6399 050 /* alias for the digits of x*/
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6400 051 tmpx = x->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6401 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6402 053 /* copy the digits of a into W[0..a->used-1] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6403 054 for (ix = 0; ix < x->used; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6404 055 *_W++ = *tmpx++;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6405 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6406 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6407 058 /* zero the high words of W[a->used..m->used*2] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6408 059 for (; ix < n->used * 2 + 1; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6409 060 *_W++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6410 061 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6411 062 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6412 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6413 064 /* now we proceed to zero successive digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6414 065 * from the least significant upwards
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6415 066 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6416 067 for (ix = 0; ix < n->used; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6417 068 /* mu = ai * m' mod b
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6418 069 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6419 070 * We avoid a double precision multiplication (which isn't required)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6420 071 * by casting the value down to a mp_digit. Note this requires
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6421 072 * that W[ix-1] have the carry cleared (see after the inner loop)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6422 073 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6423 074 register mp_digit mu;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6424 075 mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6425 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6426 077 /* a = a + mu * m * b**i
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6427 078 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6428 079 * This is computed in place and on the fly. The multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6429 080 * by b**i is handled by offseting which columns the results
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6430 081 * are added to.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6431 082 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6432 083 * Note the comba method normally doesn't handle carries in the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6433 084 * inner loop In this case we fix the carry from the previous
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6434 085 * column since the Montgomery reduction requires digits of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6435 086 * result (so far) [see above] to work. This is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6436 087 * handled by fixing up one carry after the inner loop. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6437 088 * carry fixups are done in order so after these loops the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6438 089 * first m->used words of W[] have the carries fixed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6439 090 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6440 091 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6441 092 register int iy;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6442 093 register mp_digit *tmpn;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6443 094 register mp_word *_W;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6444 095
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6445 096 /* alias for the digits of the modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6446 097 tmpn = n->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6447 098
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6448 099 /* Alias for the columns set by an offset of ix */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6449 100 _W = W + ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6450 101
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6451 102 /* inner loop */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6452 103 for (iy = 0; iy < n->used; iy++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6453 104 *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6454 105 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6455 106 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6456 107
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6457 108 /* now fix carry for next digit, W[ix+1] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6458 109 W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6459 110 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6460 111
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6461 112 /* now we have to propagate the carries and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6462 113 * shift the words downward [all those least
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6463 114 * significant digits we zeroed].
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6464 115 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6465 116 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6466 117 register mp_digit *tmpx;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6467 118 register mp_word *_W, *_W1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6468 119
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6469 120 /* nox fix rest of carries */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6470 121
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6471 122 /* alias for current word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6472 123 _W1 = W + ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6473 124
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6474 125 /* alias for next word, where the carry goes */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6475 126 _W = W + ++ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6476 127
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6477 128 for (; ix <= n->used * 2 + 1; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6478 129 *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6479 130 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6480 131
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6481 132 /* copy out, A = A/b**n
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6482 133 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6483 134 * The result is A/b**n but instead of converting from an
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6484 135 * array of mp_word to mp_digit than calling mp_rshd
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6485 136 * we just copy them in the right order
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6486 137 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6487 138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6488 139 /* alias for destination word */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6489 140 tmpx = x->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6490 141
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6491 142 /* alias for shifted double precision result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6492 143 _W = W + n->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6493 144
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6494 145 for (ix = 0; ix < n->used + 1; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6495 146 *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6496 147 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6497 148
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6498 149 /* zero oldused digits, if the input a was larger than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6499 150 * m->used+1 we'll have to clear the digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6500 151 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6501 152 for (; ix < olduse; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6502 153 *tmpx++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6503 154 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6504 155 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6505 156
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6506 157 /* set the max used and clamp */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6507 158 x->used = n->used + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6508 159 mp_clamp (x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6509 160
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6510 161 /* if A >= m then A = A - m */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6511 162 if (mp_cmp_mag (x, n) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6512 163 return s_mp_sub (x, n, x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6513 164 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6514 165 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6515 166 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6516 167 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6517 168
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6518 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6519 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6520
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6521 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6522 the same alias variables to make the code easier to read.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6523
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6524 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6525 forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line 109 fixes the carry
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6526 for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6527
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6528 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6529 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6530 digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6531
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6532 \subsection{Montgomery Setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6533 To calculate the variable $\rho$ a relatively simple algorithm will be required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6534
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6535 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6536 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6537 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6538 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6539 \hline Algorithm \textbf{mp\_montgomery\_setup}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6540 \textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6541 \textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6542 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6543 1. $b \leftarrow n_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6544 2. If $b$ is even return(\textit{MP\_VAL}) \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6545 3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6546 4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6547 \hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6548 5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6549 6. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6550 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6551 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6552 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6553 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6554 \caption{Algorithm mp\_montgomery\_setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6555 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6556
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6557 \textbf{Algorithm mp\_montgomery\_setup.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6558 This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6559 to calculate $1/n_0$ when $\beta$ is a power of two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6560
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6561 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6562 \hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6563 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6564 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6565 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6566 017 /* setups the montgomery reduction stuff */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6567 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6568 019 mp_montgomery_setup (mp_int * n, mp_digit * rho)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6569 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6570 021 mp_digit x, b;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6571 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6572 023 /* fast inversion mod 2**k
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6573 024 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6574 025 * Based on the fact that
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6575 026 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6576 027 * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6577 028 * => 2*X*A - X*X*A*A = 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6578 029 * => 2*(1) - (1) = 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6579 030 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6580 031 b = n->dp[0];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6581 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6582 033 if ((b & 1) == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6583 034 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6584 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6585 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6586 037 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6587 038 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6588 039 #if !defined(MP_8BIT)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6589 040 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6590 041 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6591 042 #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6592 043 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6593 044 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6594 045 #ifdef MP_64BIT
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6595 046 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6596 047 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6597 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6598 049 /* rho = -1/m mod b */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6599 050 *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MAS
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6600 K;
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6601 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6602 052 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6603 053 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6604 054 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6605 055
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6606 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6607 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6608
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6609 This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6610 multiplications when $\beta$ is not the default 28-bits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6611
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6612 \section{The Diminished Radix Algorithm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6613 The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6614 or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6615
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6616 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6617 (x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6618 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6619
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6620 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6621 then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6622 of the above equation is very simple. First write $x$ in the product form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6623
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6624 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6625 x = qn + r
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6626 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6627
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6628 Now reduce both sides modulo $(n - k)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6629
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6630 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6631 x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6632 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6633
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6634 The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6635 into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6636
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6637 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6638 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6639 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6640 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6641 \hline Algorithm \textbf{Diminished Radix Reduction}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6642 \textbf{Input}. Integer $x$, $n$, $k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6643 \textbf{Output}. $x \mbox{ mod } (n - k)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6644 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6645 1. $q \leftarrow \lfloor x / n \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6646 2. $q \leftarrow k \cdot q$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6647 3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6648 4. $x \leftarrow x + q$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6649 5. If $x \ge (n - k)$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6650 \hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6651 \hspace{3mm}5.2 Goto step 1. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6652 6. Return $x$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6653 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6654 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6655 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6656 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6657 \caption{Algorithm Diminished Radix Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6658 \label{fig:DR}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6659 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6660
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6661 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6662 once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6663
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6664 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6665 0 \le x < n^2 + k^2 - 2nk
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6666 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6667
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6668 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6669
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6670 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6671 q < n - 2k - k^2/n
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6672 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6673
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6674 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6675 $0 \le x < n$. By step four the sum $x + q$ is bounded by
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6676
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6677 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6678 0 \le q + x < (k + 1)n - 2k^2 - 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6679 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6680
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6681 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6682 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6683 range $0 \le x < (n - k - 1)^2$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6684
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6685 \begin{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6686 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6687 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6688 \begin{tabular}{|l|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6689 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6690 $x = 123456789, n = 256, k = 3$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6691 \hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6692 $q \leftarrow q*k = 1446759$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6693 $x \leftarrow x \mbox{ mod } n = 21$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6694 $x \leftarrow x + q = 1446780$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6695 $x \leftarrow x - (n - k) = 1446527$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6696 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6697 $q \leftarrow \lfloor x/n \rfloor = 5650$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6698 $q \leftarrow q*k = 16950$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6699 $x \leftarrow x \mbox{ mod } n = 127$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6700 $x \leftarrow x + q = 17077$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6701 $x \leftarrow x - (n - k) = 16824$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6702 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6703 $q \leftarrow \lfloor x/n \rfloor = 65$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6704 $q \leftarrow q*k = 195$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6705 $x \leftarrow x \mbox{ mod } n = 184$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6706 $x \leftarrow x + q = 379$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6707 $x \leftarrow x - (n - k) = 126$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6708 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6709 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6710 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6711 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6712 \caption{Example Diminished Radix Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6713 \label{fig:EXDR}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6714 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6715
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6716 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6717 is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6718 three passes were required to find the residue $x \equiv 126$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6719
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6720
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6721 \subsection{Choice of Moduli}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6722 On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6723 modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6724
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6725 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6726 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6727 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6728 which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6729
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6730 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6731 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6732 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6733
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6734 Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6735 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6736 $2^p$ logic except $p$ must be a multiple of $lg(\beta)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6737
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6738 \subsection{Choice of $k$}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6739 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6740 in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6741 as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6742
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6743 \subsection{Restricted Diminished Radix Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6744 The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6745 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6746 of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6747 of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6748 exponentiations are performed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6749
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6750 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6751 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6752 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6753 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6754 \hline Algorithm \textbf{mp\_dr\_reduce}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6755 \textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6756 \hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6757 \textbf{Output}. $x \mbox{ mod } n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6758 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6759 1. $m \leftarrow n.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6760 2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6761 3. $\mu \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6762 4. for $i$ from $0$ to $m - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6763 \hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6764 \hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6765 \hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6766 5. $x_{m} \leftarrow \mu$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6767 6. for $i$ from $m + 1$ to $x.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6768 \hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6769 7. Clamp excess digits of $x$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6770 8. If $x \ge n$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6771 \hspace{3mm}8.1 $x \leftarrow x - n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6772 \hspace{3mm}8.2 Goto step 3. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6773 9. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6774 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6775 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6776 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6777 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6778 \caption{Algorithm mp\_dr\_reduce}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6779 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6780
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6781 \textbf{Algorithm mp\_dr\_reduce.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6782 This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6783 with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6784
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6785 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6786 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6787 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6788 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6789 $x$ before the addition of the multiple of the upper half.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6790
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6791 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6792 at step 3.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6793
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6794 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6795 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6796 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6797 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6798 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6799 017 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6800 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6801 019 * Based on algorithm from the paper
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6802 020 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6803 021 * "Generating Efficient Primes for Discrete Log Cryptosystems"
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6804 022 * Chae Hoon Lim, Pil Joong Lee,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6805 023 * POSTECH Information Research Laboratories
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6806 024 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6807 025 * The modulus must be of a special format [see manual]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6808 026 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6809 027 * Has been modified to use algorithm 7.10 from the LTM book instead
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6810 028 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6811 029 * Input x must be in the range 0 <= x <= (n-1)**2
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6812 030 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6813 031 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6814 032 mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6815 033 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6816 034 int err, i, m;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6817 035 mp_word r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6818 036 mp_digit mu, *tmpx1, *tmpx2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6819 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6820 038 /* m = digits in modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6821 039 m = n->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6822 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6823 041 /* ensure that "x" has at least 2m digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6824 042 if (x->alloc < m + m) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6825 043 if ((err = mp_grow (x, m + m)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6826 044 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6827 045 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6828 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6829 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6830 048 /* top of loop, this is where the code resumes if
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6831 049 * another reduction pass is required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6832 050 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6833 051 top:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6834 052 /* aliases for digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6835 053 /* alias for lower half of x */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6836 054 tmpx1 = x->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6837 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6838 056 /* alias for upper half of x, or x/B**m */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6839 057 tmpx2 = x->dp + m;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6840 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6841 059 /* set carry to zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6842 060 mu = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6843 061
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6844 062 /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6845 063 for (i = 0; i < m; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6846 064 r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6847 065 *tmpx1++ = (mp_digit)(r & MP_MASK);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6848 066 mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6849 067 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6850 068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6851 069 /* set final carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6852 070 *tmpx1++ = mu;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6853 071
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6854 072 /* zero words above m */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6855 073 for (i = m + 1; i < x->used; i++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6856 074 *tmpx1++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6857 075 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6858 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6859 077 /* clamp, sub and return */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6860 078 mp_clamp (x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6861 079
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6862 080 /* if x >= n then subtract and reduce again
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6863 081 * Each successive "recursion" makes the input smaller and smaller.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6864 082 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6865 083 if (mp_cmp_mag (x, n) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6866 084 s_mp_sub(x, n, x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6867 085 goto top;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6868 086 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6869 087 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6870 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6871 089 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6872 090
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6873 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6874 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6875
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6876 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6877 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6878 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6879
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6880 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6881 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})
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6882 in this algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6883
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6884 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6885 same pointer will point to the $m+1$'th digit where the zeroes will be placed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6886
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6887 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6888 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6889 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6890 does not need to be checked.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6891
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6892 \subsubsection{Setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6893 To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6894 completeness.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6895
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6896 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6897 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6898 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6899 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6900 \hline Algorithm \textbf{mp\_dr\_setup}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6901 \textbf{Input}. mp\_int $n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6902 \textbf{Output}. $k = \beta - n_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6903 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6904 1. $k \leftarrow \beta - n_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6905 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6906 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6907 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6908 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6909 \caption{Algorithm mp\_dr\_setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6910 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6911
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6912 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6913 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6914 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6915 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6916 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6917 017 /* determines the setup value */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6918 018 void mp_dr_setup(mp_int *a, mp_digit *d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6919 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6920 020 /* the casts are required if DIGIT_BIT is one less than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6921 021 * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6922 022 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6923 023 *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6924 024 ((mp_word)a->dp[0]));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6925 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6926 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6927 027 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6928 028
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6929 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6930 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6931
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6932 \subsubsection{Modulus Detection}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6933 Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6934 of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6935
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6936 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6937 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6938 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6939 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6940 \hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6941 \textbf{Input}. mp\_int $n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6942 \textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6943 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6944 1. If $n.used < 2$ then return($0$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6945 2. for $ix$ from $1$ to $n.used - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6946 \hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6947 3. Return($1$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6948 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6949 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6950 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6951 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6952 \caption{Algorithm mp\_dr\_is\_modulus}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6953 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6954
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6955 \textbf{Algorithm mp\_dr\_is\_modulus.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6956 This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6957 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6958 step 3 then $n$ must be of Diminished Radix form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6959
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6960 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6961 \hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6962 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6963 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6964 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6965 017 /* determines if a number is a valid DR modulus */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6966 018 int mp_dr_is_modulus(mp_int *a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6967 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6968 020 int ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6969 021
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6970 022 /* must be at least two digits */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6971 023 if (a->used < 2) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6972 024 return 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6973 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6974 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6975 027 /* must be of the form b**k - a [a <= b] so all
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6976 028 * but the first digit must be equal to -1 (mod b).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6977 029 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6978 030 for (ix = 1; ix < a->used; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6979 031 if (a->dp[ix] != MP_MASK) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6980 032 return 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6981 033 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6982 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6983 035 return 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6984 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6985 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6986 038 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
6987 039
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6988 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6989 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6990
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6991 \subsection{Unrestricted Diminished Radix Reduction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6992 The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6993 is a straightforward adaptation of algorithm~\ref{fig:DR}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6994
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6995 In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6996 algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6997
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6998 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
6999 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7000 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7001 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7002 \hline Algorithm \textbf{mp\_reduce\_2k}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7003 \textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7004 \hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7005 \textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7006 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7007 1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7008 2. While $a \ge n$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7009 \hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7010 \hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7011 \hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7012 \hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7013 \hspace{3mm}2.5 If $a \ge n$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7014 \hspace{6mm}2.5.1 $a \leftarrow a - n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7015 3. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7016 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7017 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7018 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7019 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7020 \caption{Algorithm mp\_reduce\_2k}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7021 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7023 \textbf{Algorithm mp\_reduce\_2k.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7024 This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7025 shift which makes the algorithm fairly inexpensive to use.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7027 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7028 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7029 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7030 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7031 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7032 017 /* reduces a modulo n where n is of the form 2**p - d */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7033 018 int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7034 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7035 020 mp_int q;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7036 021 int p, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7037 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7038 023 if ((res = mp_init(&q)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7039 024 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7040 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7041 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7042 027 p = mp_count_bits(n);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7043 028 top:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7044 029 /* q = a/2**p, a = a mod 2**p */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7045 030 if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7046 031 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7047 032 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7048 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7049 034 if (d != 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7050 035 /* q = q * d */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7051 036 if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7052 037 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7053 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7054 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7055 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7056 041 /* a = a + q */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7057 042 if ((res = s_mp_add(a, &q, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7058 043 goto ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7059 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7060 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7061 046 if (mp_cmp_mag(a, n) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7062 047 s_mp_sub(a, n, a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7063 048 goto top;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7064 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7065 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7066 051 ERR:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7067 052 mp_clear(&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7068 053 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7069 054 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7070 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7071 056 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7072 057
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7073 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7074 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7075
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7076 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7077 on line 30 calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7078 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7079 any multiplications.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7080
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7081 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7082 positive. By using the unsigned versions the overhead is kept to a minimum.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7083
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7084 \subsubsection{Unrestricted Setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7085 To setup this reduction algorithm the value of $k = 2^p - n$ is required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7086
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7087 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7088 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7089 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7090 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7091 \hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7092 \textbf{Input}. mp\_int $n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7093 \textbf{Output}. $k = 2^p - n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7094 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7095 1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7096 2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7097 3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7098 4. $k \leftarrow x_0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7099 5. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7100 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7101 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7102 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7103 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7104 \caption{Algorithm mp\_reduce\_2k\_setup}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7105 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7106
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7107 \textbf{Algorithm mp\_reduce\_2k\_setup.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7108 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7109 is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7111 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7112 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7113 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7114 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7115 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7116 017 /* determines the setup value */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7117 018 int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7118 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7119 020 int res, p;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7120 021 mp_int tmp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7121 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7122 023 if ((res = mp_init(&tmp)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7123 024 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7124 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7125 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7126 027 p = mp_count_bits(a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7127 028 if ((res = mp_2expt(&tmp, p)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7128 029 mp_clear(&tmp);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7129 030 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7130 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7131 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7132 033 if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7133 034 mp_clear(&tmp);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7134 035 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7135 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7136 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7137 038 *d = tmp.dp[0];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7138 039 mp_clear(&tmp);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7139 040 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7140 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7141 042 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7142 043
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7143 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7144 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7145
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7146 \subsubsection{Unrestricted Detection}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7147 An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7148
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7149 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7150 \item The number has only one digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7151 \item The number has more than one digit and every bit from the $\beta$'th to the most significant is one.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7152 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7153
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7154 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7155 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7156 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7157 significant bit. The resulting sum will be a power of two.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7158
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7159 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7160 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7161 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7162 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7163 \hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7164 \textbf{Input}. mp\_int $n$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7165 \textbf{Output}. $1$ if of proper form, $0$ otherwise \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7166 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7167 1. If $n.used = 0$ then return($0$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7168 2. If $n.used = 1$ then return($1$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7169 3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7170 4. for $x$ from $lg(\beta)$ to $p$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7171 \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$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7172 5. Return($1$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7173 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7174 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7175 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7176 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7177 \caption{Algorithm mp\_reduce\_is\_2k}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7178 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7179
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7180 \textbf{Algorithm mp\_reduce\_is\_2k.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7181 This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7182
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7183 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7184 \hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7185 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7186 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7187 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7188 017 /* determines if mp_reduce_2k can be used */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7189 018 int mp_reduce_is_2k(mp_int *a)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7190 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7191 020 int ix, iy, iw;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7192 021 mp_digit iz;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7193 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7194 023 if (a->used == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7195 024 return MP_NO;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7196 025 \} else if (a->used == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7197 026 return MP_YES;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7198 027 \} else if (a->used > 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7199 028 iy = mp_count_bits(a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7200 029 iz = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7201 030 iw = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7202 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7203 032 /* Test every bit from the second digit up, must be 1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7204 033 for (ix = DIGIT_BIT; ix < iy; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7205 034 if ((a->dp[iw] & iz) == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7206 035 return MP_NO;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7207 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7208 037 iz <<= 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7209 038 if (iz > (mp_digit)MP_MASK) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7210 039 ++iw;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7211 040 iz = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7212 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7213 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7214 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7215 044 return MP_YES;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7216 045 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7217 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7218 047 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7219 048
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7220 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7221 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7222
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7223
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7224
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7225 \section{Algorithm Comparison}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7226 So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7227 that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7228 all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7229
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7230 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7231 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7232 \begin{tabular}{|c|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7233 \hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7234 \hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7235 \hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7236 \hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7237 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7238 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7239 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7240 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7241
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7242 In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7243 reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7244 calling the half precision multipliers, addition and division by $\beta$ algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7245
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7246 For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7247 shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7248 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7249 modular exponentiation to greatly speed up the operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7250
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7251
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7252
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7253 \section*{Exercises}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7254 \begin{tabular}{cl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7255 $\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7256 & calculates the correct value of $\rho$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7257 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7258 $\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7259 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7260 $\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7261 & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7262 & terminate within $1 \le k \le 10$ iterations. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7263 & \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7264 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7265
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7266
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7267 \chapter{Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7268 Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7269 in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7270 cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7271 such cryptosystem and many methods have been sought to speed it up.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7272
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7273 \section{Exponentiation Basics}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7274 A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7275 the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7276 with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7277
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7278 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7279 are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7280 significant bit. If $b$ is a $k$-bit integer than the following equation is true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7281
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7282 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7283 a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7284 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7285
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7286 By taking the base $a$ logarithm of both sides of the equation the following equation is the result.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7287
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7288 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7289 b = \sum_{i=0}^{k-1}2^i \cdot b_i
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7290 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7291
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7292 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7293 $a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7294 $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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7295
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7296 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7297 be computed in an auxilary variable. Consider the following equivalent algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7298
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7299 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7300 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7301 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7302 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7303 \hline Algorithm \textbf{Left to Right Exponentiation}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7304 \textbf{Input}. Integer $a$, $b$ and $k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7305 \textbf{Output}. $c = a^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7306 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7307 1. $c \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7308 2. for $i$ from $k - 1$ to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7309 \hspace{3mm}2.1 $c \leftarrow c^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7310 \hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7311 3. Return $c$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7312 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7313 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7314 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7315 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7316 \caption{Left to Right Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7317 \label{fig:LTOR}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7318 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7319
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7320 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7321 multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7322 product.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7323
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7324 For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7325
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7326 \newpage\begin{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7327 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7328 \begin{tabular}{|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7329 \hline \textbf{Value of $i$} & \textbf{Value of $c$} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7330 \hline - & $1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7331 \hline $5$ & $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7332 \hline $4$ & $a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7333 \hline $3$ & $a^4 \cdot a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7334 \hline $2$ & $a^8 \cdot a^2 \cdot a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7335 \hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7336 \hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7337 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7338 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7339 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7340 \caption{Example of Left to Right Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7341 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7342
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7343 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7344 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7345
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7346 \subsection{Single Digit Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7347 The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7348 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7349 $b$ that are greater than three.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7350
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7351 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7352 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7353 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7354 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7355 \hline Algorithm \textbf{mp\_expt\_d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7356 \textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7357 \textbf{Output}. $c = a^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7358 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7359 1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7360 2. $c \leftarrow 1$ (\textit{mp\_set}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7361 3. for $x$ from 1 to $lg(\beta)$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7362 \hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7363 \hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7364 \hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7365 \hspace{3mm}3.3 $b \leftarrow b << 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7366 4. Clear $g$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7367 5. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7368 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7369 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7370 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7371 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7372 \caption{Algorithm mp\_expt\_d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7373 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7374
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7375 \textbf{Algorithm mp\_expt\_d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7376 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7377 quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7378 exponent is a fixed width.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7379
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7380 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7381 $1$ in the subsequent step.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7382
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7383 Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7384 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7385 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7386 iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7387
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7388 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7389 \hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7390 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7391 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7392 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7393 017 /* calculate c = a**b using a square-multiply algorithm */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7394 018 int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7395 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7396 020 int res, x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7397 021 mp_int g;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7398 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7399 023 if ((res = mp_init_copy (&g, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7400 024 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7401 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7402 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7403 027 /* set initial result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7404 028 mp_set (c, 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7405 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7406 030 for (x = 0; x < (int) DIGIT_BIT; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7407 031 /* square */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7408 032 if ((res = mp_sqr (c, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7409 033 mp_clear (&g);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7410 034 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7411 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7412 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7413 037 /* if the bit is set multiply */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7414 038 if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7415 039 if ((res = mp_mul (c, &g, c)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7416 040 mp_clear (&g);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7417 041 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7418 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7419 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7420 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7421 045 /* shift to next bit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7422 046 b <<= 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7423 047 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7424 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7425 049 mp_clear (&g);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7426 050 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7427 051 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7428 052 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7429 053
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7430 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7431 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7432
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7433 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7434 the most significant down towards the least significant. The invariant squaring operation placed on line 32 is performed first. After
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7435 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7436 46 moves all of the bits of the exponent upwards towards the most significant location.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7437
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7438 \section{$k$-ary Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7439 When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7440 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7441 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7442 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7443 portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7444
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7445 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7446 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7447 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7448 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7449 \hline Algorithm \textbf{$k$-ary Exponentiation}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7450 \textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7451 \textbf{Output}. $c = a^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7452 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7453 1. $c \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7454 2. for $i$ from $t - 1$ to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7455 \hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7456 \hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7457 \hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7458 3. Return $c$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7459 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7460 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7461 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7462 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7463 \caption{$k$-ary Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7464 \label{fig:KARY}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7465 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7466
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7467 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7468 precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7469 $2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7470 However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7471
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7472 Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7473 original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7474 has increased slightly but the number of multiplications has nearly halved.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7475
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7476 \subsection{Optimal Values of $k$}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7477 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7478 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7479 for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7480
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7481 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7482 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7483 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7484 \begin{tabular}{|c|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7485 \hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7486 \hline $16$ & $2$ & $27$ & $24$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7487 \hline $32$ & $3$ & $49$ & $48$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7488 \hline $64$ & $3$ & $92$ & $96$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7489 \hline $128$ & $4$ & $175$ & $192$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7490 \hline $256$ & $4$ & $335$ & $384$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7491 \hline $512$ & $5$ & $645$ & $768$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7492 \hline $1024$ & $6$ & $1257$ & $1536$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7493 \hline $2048$ & $6$ & $2452$ & $3072$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7494 \hline $4096$ & $7$ & $4808$ & $6144$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7495 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7496 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7497 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7498 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7499 \caption{Optimal Values of $k$ for $k$-ary Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7500 \label{fig:OPTK}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7501 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7502
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7503 \subsection{Sliding-Window Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7504 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7505 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7506 algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7507
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7508 Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7509
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7510 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7511 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7512 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7513 \begin{tabular}{|c|c|c|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7514 \hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7515 \hline $16$ & $3$ & $24$ & $27$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7516 \hline $32$ & $3$ & $45$ & $49$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7517 \hline $64$ & $4$ & $87$ & $92$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7518 \hline $128$ & $4$ & $167$ & $175$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7519 \hline $256$ & $5$ & $322$ & $335$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7520 \hline $512$ & $6$ & $628$ & $645$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7521 \hline $1024$ & $6$ & $1225$ & $1257$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7522 \hline $2048$ & $7$ & $2403$ & $2452$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7523 \hline $4096$ & $8$ & $4735$ & $4808$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7524 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7525 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7526 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7527 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7528 \caption{Optimal Values of $k$ for Sliding Window Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7529 \label{fig:OPTK2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7530 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7531
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7532 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7533 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7534 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7535 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7536 \hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7537 \textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7538 \textbf{Output}. $c = a^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7539 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7540 1. $c \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7541 2. for $i$ from $t - 1$ to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7542 \hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7543 \hspace{6mm}2.1.1 $c \leftarrow c^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7544 \hspace{3mm}2.2 else do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7545 \hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7546 \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$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7547 \hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7548 \hspace{6mm}2.2.4 $i \leftarrow i - k$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7549 3. Return $c$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7550 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7551 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7552 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7553 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7554 \caption{Sliding Window $k$-ary Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7555 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7556
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7557 Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7558 algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7559 the size as the previous table.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7560
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7561 Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7562 the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7563 exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7564 a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7565 squarings. The second method requires $8$ multiplications and $18$ squarings.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7566
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7567 In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7568
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7569 \section{Modular Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7570
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7571 Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7572 $d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7573 modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7574
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7575 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7576 one of the algorithms presented in chapter six.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7577
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7578 Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7579 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7580 value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7581 terminates with an error.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7582
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7583 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7584 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7585 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7586 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7587 \hline Algorithm \textbf{mp\_exptmod}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7588 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7589 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7590 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7591 1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7592 2. If $b.sign = MP\_NEG$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7593 \hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7594 \hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7595 \hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7596 3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7597 \hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7598 4. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7599 \hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7600 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7601 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7602 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7603 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7604 \caption{Algorithm mp\_exptmod}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7605 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7606
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7607 \textbf{Algorithm mp\_exptmod.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7608 The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7609 which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7610 except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7611 algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7612
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7613 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7614 \hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7615 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7616 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7617 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7618 017
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7619 018 /* this is a shell function that calls either the normal or Montgomery
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7620 019 * exptmod functions. Originally the call to the montgomery code was
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7621 020 * embedded in the normal function but that wasted alot of stack space
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7622 021 * for nothing (since 99% of the time the Montgomery code would be called)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7623 022 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7624 023 int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7625 024 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7626 025 int dr;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7627 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7628 027 /* modulus P must be positive */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7629 028 if (P->sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7630 029 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7631 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7632 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7633 032 /* if exponent X is negative we have to recurse */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7634 033 if (X->sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7635 034 #ifdef BN_MP_INVMOD_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7636 035 mp_int tmpG, tmpX;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7637 036 int err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7638 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7639 038 /* first compute 1/G mod P */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7640 039 if ((err = mp_init(&tmpG)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7641 040 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7642 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7643 042 if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7644 043 mp_clear(&tmpG);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7645 044 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7646 045 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7647 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7648 047 /* now get |X| */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7649 048 if ((err = mp_init(&tmpX)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7650 049 mp_clear(&tmpG);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7651 050 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7652 051 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7653 052 if ((err = mp_abs(X, &tmpX)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7654 053 mp_clear_multi(&tmpG, &tmpX, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7655 054 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7656 055 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7657 056
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7658 057 /* and now compute (1/G)**|X| instead of G**X [X < 0] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7659 058 err = mp_exptmod(&tmpG, &tmpX, P, Y);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7660 059 mp_clear_multi(&tmpG, &tmpX, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7661 060 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7662 061 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7663 062 /* no invmod */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7664 063 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7665 064 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7666 065 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7667 066
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7668 067 /* modified diminished radix reduction */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7669 068 #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defin
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7670 ed(BN_S_MP_EXPTMOD_C)
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7671 069 if (mp_reduce_is_2k_l(P) == MP_YES) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7672 070 return s_mp_exptmod(G, X, P, Y, 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7673 071 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7674 072 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7675 073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7676 074 #ifdef BN_MP_DR_IS_MODULUS_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7677 075 /* is it a DR modulus? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7678 076 dr = mp_dr_is_modulus(P);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7679 077 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7680 078 /* default to no */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7681 079 dr = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7682 080 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7683 081
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7684 082 #ifdef BN_MP_REDUCE_IS_2K_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7685 083 /* if not, is it a unrestricted DR modulus? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7686 084 if (dr == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7687 085 dr = mp_reduce_is_2k(P) << 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7688 086 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7689 087 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7690 088
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7691 089 /* if the modulus is odd or dr != 0 use the montgomery method */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7692 090 #ifdef BN_MP_EXPTMOD_FAST_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7693 091 if (mp_isodd (P) == 1 || dr != 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7694 092 return mp_exptmod_fast (G, X, P, Y, dr);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7695 093 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7696 094 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7697 095 #ifdef BN_S_MP_EXPTMOD_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7698 096 /* otherwise use the generic Barrett reduction technique */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7699 097 return s_mp_exptmod (G, X, P, Y, 0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7700 098 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7701 099 /* no exptmod for evens */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7702 100 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7703 101 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7704 102 #ifdef BN_MP_EXPTMOD_FAST_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7705 103 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7706 104 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7707 105 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7708 106
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7709 107 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7710 108
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7711 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7712 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7713
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7714 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7715 negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7716 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7717 exponent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7718
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7719 If the exponent is positive the algorithm resumes the exponentiation. Line 76 determines if the modulus is of the restricted Diminished Radix
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7720 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7721 of three values.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7722
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7723 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7724 \item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7725 \item $dr = 1$ means that the modulus is of restricted Diminished Radix form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7726 \item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7727 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7728
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7729 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,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7730 the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7731
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7732 \subsection{Barrett Modular Exponentiation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7733
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7734 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7735 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7736 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7737 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7738 \hline Algorithm \textbf{s\_mp\_exptmod}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7739 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7740 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7741 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7742 1. $k \leftarrow lg(x)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7743 2. $winsize \leftarrow \left \lbrace \begin{array}{ll}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7744 2 & \mbox{if }k \le 7 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7745 3 & \mbox{if }7 < k \le 36 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7746 4 & \mbox{if }36 < k \le 140 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7747 5 & \mbox{if }140 < k \le 450 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7748 6 & \mbox{if }450 < k \le 1303 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7749 7 & \mbox{if }1303 < k \le 3529 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7750 8 & \mbox{if }3529 < k \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7751 \end{array} \right .$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7752 3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7753 4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7754 5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7755 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7756 Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7757 6. $k \leftarrow 2^{winsize - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7758 7. $M_{k} \leftarrow M_1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7759 8. for $ix$ from 0 to $winsize - 2$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7760 \hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7761 \hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7762 9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7763 \hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7764 \hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7765 10. $res \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7766 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7767 Start Sliding Window. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7768 11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7769 12. Loop \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7770 \hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7771 \hspace{3mm}12.2 If $bitcnt = 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7772 \hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7773 \hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7774 \hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7775 \hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7776 Continued on next page. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7777 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7778 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7779 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7780 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7781 \caption{Algorithm s\_mp\_exptmod}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7782 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7783
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7784 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7785 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7786 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7787 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7788 \hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7789 \textbf{Input}. mp\_int $a$, $b$ and $c$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7790 \textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7791 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7792 \hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7793 \hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7794 \hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7795 \hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7796 \hspace{6mm}12.6.1 $res \leftarrow res^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7797 \hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7798 \hspace{6mm}12.6.3 Goto step 12. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7799 \hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7800 \hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7801 \hspace{3mm}12.9 $mode \leftarrow 2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7802 \hspace{3mm}12.10 If $bitcpy = winsize$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7803 \hspace{6mm}Window is full so perform the squarings and single multiplication. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7804 \hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7805 \hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7806 \hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7807 \hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7808 \hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7809 \hspace{6mm}Reset the window. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7810 \hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7811 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7812 No more windows left. Check for residual bits of exponent. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7813 13. If $mode = 2$ and $bitcpy > 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7814 \hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7815 \hspace{6mm}13.1.1 $res \leftarrow res^2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7816 \hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7817 \hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7818 \hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7819 \hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7820 \hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7821 14. $y \leftarrow res$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7822 15. Clear $res$, $mu$ and the $M$ array. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7823 16. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7824 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7825 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7826 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7827 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7828 \caption{Algorithm s\_mp\_exptmod (continued)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7829 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7830
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7831 \textbf{Algorithm s\_mp\_exptmod.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7832 This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7833 algorithm to keep the product small throughout the algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7834
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7835 The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7836 larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7837 table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7838
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7839 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7840 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7841 times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7842
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7843 Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7844 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7845 \item The variable $mode$ dictates how the bits of the exponent are interpreted.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7846 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7847 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7848 $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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7849 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7850 are read and a single squaring is performed. If a non-zero bit is read a new window is created.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7851 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7852 downwards.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7853 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7854 \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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7855 is fetched from the exponent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7856 \item The variable $buf$ holds the currently read digit of the exponent.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7857 \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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7858 \item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7859 the appropriate operations performed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7860 \item The variable $bitbuf$ holds the current bits of the window being formed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7861 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7862
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7863 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7864 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7865 read and if there are no digits left than the loop terminates.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7866
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7867 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7868 upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7869 trailing edges the entire exponent is read from most significant bit to least significant bit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7870
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7871 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7872 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7873 the two cases of $mode = 1$ and $mode = 2$ respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7874
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7875 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7876 \begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7877 \includegraphics{pics/expt_state.ps}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7878 \caption{Sliding Window State Diagram}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7879 \label{pic:expt_state}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7880 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7881 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7882
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7883 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7884 a Left-to-Right algorithm is used to process the remaining few bits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7885
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7886 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7887 \hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7888 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7889 \begin{alltt}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7890 016 #ifdef MP_LOW_MEM
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7891 017 #define TAB_SIZE 32
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7892 018 #else
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7893 019 #define TAB_SIZE 256
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7894 020 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7895 021
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7896 022 int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmod
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
7897 e)
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7898 023 \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7899 024 mp_int M[TAB_SIZE], res, mu;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7900 025 mp_digit buf;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7901 026 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7902 027 int (*redux)(mp_int*,mp_int*,mp_int*);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7903 028
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7904 029 /* find window size */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7905 030 x = mp_count_bits (X);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7906 031 if (x <= 7) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7907 032 winsize = 2;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7908 033 \} else if (x <= 36) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7909 034 winsize = 3;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7910 035 \} else if (x <= 140) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7911 036 winsize = 4;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7912 037 \} else if (x <= 450) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7913 038 winsize = 5;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7914 039 \} else if (x <= 1303) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7915 040 winsize = 6;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7916 041 \} else if (x <= 3529) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7917 042 winsize = 7;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7918 043 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7919 044 winsize = 8;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7920 045 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7921 046
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7922 047 #ifdef MP_LOW_MEM
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7923 048 if (winsize > 5) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7924 049 winsize = 5;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7925 050 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7926 051 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7927 052
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7928 053 /* init M array */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7929 054 /* init first cell */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7930 055 if ((err = mp_init(&M[1])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7931 056 return err;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7932 057 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7933 058
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7934 059 /* now init the second half of the array */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7935 060 for (x = 1<<(winsize-1); x < (1 << winsize); x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7936 061 if ((err = mp_init(&M[x])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7937 062 for (y = 1<<(winsize-1); y < x; y++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7938 063 mp_clear (&M[y]);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7939 064 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7940 065 mp_clear(&M[1]);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7941 066 return err;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7942 067 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7943 068 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7944 069
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7945 070 /* create mu, used for Barrett reduction */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7946 071 if ((err = mp_init (&mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7947 072 goto LBL_M;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7948 073 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7949 074
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7950 075 if (redmode == 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7951 076 if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7952 077 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7953 078 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7954 079 redux = mp_reduce;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7955 080 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7956 081 if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7957 082 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7958 083 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7959 084 redux = mp_reduce_2k_l;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7960 085 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7961 086
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7962 087 /* create M table
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7963 088 *
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7964 089 * The M table contains powers of the base,
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7965 090 * e.g. M[x] = G**x mod P
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7966 091 *
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7967 092 * The first half of the table is not
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7968 093 * computed though accept for M[0] and M[1]
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7969 094 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7970 095 if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7971 096 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7972 097 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7973 098
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7974 099 /* compute the value at M[1<<(winsize-1)] by squaring
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7975 100 * M[1] (winsize-1) times
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7976 101 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7977 102 if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7978 103 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7979 104 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7980 105
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7981 106 for (x = 0; x < (winsize - 1); x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7982 107 /* square it */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7983 108 if ((err = mp_sqr (&M[1 << (winsize - 1)],
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7984 109 &M[1 << (winsize - 1)])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7985 110 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7986 111 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7987 112
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7988 113 /* reduce modulo P */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7989 114 if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7990 115 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7991 116 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7992 117 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7993 118
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7994 119 /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7995 120 * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7996 121 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7997 122 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7998 123 if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
7999 124 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8000 125 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8001 126 if ((err = redux (&M[x], P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8002 127 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8003 128 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8004 129 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8005 130
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8006 131 /* setup result */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8007 132 if ((err = mp_init (&res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8008 133 goto LBL_MU;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8009 134 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8010 135 mp_set (&res, 1);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8011 136
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8012 137 /* set initial mode and bit cnt */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8013 138 mode = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8014 139 bitcnt = 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8015 140 buf = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8016 141 digidx = X->used - 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8017 142 bitcpy = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8018 143 bitbuf = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8019 144
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8020 145 for (;;) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8021 146 /* grab next digit as required */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8022 147 if (--bitcnt == 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8023 148 /* if digidx == -1 we are out of digits */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8024 149 if (digidx == -1) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8025 150 break;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8026 151 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8027 152 /* read next digit and reset the bitcnt */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8028 153 buf = X->dp[digidx--];
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8029 154 bitcnt = (int) DIGIT_BIT;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8030 155 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8031 156
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8032 157 /* grab the next msb from the exponent */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8033 158 y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8034 159 buf <<= (mp_digit)1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8035 160
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8036 161 /* if the bit is zero and mode == 0 then we ignore it
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8037 162 * These represent the leading zero bits before the first 1 bit
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8038 163 * in the exponent. Technically this opt is not required but it
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8039 164 * does lower the # of trivial squaring/reductions used
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8040 165 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8041 166 if (mode == 0 && y == 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8042 167 continue;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8043 168 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8044 169
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8045 170 /* if the bit is zero and mode == 1 then we square */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8046 171 if (mode == 1 && y == 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8047 172 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8048 173 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8049 174 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8050 175 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8051 176 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8052 177 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8053 178 continue;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8054 179 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8055 180
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8056 181 /* else we add it to the window */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8057 182 bitbuf |= (y << (winsize - ++bitcpy));
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8058 183 mode = 2;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8059 184
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8060 185 if (bitcpy == winsize) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8061 186 /* ok window is filled so square as required and multiply */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8062 187 /* square first */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8063 188 for (x = 0; x < winsize; x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8064 189 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8065 190 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8066 191 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8067 192 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8068 193 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8069 194 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8070 195 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8071 196
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8072 197 /* then multiply */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8073 198 if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8074 199 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8075 200 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8076 201 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8077 202 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8078 203 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8079 204
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8080 205 /* empty window and reset */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8081 206 bitcpy = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8082 207 bitbuf = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8083 208 mode = 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8084 209 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8085 210 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8086 211
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8087 212 /* if bits remain then square/multiply */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8088 213 if (mode == 2 && bitcpy > 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8089 214 /* square then multiply if the bit is set */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8090 215 for (x = 0; x < bitcpy; x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8091 216 if ((err = mp_sqr (&res, &res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8092 217 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8093 218 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8094 219 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8095 220 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8096 221 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8097 222
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8098 223 bitbuf <<= 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8099 224 if ((bitbuf & (1 << winsize)) != 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8100 225 /* then multiply */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8101 226 if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8102 227 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8103 228 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8104 229 if ((err = redux (&res, P, &mu)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8105 230 goto LBL_RES;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8106 231 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8107 232 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8108 233 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8109 234 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8110 235
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8111 236 mp_exch (&res, Y);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8112 237 err = MP_OKAY;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8113 238 LBL_RES:mp_clear (&res);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8114 239 LBL_MU:mp_clear (&mu);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8115 240 LBL_M:
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8116 241 mp_clear(&M[1]);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8117 242 for (x = 1<<(winsize-1); x < (1 << winsize); x++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8118 243 mp_clear (&M[x]);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8119 244 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8120 245 return err;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8121 246 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8122 247 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8123 248
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8124 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8125 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8126
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8127 Lines 31 through 45 determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8128 from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8129 on line 37 the value of $x$ is already known to be greater than $140$.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8130
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8131 The conditional piece of code beginning on line 47 allows the window size to be restricted to five bits. This logic is used to ensure
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8132 the table of precomputed powers of $G$ remains relatively small.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8133
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8134 The for loop on line 60 initializes the $M$ array while lines 71 and 76 through 85 initialize the reduction
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8135 function that will be used for this modulus.
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8136
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8137 -- More later.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8139 \section{Quick Power of Two}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8140 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8141 equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8142
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8143 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8144 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8145 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8146 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8147 \hline Algorithm \textbf{mp\_2expt}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8148 \textbf{Input}. integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8149 \textbf{Output}. $a \leftarrow 2^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8150 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8151 1. $a \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8152 2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8153 3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8154 4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8155 5. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8156 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8157 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8158 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8159 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8160 \caption{Algorithm mp\_2expt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8161 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8162
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8163 \textbf{Algorithm mp\_2expt.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8164
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8165 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8166 \hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8167 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8168 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8169 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8170 017 /* computes a = 2**b
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8171 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8172 019 * Simple algorithm which zeroes the int, grows it then just sets one bit
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8173 020 * as required.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8174 021 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8175 022 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8176 023 mp_2expt (mp_int * a, int b)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8177 024 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8178 025 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8179 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8180 027 /* zero a as per default */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8181 028 mp_zero (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8182 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8183 030 /* grow a to accomodate the single bit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8184 031 if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8185 032 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8186 033 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8187 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8188 035 /* set the used count of where the bit will go */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8189 036 a->used = b / DIGIT_BIT + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8190 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8191 038 /* put the single bit in its place */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8192 039 a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8193 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8194 041 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8195 042 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8196 043 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8197 044
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8198 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8199 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8200
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8201 \chapter{Higher Level Algorithms}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8202
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8203 This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8204 routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8205
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8206 The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8207 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8208 These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8209 various representations of integers. For example, converting from an mp\_int to a string of character.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8210
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8211 \section{Integer Division with Remainder}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8212 \label{sec:division}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8213
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8214 Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8215 the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8216 will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8217 let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8218
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8219 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8220 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8221 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8222 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8223 \hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8224 \textbf{Input}. integer $x$ and $y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8225 \textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8226 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8227 1. $q \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8228 2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8229 3. for $t$ from $n$ down to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8230 \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. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8231 \hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8232 \hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8233 4. $r \leftarrow y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8234 5. Return($q, r$) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8235 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8236 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8237 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8238 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8239 \caption{Algorithm Radix-$\beta$ Integer Division}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8240 \label{fig:raddiv}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8241 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8242
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8243 As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8244 their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8245
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8246 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8247 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8248 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8249 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8250 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8251 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8252
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8253 Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8254 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8255 remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8256 $237 \cdot 23 + 20 = 5471$ is true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8257
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8258 \subsection{Quotient Estimation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8259 \label{sec:divest}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8260 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8261 digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8262 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8263 dividend and divisor are zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8264
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8265 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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8266 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8267 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8268 represent the most significant digits of the dividend and divisor respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8269
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8270 \textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8271 $k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. }
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8272 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8273 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8274 $-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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8275 inequalities will prove the hypothesis.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8276
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8277 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8278 y - \hat k x \le y - \hat k x_s\beta^s
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8279 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8280
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8281 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8283 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8284 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)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8285 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8286
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8287 By simplifying the previous inequality the following inequality is formed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8288
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8289 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8290 y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8291 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8292
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8293 Subsequently,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8294
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8295 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8296 y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8297 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8298
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8299 Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8300
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8301
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8302 \subsection{Normalized Integers}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8303 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8304 $x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8305 remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8306 lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8307
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8308 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8309 {{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8310 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8311
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8312 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8313
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8314 \subsection{Radix-$\beta$ Division with Remainder}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8315 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8316 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8317 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8318 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8319 \hline Algorithm \textbf{mp\_div}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8320 \textbf{Input}. mp\_int $a, b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8321 \textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8322 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8323 1. If $b = 0$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8324 2. If $\vert a \vert < \vert b \vert$ then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8325 \hspace{3mm}2.1 $d \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8326 \hspace{3mm}2.2 $c \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8327 \hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8328 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8329 Setup the quotient to receive the digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8330 3. Grow $q$ to $a.used + 2$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8331 4. $q \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8332 5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8333 6. $sign \leftarrow \left \lbrace \begin{array}{ll}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8334 MP\_ZPOS & \mbox{if }a.sign = b.sign \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8335 MP\_NEG & \mbox{otherwise} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8336 \end{array} \right .$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8337 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8338 Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8339 7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8340 8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8341 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8342 Find the leading digit of the quotient. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8343 9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8344 10. $y \leftarrow y \cdot \beta^{n - t}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8345 11. While ($x \ge y$) do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8346 \hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8347 \hspace{3mm}11.2 $x \leftarrow x - y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8348 12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8349 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8350 Continued on the next page. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8351 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8352 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8353 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8354 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8355 \caption{Algorithm mp\_div}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8356 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8357
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8358 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8359 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8360 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8361 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8362 \hline Algorithm \textbf{mp\_div} (continued). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8363 \textbf{Input}. mp\_int $a, b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8364 \textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8365 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8366 Now find the remainder fo the digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8367 13. for $i$ from $n$ down to $(t + 1)$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8368 \hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8369 \hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8370 \hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8371 \hspace{3mm}13.3 else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8372 \hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8373 \hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8374 \hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8375 \hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8376 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8377 Fixup quotient estimation. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8378 \hspace{3mm}13.5 Loop \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8379 \hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8380 \hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8381 \hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8382 \hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8383 \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$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8384 \hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8385 \hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8386 \hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8387 \hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8388 \hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8389 \hspace{6mm}13.10 t$1 \leftarrow y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8390 \hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8391 \hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8392 \hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8393 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8394 Finalize the result. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8395 14. Clamp excess digits of $q$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8396 15. $c \leftarrow q, c.sign \leftarrow sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8397 16. $x.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8398 17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8399 18. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8400 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8401 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8402 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8403 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8404 \caption{Algorithm mp\_div (continued)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8405 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8406 \textbf{Algorithm mp\_div.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8407 This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8408 division and will produce a fully qualified quotient and remainder.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8409
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8410 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8411 zero and the remainder is the dividend.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8412
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8413 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8414 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8415 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8416 This is performed by shifting both to the left by enough bits to get the desired normalization.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8417
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8418 At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8419 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8420 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8421 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8422 times to produce the desired leading digit of the quotient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8423
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8424 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8425 accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8426 induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8427
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8428 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8429 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8430 order approximation to adjust the quotient digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8431
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8432 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8433 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8434 algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8435
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8436 Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8437 remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8438 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8439 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8440 respectively be replaced with a zero.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8441
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8442 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8443 \hspace{-5.1mm}{\bf File}: bn\_mp\_div.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8444 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8445 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8446 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8447 017 #ifdef BN_MP_DIV_SMALL
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8448 018
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8449 019 /* slower bit-bang division... also smaller */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8450 020 int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8451 021 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8452 022 mp_int ta, tb, tq, q;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8453 023 int res, n, n2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8454 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8455 025 /* is divisor zero ? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8456 026 if (mp_iszero (b) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8457 027 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8458 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8459 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8460 030 /* if a < b then q=0, r = a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8461 031 if (mp_cmp_mag (a, b) == MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8462 032 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8463 033 res = mp_copy (a, d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8464 034 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8465 035 res = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8466 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8467 037 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8468 038 mp_zero (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8469 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8470 040 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8471 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8472 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8473 043 /* init our temps */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8474 044 if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8475 045 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8476 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8477 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8478 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8479 049 mp_set(&tq, 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8480 050 n = mp_count_bits(a) - mp_count_bits(b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8481 051 if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8482 052 ((res = mp_abs(b, &tb)) != MP_OKAY) ||
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8483 053 ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8484 054 ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8485 055 goto LBL_ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8486 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8487 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8488 058 while (n-- >= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8489 059 if (mp_cmp(&tb, &ta) != MP_GT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8490 060 if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8491 061 ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8492 062 goto LBL_ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8493 063 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8494 064 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8495 065 if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8496 066 ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8497 067 goto LBL_ERR;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8498 068 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8499 069 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8500 070
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8501 071 /* now q == quotient and ta == remainder */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8502 072 n = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8503 073 n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8504 074 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8505 075 mp_exch(c, &q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8506 076 c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8507 077 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8508 078 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8509 079 mp_exch(d, &ta);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8510 080 d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8511 081 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8512 082 LBL_ERR:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8513 083 mp_clear_multi(&ta, &tb, &tq, &q, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8514 084 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8515 085 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8516 086
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8517 087 #else
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8518 088
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8519 089 /* integer signed division.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8520 090 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8521 091 * HAC pp.598 Algorithm 14.20
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8522 092 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8523 093 * Note that the description in HAC is horribly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8524 094 * incomplete. For example, it doesn't consider
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8525 095 * the case where digits are removed from 'x' in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8526 096 * the inner loop. It also doesn't consider the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8527 097 * case that y has fewer than three digits, etc..
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8528 098 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8529 099 * The overall algorithm is as described as
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8530 100 * 14.20 from HAC but fixed to treat these cases.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8531 101 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8532 102 int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8533 103 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8534 104 mp_int q, x, y, t1, t2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8535 105 int res, n, t, i, norm, neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8536 106
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8537 107 /* is divisor zero ? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8538 108 if (mp_iszero (b) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8539 109 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8540 110 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8541 111
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8542 112 /* if a < b then q=0, r = a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8543 113 if (mp_cmp_mag (a, b) == MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8544 114 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8545 115 res = mp_copy (a, d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8546 116 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8547 117 res = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8548 118 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8549 119 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8550 120 mp_zero (c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8551 121 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8552 122 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8553 123 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8554 124
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8555 125 if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8556 126 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8557 127 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8558 128 q.used = a->used + 2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8559 129
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8560 130 if ((res = mp_init (&t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8561 131 goto LBL_Q;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8562 132 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8563 133
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8564 134 if ((res = mp_init (&t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8565 135 goto LBL_T1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8566 136 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8567 137
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8568 138 if ((res = mp_init_copy (&x, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8569 139 goto LBL_T2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8570 140 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8571 141
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8572 142 if ((res = mp_init_copy (&y, b)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8573 143 goto LBL_X;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8574 144 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8575 145
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8576 146 /* fix the sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8577 147 neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8578 148 x.sign = y.sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8579 149
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8580 150 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8581 151 norm = mp_count_bits(&y) % DIGIT_BIT;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8582 152 if (norm < (int)(DIGIT_BIT-1)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8583 153 norm = (DIGIT_BIT-1) - norm;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8584 154 if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8585 155 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8586 156 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8587 157 if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8588 158 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8589 159 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8590 160 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8591 161 norm = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8592 162 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8593 163
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8594 164 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8595 165 n = x.used - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8596 166 t = y.used - 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8597 167
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8598 168 /* while (x >= y*b**n-t) do \{ q[n-t] += 1; x -= y*b**\{n-t\} \} */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8599 169 if ((res = mp_lshd (&y, n - t)) != MP_OKAY) \{ /* y = y*b**\{n-t\} */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8600 170 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8601 171 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8602 172
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8603 173 while (mp_cmp (&x, &y) != MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8604 174 ++(q.dp[n - t]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8605 175 if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8606 176 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8607 177 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8608 178 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8609 179
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8610 180 /* reset y by shifting it back down */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8611 181 mp_rshd (&y, n - t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8612 182
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8613 183 /* step 3. for i from n down to (t + 1) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8614 184 for (i = n; i >= (t + 1); i--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8615 185 if (i > x.used) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8616 186 continue;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8617 187 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8618 188
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8619 189 /* step 3.1 if xi == yt then set q\{i-t-1\} to b-1,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8620 190 * otherwise set q\{i-t-1\} to (xi*b + x\{i-1\})/yt */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8621 191 if (x.dp[i] == y.dp[t]) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8622 192 q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8623 193 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8624 194 mp_word tmp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8625 195 tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8626 196 tmp |= ((mp_word) x.dp[i - 1]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8627 197 tmp /= ((mp_word) y.dp[t]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8628 198 if (tmp > (mp_word) MP_MASK)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8629 199 tmp = MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8630 200 q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8631 201 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8632 202
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8633 203 /* while (q\{i-t-1\} * (yt * b + y\{t-1\})) >
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8634 204 xi * b**2 + xi-1 * b + xi-2
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8635 205
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8636 206 do q\{i-t-1\} -= 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8637 207 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8638 208 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8639 209 do \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8640 210 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8641 211
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8642 212 /* find left hand */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8643 213 mp_zero (&t1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8644 214 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8645 215 t1.dp[1] = y.dp[t];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8646 216 t1.used = 2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8647 217 if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8648 218 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8649 219 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8650 220
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8651 221 /* find right hand */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8652 222 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8653 223 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8654 224 t2.dp[2] = x.dp[i];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8655 225 t2.used = 3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8656 226 \} while (mp_cmp_mag(&t1, &t2) == MP_GT);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8657 227
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8658 228 /* step 3.3 x = x - q\{i-t-1\} * y * b**\{i-t-1\} */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8659 229 if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8660 230 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8661 231 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8662 232
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8663 233 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8664 234 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8665 235 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8666 236
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8667 237 if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8668 238 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8669 239 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8670 240
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8671 241 /* if x < 0 then \{ x = x + y*b**\{i-t-1\}; q\{i-t-1\} -= 1; \} */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8672 242 if (x.sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8673 243 if ((res = mp_copy (&y, &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8674 244 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8675 245 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8676 246 if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8677 247 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8678 248 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8679 249 if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8680 250 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8681 251 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8682 252
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8683 253 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8684 254 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8685 255 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8686 256
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8687 257 /* now q is the quotient and x is the remainder
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8688 258 * [which we have to normalize]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8689 259 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8690 260
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8691 261 /* get sign before writing to c */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8692 262 x.sign = x.used == 0 ? MP_ZPOS : a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8693 263
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8694 264 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8695 265 mp_clamp (&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8696 266 mp_exch (&q, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8697 267 c->sign = neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8698 268 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8699 269
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8700 270 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8701 271 mp_div_2d (&x, norm, &x, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8702 272 mp_exch (&x, d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8703 273 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8704 274
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8705 275 res = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8706 276
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8707 277 LBL_Y:mp_clear (&y);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8708 278 LBL_X:mp_clear (&x);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8709 279 LBL_T2:mp_clear (&t2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8710 280 LBL_T1:mp_clear (&t1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8711 281 LBL_Q:mp_clear (&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8712 282 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8713 283 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8714 284
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8715 285 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8716 286
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8717 287 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8718 288
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8719 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8720 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8721
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8722 The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8723 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8724 algorithm with only the quotient is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8725
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8726 \begin{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8727 mp_div(&a, &b, &c, NULL); /* c = [a/b] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8728 \end{verbatim}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8729
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8730 Lines 108 and 113 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8731 respectively. After the two trivial cases all of the temporary variables are initialized. Line 147 determines the sign of
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8732 the quotient and line 148 ensures that both $x$ and $y$ are positive.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8733
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8734 The number of bits in the leading digit is calculated on line 151. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8735 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8736 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8737 them to the left by $lg(\beta) - 1 - k$ bits.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8738
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8739 Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8740 leading digit of the quotient. The loop beginning on line 184 will produce the remainder of the quotient digits.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8741
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8742 The conditional ``continue'' on line 186 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8743 algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8744 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.}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8745
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8746 Lines 214, 216 and 222 through 225 manually construct the high accuracy estimations by setting the digits of the two mp\_int
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8747 variables directly.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8748
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8749 \section{Single Digit Helpers}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8750
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8751 This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8752 the helper functions assume the single digit input is positive and will treat them as such.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8753
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8754 \subsection{Single Digit Addition and Subtraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8755
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8756 Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8757 algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8758
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8759 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8760 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8761 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8762 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8763 \hline Algorithm \textbf{mp\_add\_d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8764 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8765 \textbf{Output}. $c = a + b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8766 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8767 1. $t \leftarrow b$ (\textit{mp\_set}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8768 2. $c \leftarrow a + t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8769 3. Return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8770 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8771 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8772 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8773 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8774 \caption{Algorithm mp\_add\_d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8775 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8776
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8777 \textbf{Algorithm mp\_add\_d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8778 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8779
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8780 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8781 \hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8782 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8783 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8784 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8785 017 /* single digit addition */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8786 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8787 019 mp_add_d (mp_int * a, mp_digit b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8788 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8789 021 int res, ix, oldused;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8790 022 mp_digit *tmpa, *tmpc, mu;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8791 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8792 024 /* grow c as required */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8793 025 if (c->alloc < a->used + 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8794 026 if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8795 027 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8796 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8797 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8798 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8799 031 /* if a is negative and |a| >= b, call c = |a| - b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8800 032 if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8801 033 /* temporarily fix sign of a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8802 034 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8803 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8804 036 /* c = |a| - b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8805 037 res = mp_sub_d(a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8806 038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8807 039 /* fix sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8808 040 a->sign = c->sign = MP_NEG;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8809 041
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8810 042 /* clamp */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8811 043 mp_clamp(c);
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8812 044
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8813 045 return res;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8814 046 \}
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8815 047
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8816 048 /* old number of used digits in c */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8817 049 oldused = c->used;
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8818 050
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8819 051 /* sign always positive */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8820 052 c->sign = MP_ZPOS;
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8821 053
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8822 054 /* source alias */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8823 055 tmpa = a->dp;
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8824 056
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8825 057 /* destination alias */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8826 058 tmpc = c->dp;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8827 059
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8828 060 /* if a is positive */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8829 061 if (a->sign == MP_ZPOS) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8830 062 /* add digit, after this we're propagating
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8831 063 * the carry.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8832 064 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8833 065 *tmpc = *tmpa++ + b;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8834 066 mu = *tmpc >> DIGIT_BIT;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8835 067 *tmpc++ &= MP_MASK;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8836 068
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8837 069 /* now handle rest of the digits */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8838 070 for (ix = 1; ix < a->used; ix++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8839 071 *tmpc = *tmpa++ + mu;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8840 072 mu = *tmpc >> DIGIT_BIT;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8841 073 *tmpc++ &= MP_MASK;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8842 074 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8843 075 /* set final carry */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8844 076 ix++;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8845 077 *tmpc++ = mu;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8846 078
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8847 079 /* setup size */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8848 080 c->used = a->used + 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8849 081 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8850 082 /* a was negative and |a| < b */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8851 083 c->used = 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8852 084
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8853 085 /* the result is a single digit */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8854 086 if (a->used == 1) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8855 087 *tmpc++ = b - a->dp[0];
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8856 088 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8857 089 *tmpc++ = b;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8858 090 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8859 091
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8860 092 /* setup count so the clearing of oldused
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8861 093 * can fall through correctly
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8862 094 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8863 095 ix = 1;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8864 096 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8865 097
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8866 098 /* now zero to oldused */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8867 099 while (ix++ < oldused) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8868 100 *tmpc++ = 0;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8869 101 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8870 102 mp_clamp(c);
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8871 103
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8872 104 return MP_OKAY;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8873 105 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8874 106
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8875 107 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8876 108
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8877 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8878 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8879
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8880 Clever use of the letter 't'.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8881
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8882 \subsubsection{Subtraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8883 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8884
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8885 \subsection{Single Digit Multiplication}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8886 Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8887 multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8888 only has one digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8889
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8890 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8891 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8892 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8893 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8894 \hline Algorithm \textbf{mp\_mul\_d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8895 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8896 \textbf{Output}. $c = ab$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8897 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8898 1. $pa \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8899 2. Grow $c$ to at least $pa + 1$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8900 3. $oldused \leftarrow c.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8901 4. $c.used \leftarrow pa + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8902 5. $c.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8903 6. $\mu \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8904 7. for $ix$ from $0$ to $pa - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8905 \hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8906 \hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8907 \hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8908 8. $c_{pa} \leftarrow \mu$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8909 9. for $ix$ from $pa + 1$ to $oldused$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8910 \hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8911 10. Clamp excess digits of $c$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8912 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8913 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8914 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8915 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8916 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8917 \caption{Algorithm mp\_mul\_d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8918 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8919 \textbf{Algorithm mp\_mul\_d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8920 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8921 Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8922
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8923 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8924 \hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8925 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8926 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8927 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8928 017 /* multiply by a digit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8929 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8930 019 mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8931 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8932 021 mp_digit u, *tmpa, *tmpc;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8933 022 mp_word r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8934 023 int ix, res, olduse;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8935 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8936 025 /* make sure c is big enough to hold a*b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8937 026 if (c->alloc < a->used + 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8938 027 if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8939 028 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8940 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8941 030 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8942 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8943 032 /* get the original destinations used count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8944 033 olduse = c->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8945 034
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8946 035 /* set the sign */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8947 036 c->sign = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8948 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8949 038 /* alias for a->dp [source] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8950 039 tmpa = a->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8951 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8952 041 /* alias for c->dp [dest] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8953 042 tmpc = c->dp;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8954 043
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8955 044 /* zero carry */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8956 045 u = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8957 046
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8958 047 /* compute columns */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8959 048 for (ix = 0; ix < a->used; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8960 049 /* compute product and carry sum for this term */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8961 050 r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8962 051
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8963 052 /* mask off higher bits to get a single digit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8964 053 *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8965 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8966 055 /* send carry into next iteration */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8967 056 u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8968 057 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8969 058
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8970 059 /* store final carry [if any] and increment ix offset */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8971 060 *tmpc++ = u;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8972 061 ++ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8973 062
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8974 063 /* now zero digits above the top */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8975 064 while (ix++ < olduse) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8976 065 *tmpc++ = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8977 066 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8978 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8979 068 /* set used count */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8980 069 c->used = a->used + 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8981 070 mp_clamp(c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8982 071
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8983 072 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8984 073 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8985 074 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
8986 075
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8987 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8988 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8989
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8990 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8991 read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8992
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8993 \subsection{Single Digit Division}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8994 Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8995 divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8996
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8997 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8998 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
8999 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9000 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9001 \hline Algorithm \textbf{mp\_div\_d}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9002 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9003 \textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9004 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9005 1. If $b = 0$ then return(\textit{MP\_VAL}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9006 2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9007 3. Init $q$ to $a.used$ digits. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9008 4. $q.used \leftarrow a.used$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9009 5. $q.sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9010 6. $\hat w \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9011 7. for $ix$ from $a.used - 1$ down to $0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9012 \hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9013 \hspace{3mm}7.2 If $\hat w \ge b$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9014 \hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9015 \hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9016 \hspace{3mm}7.3 else\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9017 \hspace{6mm}7.3.1 $t \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9018 \hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9019 8. $d \leftarrow \hat w$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9020 9. Clamp excess digits of $q$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9021 10. $c \leftarrow q$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9022 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9023 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9024 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9025 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9026 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9027 \caption{Algorithm mp\_div\_d}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9028 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9029 \textbf{Algorithm mp\_div\_d.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9030 This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9031 algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9032 after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9034 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9035 a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9036 from chapter seven.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9038 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9039 \hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9040 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9041 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9042 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9043 017 static int s_is_power_of_two(mp_digit b, int *p)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9044 018 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9045 019 int x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9046 020
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9047 021 for (x = 1; x < DIGIT_BIT; x++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9048 022 if (b == (((mp_digit)1)<<x)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9049 023 *p = x;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9050 024 return 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9051 025 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9052 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9053 027 return 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9054 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9055 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9056 030 /* single digit division (based on routine from MPI) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9057 031 int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9058 032 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9059 033 mp_int q;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9060 034 mp_word w;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9061 035 mp_digit t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9062 036 int res, ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9063 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9064 038 /* cannot divide by zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9065 039 if (b == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9066 040 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9067 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9068 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9069 043 /* quick outs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9070 044 if (b == 1 || mp_iszero(a) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9071 045 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9072 046 *d = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9073 047 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9074 048 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9075 049 return mp_copy(a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9076 050 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9077 051 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9078 052 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9079 053
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9080 054 /* power of two ? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9081 055 if (s_is_power_of_two(b, &ix) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9082 056 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9083 057 *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9084 058 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9085 059 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9086 060 return mp_div_2d(a, ix, c, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9087 061 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9088 062 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9089 063 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9090 064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9091 065 #ifdef BN_MP_DIV_3_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9092 066 /* three? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9093 067 if (b == 3) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9094 068 return mp_div_3(a, c, d);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9095 069 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9096 070 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9097 071
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9098 072 /* no easy answer [c'est la vie]. Just division */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9099 073 if ((res = mp_init_size(&q, a->used)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9100 074 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9101 075 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9102 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9103 077 q.used = a->used;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9104 078 q.sign = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9105 079 w = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9106 080 for (ix = a->used - 1; ix >= 0; ix--) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9107 081 w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9108 082
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9109 083 if (w >= b) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9110 084 t = (mp_digit)(w / b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9111 085 w -= ((mp_word)t) * ((mp_word)b);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9112 086 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9113 087 t = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9114 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9115 089 q.dp[ix] = (mp_digit)t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9116 090 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9117 091
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9118 092 if (d != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9119 093 *d = (mp_digit)w;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9120 094 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9121 095
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9122 096 if (c != NULL) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9123 097 mp_clamp(&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9124 098 mp_exch(&q, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9125 099 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9126 100 mp_clear(&q);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9127 101
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9128 102 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9129 103 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9130 104
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9131 105 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9132 106
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9133 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9134 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9135
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9136 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9137 indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9138
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9139 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9140 processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9141 compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9142
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9143 \subsection{Single Digit Root Extraction}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9144
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9145 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9146 (\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9147
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9148 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9149 x_{i+1} = x_i - {f(x_i) \over f'(x_i)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9150 \label{eqn:newton}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9151 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9152
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9153 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9154 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9155 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9156 algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9157
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9158 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9159 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9160 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9161 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9162 \hline Algorithm \textbf{mp\_n\_root}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9163 \textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9164 \textbf{Output}. $c^b \le a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9165 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9166 1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9167 2. $sign \leftarrow a.sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9168 3. $a.sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9169 4. t$2 \leftarrow 2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9170 5. Loop \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9171 \hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9172 \hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9173 \hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9174 \hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9175 \hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9176 \hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9177 \hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9178 \hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9179 6. Loop \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9180 \hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9181 \hspace{3mm}6.2 If t$2 > a$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9182 \hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9183 \hspace{6mm}6.2.2 Goto step 6. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9184 7. $a.sign \leftarrow sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9185 8. $c \leftarrow $ t$1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9186 9. $c.sign \leftarrow sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9187 10. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9188 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9189 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9190 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9191 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9192 \caption{Algorithm mp\_n\_root}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9193 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9194 \textbf{Algorithm mp\_n\_root.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9195 This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9196 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9197 $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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9198 multiplications by t$1$ inside the loop.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9199
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9200 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9201 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9202
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9203 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9204 \hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9205 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9206 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9207 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9208 017 /* find the n'th root of an integer
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9209 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9210 019 * Result found such that (c)**b <= a and (c+1)**b > a
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9211 020 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9212 021 * This algorithm uses Newton's approximation
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9213 022 * x[i+1] = x[i] - f(x[i])/f'(x[i])
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9214 023 * which will find the root in log(N) time where
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9215 024 * each step involves a fair bit. This is not meant to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9216 025 * find huge roots [square and cube, etc].
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9217 026 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9218 027 int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9219 028 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9220 029 mp_int t1, t2, t3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9221 030 int res, neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9222 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9223 032 /* input must be positive if b is even */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9224 033 if ((b & 1) == 0 && a->sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9225 034 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9226 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9227 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9228 037 if ((res = mp_init (&t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9229 038 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9230 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9231 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9232 041 if ((res = mp_init (&t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9233 042 goto LBL_T1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9234 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9235 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9236 045 if ((res = mp_init (&t3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9237 046 goto LBL_T2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9238 047 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9239 048
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9240 049 /* if a is negative fudge the sign but keep track */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9241 050 neg = a->sign;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9242 051 a->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9243 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9244 053 /* t2 = 2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9245 054 mp_set (&t2, 2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9246 055
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9247 056 do \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9248 057 /* t1 = t2 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9249 058 if ((res = mp_copy (&t2, &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9250 059 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9251 060 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9252 061
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9253 062 /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9254 063
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9255 064 /* t3 = t1**(b-1) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9256 065 if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9257 066 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9258 067 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9259 068
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9260 069 /* numerator */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9261 070 /* t2 = t1**b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9262 071 if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9263 072 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9264 073 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9265 074
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9266 075 /* t2 = t1**b - a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9267 076 if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9268 077 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9269 078 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9270 079
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9271 080 /* denominator */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9272 081 /* t3 = t1**(b-1) * b */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9273 082 if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9274 083 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9275 084 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9276 085
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9277 086 /* t3 = (t1**b - a)/(b * t1**(b-1)) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9278 087 if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9279 088 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9280 089 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9281 090
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9282 091 if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9283 092 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9284 093 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9285 094 \} while (mp_cmp (&t1, &t2) != MP_EQ);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9286 095
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9287 096 /* result can be off by a few so check */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9288 097 for (;;) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9289 098 if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9290 099 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9291 100 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9292 101
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9293 102 if (mp_cmp (&t2, a) == MP_GT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9294 103 if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9295 104 goto LBL_T3;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9296 105 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9297 106 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9298 107 break;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9299 108 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9300 109 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9301 110
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9302 111 /* reset the sign of a first */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9303 112 a->sign = neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9304 113
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9305 114 /* set the result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9306 115 mp_exch (&t1, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9307 116
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9308 117 /* set the sign of the result */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9309 118 c->sign = neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9310 119
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9311 120 res = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9312 121
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9313 122 LBL_T3:mp_clear (&t3);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9314 123 LBL_T2:mp_clear (&t2);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9315 124 LBL_T1:mp_clear (&t1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9316 125 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9317 126 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9318 127 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9319 128
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9320 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9321 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9322
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9323 \section{Random Number Generation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9324
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9325 Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9326 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9327 is solely for simulations and not intended for cryptographic use.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9328
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9329 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9330 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9331 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9332 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9333 \hline Algorithm \textbf{mp\_rand}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9334 \textbf{Input}. An integer $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9335 \textbf{Output}. A pseudo-random number of $b$ digits \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9336 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9337 1. $a \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9338 2. If $b \le 0$ return(\textit{MP\_OKAY}) \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9339 3. Pick a non-zero random digit $d$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9340 4. $a \leftarrow a + d$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9341 5. for $ix$ from 1 to $d - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9342 \hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9343 \hspace{3mm}5.2 Pick a random digit $d$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9344 \hspace{3mm}5.3 $a \leftarrow a + d$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9345 6. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9346 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9347 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9348 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9349 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9350 \caption{Algorithm mp\_rand}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9351 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9352 \textbf{Algorithm mp\_rand.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9353 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9354 final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9355 the integers from $0$ to $\beta - 1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9356
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9357 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9358 \hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9359 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9360 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9361 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9362 017 /* makes a pseudo-random int of a given size */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9363 018 int
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9364 019 mp_rand (mp_int * a, int digits)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9365 020 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9366 021 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9367 022 mp_digit d;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9368 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9369 024 mp_zero (a);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9370 025 if (digits <= 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9371 026 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9372 027 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9373 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9374 029 /* first place a random non-zero digit */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9375 030 do \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9376 031 d = ((mp_digit) abs (rand ())) & MP_MASK;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9377 032 \} while (d == 0);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9378 033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9379 034 if ((res = mp_add_d (a, d, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9380 035 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9381 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9382 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9383 038 while (--digits > 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9384 039 if ((res = mp_lshd (a, 1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9385 040 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9386 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9387 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9388 043 if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9389 044 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9390 045 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9391 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9392 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9393 048 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9394 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9395 050 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9396 051
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9397 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9398 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9399
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9400 \section{Formatted Representations}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9401 The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9402 be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9403 into a program.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9404
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9405 \subsection{Reading Radix-n Input}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9406 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9407 printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9408 map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9409 such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9410 mediums.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9411
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9412 \newpage\begin{figure}[here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9413 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9414 \begin{tabular}{cc|cc|cc|cc}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9415 \hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9416 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9417 0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9418 4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9419 8 & 8 & 9 & 9 & 10 & A & 11 & B \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9420 12 & C & 13 & D & 14 & E & 15 & F \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9421 16 & G & 17 & H & 18 & I & 19 & J \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9422 20 & K & 21 & L & 22 & M & 23 & N \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9423 24 & O & 25 & P & 26 & Q & 27 & R \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9424 28 & S & 29 & T & 30 & U & 31 & V \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9425 32 & W & 33 & X & 34 & Y & 35 & Z \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9426 36 & a & 37 & b & 38 & c & 39 & d \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9427 40 & e & 41 & f & 42 & g & 43 & h \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9428 44 & i & 45 & j & 46 & k & 47 & l \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9429 48 & m & 49 & n & 50 & o & 51 & p \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9430 52 & q & 53 & r & 54 & s & 55 & t \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9431 56 & u & 57 & v & 58 & w & 59 & x \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9432 60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9433 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9434 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9435 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9436 \caption{Lower ASCII Map}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9437 \label{fig:ASC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9438 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9439
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9440 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9441 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9442 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9443 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9444 \hline Algorithm \textbf{mp\_read\_radix}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9445 \textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9446 \textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9447 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9448 1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9449 2. $ix \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9450 3. If $str_0 =$ ``-'' then do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9451 \hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9452 \hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9453 4. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9454 \hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9455 5. $a \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9456 6. for $iy$ from $ix$ to $sn - 1$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9457 \hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9458 \hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9459 \hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9460 \hspace{3mm}6.4 $a \leftarrow a + y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9461 7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9462 8. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9463 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9464 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9465 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9466 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9467 \caption{Algorithm mp\_read\_radix}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9468 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9469 \textbf{Algorithm mp\_read\_radix.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9470 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9471 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9472 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9473 as part of larger input without any significant problem.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9474
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9475 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9476 \hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9477 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9478 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9479 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9480 017 /* read a string [ASCII] in a given radix */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9481 018 int mp_read_radix (mp_int * a, const char *str, int radix)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9482 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9483 020 int y, res, neg;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9484 021 char ch;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9485 022
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9486 023 /* zero the digit bignum */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9487 024 mp_zero(a);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9488 025
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9489 026 /* make sure the radix is ok */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9490 027 if (radix < 2 || radix > 64) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9491 028 return MP_VAL;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9492 029 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9493 030
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9494 031 /* if the leading digit is a
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9495 032 * minus set the sign to negative.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9496 033 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9497 034 if (*str == '-') \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9498 035 ++str;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9499 036 neg = MP_NEG;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9500 037 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9501 038 neg = MP_ZPOS;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9502 039 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9503 040
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9504 041 /* set the integer to the default of zero */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9505 042 mp_zero (a);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9506 043
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9507 044 /* process each digit of the string */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9508 045 while (*str) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9509 046 /* if the radix < 36 the conversion is case insensitive
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9510 047 * this allows numbers like 1AB and 1ab to represent the same value
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9511 048 * [e.g. in hex]
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9512 049 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9513 050 ch = (char) ((radix < 36) ? toupper (*str) : *str);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9514 051 for (y = 0; y < 64; y++) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9515 052 if (ch == mp_s_rmap[y]) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9516 053 break;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9517 054 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9518 055 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9519 056
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9520 057 /* if the char was found in the map
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9521 058 * and is less than the given radix add it
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9522 059 * to the number, otherwise exit the loop.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9523 060 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9524 061 if (y < radix) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9525 062 if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) \{
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9526 063 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9527 064 \}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9528 065 if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9529 066 return res;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9530 067 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9531 068 \} else \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9532 069 break;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9533 070 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9534 071 ++str;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9535 072 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9536 073
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9537 074 /* set the sign only if a != 0 */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9538 075 if (mp_iszero(a) != 1) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9539 076 a->sign = neg;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9540 077 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9541 078 return MP_OKAY;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9542 079 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9543 080 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9544 081
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9545 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9546 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9547
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9548 \subsection{Generating Radix-$n$ Output}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9549 Generating radix-$n$ output is fairly trivial with a division and remainder algorithm.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9550
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9551 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9552 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9553 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9554 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9555 \hline Algorithm \textbf{mp\_toradix}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9556 \textbf{Input}. A mp\_int $a$ and an integer $r$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9557 \textbf{Output}. The radix-$r$ representation of $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9558 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9559 1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9560 2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9561 3. $t \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9562 4. $str \leftarrow$ ``'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9563 5. if $t.sign = MP\_NEG$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9564 \hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9565 \hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9566 6. While ($t \ne 0$) do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9567 \hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9568 \hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9569 \hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9570 \hspace{3mm}6.4 $str \leftarrow str + y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9571 7. If $str_0 = $``$-$'' then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9572 \hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9573 8. Otherwise \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9574 \hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9575 9. Return(\textit{MP\_OKAY}).\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9576 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9577 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9578 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9579 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9580 \caption{Algorithm mp\_toradix}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9581 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9582 \textbf{Algorithm mp\_toradix.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9583 This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9584 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9585 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9586 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9587 (see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9588
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9589 \begin{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9590 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9591 \begin{tabular}{|c|c|c|}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9592 \hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9593 \hline $1234$ & -- & -- \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9594 \hline $123$ & $4$ & ``4'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9595 \hline $12$ & $3$ & ``43'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9596 \hline $1$ & $2$ & ``432'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9597 \hline $0$ & $1$ & ``4321'' \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9598 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9599 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9600 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9601 \caption{Example of Algorithm mp\_toradix.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9602 \label{fig:mpradix}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9603 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9604
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9605 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9606 \hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9607 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9608 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9609 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9610 017 /* stores a bignum as a ASCII string in a given radix (2..64) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9611 018 int mp_toradix (mp_int * a, char *str, int radix)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9612 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9613 020 int res, digs;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9614 021 mp_int t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9615 022 mp_digit d;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9616 023 char *_s = str;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9617 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9618 025 /* check range of the radix */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9619 026 if (radix < 2 || radix > 64) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9620 027 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9621 028 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9622 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9623 030 /* quick out if its zero */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9624 031 if (mp_iszero(a) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9625 032 *str++ = '0';
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9626 033 *str = '\symbol{92}0';
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9627 034 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9628 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9629 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9630 037 if ((res = mp_init_copy (&t, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9631 038 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9632 039 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9633 040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9634 041 /* if it is negative output a - */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9635 042 if (t.sign == MP_NEG) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9636 043 ++_s;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9637 044 *str++ = '-';
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9638 045 t.sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9639 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9640 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9641 048 digs = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9642 049 while (mp_iszero (&t) == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9643 050 if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9644 051 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9645 052 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9646 053 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9647 054 *str++ = mp_s_rmap[d];
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9648 055 ++digs;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9649 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9650 057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9651 058 /* reverse the digits of the string. In this case _s points
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9652 059 * to the first digit [exluding the sign] of the number]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9653 060 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9654 061 bn_reverse ((unsigned char *)_s, digs);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9655 062
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9656 063 /* append a NULL so the string is properly terminated */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9657 064 *str = '\symbol{92}0';
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9658 065
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9659 066 mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9660 067 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9661 068 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9662 069
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9663 070 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9664 071
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9665 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9666 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9667
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9668 \chapter{Number Theoretic Algorithms}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9669 This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9670 symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9671 various Sieve based factoring algorithms.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9672
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9673 \section{Greatest Common Divisor}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9674 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9675 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9676 simultaneously.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9677
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9678 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9679 $r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9680
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9681 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9682 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9683 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9684 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9685 \hline Algorithm \textbf{Greatest Common Divisor (I)}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9686 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9687 \textbf{Output}. The greatest common divisor $(a, b)$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9688 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9689 1. While ($b > 0$) do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9690 \hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9691 \hspace{3mm}1.2 $a \leftarrow b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9692 \hspace{3mm}1.3 $b \leftarrow r$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9693 2. Return($a$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9694 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9695 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9696 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9697 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9698 \caption{Algorithm Greatest Common Divisor (I)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9699 \label{fig:gcd1}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9700 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9701
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9702 This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9703 relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9704 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9705 In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9706
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9707 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9708 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9709 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9710 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9711 \hline Algorithm \textbf{Greatest Common Divisor (II)}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9712 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9713 \textbf{Output}. The greatest common divisor $(a, b)$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9714 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9715 1. While ($b > 0$) do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9716 \hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9717 \hspace{3mm}1.2 $b \leftarrow b - a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9718 2. Return($a$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9719 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9720 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9721 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9722 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9723 \caption{Algorithm Greatest Common Divisor (II)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9724 \label{fig:gcd2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9725 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9726
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9727 \textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9728 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9729 words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9730 divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9731 second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9732
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9733 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9734 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9735 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9736 the greatest common divisor.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9737
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9738 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9739 Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9740
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9741 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9742 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9743 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9744 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9745 \hline Algorithm \textbf{Greatest Common Divisor (III)}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9746 \textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9747 \textbf{Output}. The greatest common divisor $(a, b)$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9748 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9749 1. $k \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9750 2. While $a$ and $b$ are both divisible by $p$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9751 \hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9752 \hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9753 \hspace{3mm}2.3 $k \leftarrow k + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9754 3. While $a$ is divisible by $p$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9755 \hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9756 4. While $b$ is divisible by $p$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9757 \hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9758 5. While ($b > 0$) do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9759 \hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9760 \hspace{3mm}5.2 $b \leftarrow b - a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9761 \hspace{3mm}5.3 While $b$ is divisible by $p$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9762 \hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9763 6. Return($a \cdot p^k$). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9764 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9765 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9766 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9767 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9768 \caption{Algorithm Greatest Common Divisor (III)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9769 \label{fig:gcd3}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9770 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9771
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9772 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 >$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9773 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9774 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9775 divided out of the difference $b - a$ so long as the division leaves no remainder.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9776
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9777 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9778 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9779 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9780 largest of the pair.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9781
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9782 \subsection{Complete Greatest Common Divisor}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9783 The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9784 and will produce the greatest common divisor.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9785
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9786 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9787 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9788 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9789 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9790 \hline Algorithm \textbf{mp\_gcd}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9791 \textbf{Input}. mp\_int $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9792 \textbf{Output}. The greatest common divisor $c = (a, b)$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9793 \hline \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9794 1. If $a = 0$ then \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9795 \hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9796 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9797 2. If $b = 0$ then \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9798 \hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9799 \hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9800 3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9801 4. $k \leftarrow 0$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9802 5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9803 \hspace{3mm}5.1 $k \leftarrow k + 1$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9804 \hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9805 \hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9806 6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9807 \hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9808 7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9809 \hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9810 8. While $v.used > 0$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9811 \hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9812 \hspace{6mm}8.1.1 Swap $u$ and $v$. \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9813 \hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9814 \hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9815 \hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9816 9. $c \leftarrow u \cdot 2^k$ \\
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9817 10. Return(\textit{MP\_OKAY}). \\
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9818 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9819 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9820 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9821 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9822 \caption{Algorithm mp\_gcd}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9823 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9824 \textbf{Algorithm mp\_gcd.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9825 This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9826 Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9827 Algorithm B and in practice this appears to be true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9828
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9829 The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9830 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9831 $a$ and $b$ respectively and the algorithm will proceed to reduce the pair.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9832
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9833 Step five 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
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9834 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
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9835 six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9836 they cannot both be even.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9837
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9838 By step eight 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
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9839 or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9840 factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9841
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9842 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9843 must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9844
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9845 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9846 \hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9847 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9848 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9849 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9850 017 /* Greatest Common Divisor using the binary method */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9851 018 int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9852 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9853 020 mp_int u, v;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9854 021 int k, u_lsb, v_lsb, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9855 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9856 023 /* either zero than gcd is the largest */
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9857 024 if (mp_iszero (a) == MP_YES) \{
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9858 025 return mp_abs (b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9859 026 \}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9860 027 if (mp_iszero (b) == MP_YES) \{
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9861 028 return mp_abs (a, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9862 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9863 030
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9864 031 /* get copies of a and b we can modify */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9865 032 if ((res = mp_init_copy (&u, a)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9866 033 return res;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9867 034 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9868 035
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9869 036 if ((res = mp_init_copy (&v, b)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9870 037 goto LBL_U;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9871 038 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9872 039
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9873 040 /* must be positive for the remainder of the algorithm */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9874 041 u.sign = v.sign = MP_ZPOS;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9875 042
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9876 043 /* B1. Find the common power of two for u and v */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9877 044 u_lsb = mp_cnt_lsb(&u);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9878 045 v_lsb = mp_cnt_lsb(&v);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9879 046 k = MIN(u_lsb, v_lsb);
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9880 047
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9881 048 if (k > 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9882 049 /* divide the power of two out */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9883 050 if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9884 051 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9885 052 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9886 053
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9887 054 if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9888 055 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9889 056 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9890 057 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9891 058
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9892 059 /* divide any remaining factors of two out */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9893 060 if (u_lsb != k) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9894 061 if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9895 062 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9896 063 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9897 064 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9898 065
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9899 066 if (v_lsb != k) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9900 067 if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9901 068 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9902 069 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9903 070 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9904 071
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9905 072 while (mp_iszero(&v) == 0) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9906 073 /* make sure v is the largest */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9907 074 if (mp_cmp_mag(&u, &v) == MP_GT) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9908 075 /* swap u and v to make sure v is >= u */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9909 076 mp_exch(&u, &v);
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9910 077 \}
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9911 078
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9912 079 /* subtract smallest from largest */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9913 080 if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9914 081 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9915 082 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9916 083
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9917 084 /* Divide out all factors of two */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9918 085 if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9919 086 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9920 087 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9921 088 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9922 089
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9923 090 /* multiply by 2**k which we divided out at the beginning */
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9924 091 if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) \{
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9925 092 goto LBL_V;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9926 093 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9927 094 c->sign = MP_ZPOS;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9928 095 res = MP_OKAY;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9929 096 LBL_V:mp_clear (&u);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9930 097 LBL_U:mp_clear (&v);
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9931 098 return res;
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9932 099 \}
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9933 100 #endif
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9934 101
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9935 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9936 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9937
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9938 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9939 integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9940 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
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9941 trivial cases of inputs are handled on lines 23 through 29. After those lines the inputs are assumed to be non-zero.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9942
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9943 Lines 32 and 36 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9944 must be divided out of the two inputs. The block starting at line 43 removes common factors of two by first counting the number of trailing
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9945 zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9946 the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9947 entries than are accessible by an ``int'' so this is not a limitation.}.
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9948
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9949 At this point there are no more common factors of two in the two values. The divisions by a power of two on lines 61 and 67 remove
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9950 any independent 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
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
9951 on line 72 performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9952 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9953
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9954 \section{Least Common Multiple}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9955 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9956 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9957 and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9958
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9959 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9960 collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9961 Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9962 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] $.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9963
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9964 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9965 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9966 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9967 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9968 \hline Algorithm \textbf{mp\_lcm}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9969 \textbf{Input}. mp\_int $a$ and $b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9970 \textbf{Output}. The least common multiple $c = [a, b]$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9971 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9972 1. $c \leftarrow (a, b)$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9973 2. $t \leftarrow a \cdot b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9974 3. $c \leftarrow \lfloor t / c \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9975 4. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9976 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9977 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9978 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9979 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9980 \caption{Algorithm mp\_lcm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9981 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9982 \textbf{Algorithm mp\_lcm.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9983 This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9984 dividing the product of the two inputs by their greatest common divisor.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9985
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9986 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9987 \hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9988 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9989 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9990 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9991 017 /* computes least common multiple as |a*b|/(a, b) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9992 018 int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9993 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9994 020 int res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9995 021 mp_int t1, t2;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9996 022
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9997 023
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9998 024 if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
9999 025 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10000 026 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10001 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10002 028 /* t1 = get the GCD of the two inputs */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10003 029 if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10004 030 goto LBL_T;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10005 031 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10006 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10007 033 /* divide the smallest by the GCD */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10008 034 if (mp_cmp_mag(a, b) == MP_LT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10009 035 /* store quotient in t2 such that t2 * b is the LCM */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10010 036 if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10011 037 goto LBL_T;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10012 038 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10013 039 res = mp_mul(b, &t2, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10014 040 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10015 041 /* store quotient in t2 such that t2 * a is the LCM */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10016 042 if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10017 043 goto LBL_T;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10018 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10019 045 res = mp_mul(a, &t2, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10020 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10021 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10022 048 /* fix the sign to positive */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10023 049 c->sign = MP_ZPOS;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10024 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10025 051 LBL_T:
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10026 052 mp_clear_multi (&t1, &t2, NULL);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10027 053 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10028 054 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10029 055 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10030 056
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10031 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10032 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10033
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10034 \section{Jacobi Symbol Computation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10035 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10036 defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10037 equivalent to equation \ref{eqn:legendre}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10038
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10039 \textit{-- Tom, don't be an ass, cite your source here...!}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10040
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10041 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10042 a^{(p-1)/2} \equiv \begin{array}{rl}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10043 -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10044 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10045 1 & \mbox{if }a\mbox{ is a quadratic residue}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10046 \end{array} \mbox{ (mod }p\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10047 \label{eqn:legendre}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10048 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10050 \textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10051 An integer $a$ is a quadratic residue if the following equation has a solution.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10053 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10054 x^2 \equiv a \mbox{ (mod }p\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10055 \label{eqn:root}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10056 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10057
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10058 Consider the following equation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10060 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10061 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{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10062 \label{eqn:rooti}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10063 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10064
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10065 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{)}$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10066 then the quantity in the braces must be zero. By reduction,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10068 \begin{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10069 \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10070 \left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10071 x^2 \equiv a \mbox{ (mod }p\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10072 \end{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10073
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10074 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10075 is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10076 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10077 0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10078 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10079 One of the terms on the right hand side must be zero. \textbf{QED}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10080
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10081 \subsection{Jacobi Symbol}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10082 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10083 the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10084
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10085 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10086 \left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right )
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10087 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10088
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10089 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10090 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10091 following are true.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10092
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10093 \begin{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10094 \item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10095 \item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10096 \item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10097 \item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10098 \item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10099 $\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10100 \end{enumerate}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10101
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10102 Using these facts if $a = 2^k \cdot a'$ then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10103
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10104 \begin{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10105 \left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10106 = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right )
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10107 \label{eqn:jacobi}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10108 \end{eqnarray}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10109
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10110 By fact five,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10111
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10112 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10113 \left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10114 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10115
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10116 Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10117
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10118 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10119 \left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10120 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10121
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10122 By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10123
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10124 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10125 \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}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10126 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10127
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10128 The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10129 $\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10130 factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10131 Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10132
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10133 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10134 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10135 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10136 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10137 \hline Algorithm \textbf{mp\_jacobi}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10138 \textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10139 \textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10140 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10141 1. If $a = 0$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10142 \hspace{3mm}1.1 $c \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10143 \hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10144 2. If $a = 1$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10145 \hspace{3mm}2.1 $c \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10146 \hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10147 3. $a' \leftarrow a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10148 4. $k \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10149 5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10150 \hspace{3mm}5.1 $k \leftarrow k + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10151 \hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10152 6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10153 \hspace{3mm}6.1 $s \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10154 7. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10155 \hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10156 \hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10157 \hspace{6mm}7.2.1 $s \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10158 \hspace{3mm}7.3 else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10159 \hspace{6mm}7.3.1 $s \leftarrow -1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10160 8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10161 \hspace{3mm}8.1 $s \leftarrow -s$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10162 9. If $a' \ne 1$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10163 \hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10164 \hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10165 10. $c \leftarrow s$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10166 11. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10167 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10168 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10169 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10170 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10171 \caption{Algorithm mp\_jacobi}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10172 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10173 \textbf{Algorithm mp\_jacobi.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10174 This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10175 is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10176
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10177 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10178 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10179 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10180 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'$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10181 are congruent to one modulo four, otherwise it evaluates to negative one.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10182
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10183 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10184 $\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10185
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10186 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10187 \hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10188 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10189 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10190 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10191 017 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10192 018 * HAC pp. 73 Algorithm 2.149
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10193 019 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10194 020 int mp_jacobi (mp_int * a, mp_int * p, int *c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10195 021 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10196 022 mp_int a1, p1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10197 023 int k, s, r, res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10198 024 mp_digit residue;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10199 025
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10200 026 /* if p <= 0 return MP_VAL */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10201 027 if (mp_cmp_d(p, 0) != MP_GT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10202 028 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10203 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10204 030
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10205 031 /* step 1. if a == 0, return 0 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10206 032 if (mp_iszero (a) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10207 033 *c = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10208 034 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10209 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10210 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10211 037 /* step 2. if a == 1, return 1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10212 038 if (mp_cmp_d (a, 1) == MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10213 039 *c = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10214 040 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10215 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10216 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10217 043 /* default */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10218 044 s = 0;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10219 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10220 046 /* step 3. write a = a1 * 2**k */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10221 047 if ((res = mp_init_copy (&a1, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10222 048 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10223 049 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10224 050
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10225 051 if ((res = mp_init (&p1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10226 052 goto LBL_A1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10227 053 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10228 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10229 055 /* divide out larger power of two */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10230 056 k = mp_cnt_lsb(&a1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10231 057 if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10232 058 goto LBL_P1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10233 059 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10234 060
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10235 061 /* step 4. if e is even set s=1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10236 062 if ((k & 1) == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10237 063 s = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10238 064 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10239 065 /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10240 066 residue = p->dp[0] & 7;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10241 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10242 068 if (residue == 1 || residue == 7) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10243 069 s = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10244 070 \} else if (residue == 3 || residue == 5) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10245 071 s = -1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10246 072 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10247 073 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10248 074
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10249 075 /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10250 076 if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10251 077 s = -s;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10252 078 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10253 079
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10254 080 /* if a1 == 1 we're done */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10255 081 if (mp_cmp_d (&a1, 1) == MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10256 082 *c = s;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10257 083 \} else \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10258 084 /* n1 = n mod a1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10259 085 if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10260 086 goto LBL_P1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10261 087 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10262 088 if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10263 089 goto LBL_P1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10264 090 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10265 091 *c = s * r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10266 092 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10267 093
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10268 094 /* done */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10269 095 res = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10270 096 LBL_P1:mp_clear (&p1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10271 097 LBL_A1:mp_clear (&a1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10272 098 return res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10273 099 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10274 100 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10275 101
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10276 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10277 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10278
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10279 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10280 variable name character.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10281
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10282 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10283 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10284 the values it may obtain are merely $-1$, $0$ and $1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10285
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10286 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10287 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10288 processor requirements and neither is faster than the other.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10289
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10290 Line 61 through 70 determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10291 $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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10292 $(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 75 through 73.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10293
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10294 Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10295
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10296 \textit{-- Comment about default $s$ and such...}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10297
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10298 \section{Modular Inverse}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10299 \label{sec:modinv}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10300 The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10301 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10302 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10303 fields of integers. However, the former will be the matter of discussion.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10304
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10305 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10306 order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10307
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10308 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10309 ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10310 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10311
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10312 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10313 requires all of the prime factors. This approach also is very slow as the size of $p$ grows.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10314
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10315 A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10316 Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10317
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10318 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10319 ab + pq = 1
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10320 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10321
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10322 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10323 $a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10324 However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10325 binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10326 equation.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10327
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10328 \subsection{General Case}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10329 \newpage\begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10330 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10331 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10332 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10333 \hline Algorithm \textbf{mp\_invmod}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10334 \textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10335 \textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10336 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10337 1. If $b \le 0$ then return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10338 2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10339 3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10340 4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10341 5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10342 6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10343 \hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10344 \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 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10345 \hspace{6mm}6.2.1 $A \leftarrow A + y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10346 \hspace{6mm}6.2.2 $B \leftarrow B - x$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10347 \hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10348 \hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10349 7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10350 \hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10351 \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 \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10352 \hspace{6mm}7.2.1 $C \leftarrow C + y$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10353 \hspace{6mm}7.2.2 $D \leftarrow D - x$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10354 \hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10355 \hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10356 8. If $u \ge v$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10357 \hspace{3mm}8.1 $u \leftarrow u - v$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10358 \hspace{3mm}8.2 $A \leftarrow A - C$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10359 \hspace{3mm}8.3 $B \leftarrow B - D$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10360 9. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10361 \hspace{3mm}9.1 $v \leftarrow v - u$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10362 \hspace{3mm}9.2 $C \leftarrow C - A$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10363 \hspace{3mm}9.3 $D \leftarrow D - B$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10364 10. If $u \ne 0$ goto step 6. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10365 11. If $v \ne 1$ return(\textit{MP\_VAL}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10366 12. While $C \le 0$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10367 \hspace{3mm}12.1 $C \leftarrow C + b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10368 13. While $C \ge b$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10369 \hspace{3mm}13.1 $C \leftarrow C - b$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10370 14. $c \leftarrow C$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10371 15. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10372 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10373 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10374 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10375 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10376 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10377 \textbf{Algorithm mp\_invmod.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10378 This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10379 extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10380 Diophantine solution.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10381
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10382 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10383 inverse for $a$ and the error is reported.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10384
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10385 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10386 the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10387
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10388 \begin{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10389 Ca + Db = v
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10390 \end{equation}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10391
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10392 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10393 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10394 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10395 then only a couple of additions or subtractions will be required to adjust the inverse.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10396
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10397 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10398 \hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10399 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10400 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10401 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10402 017 /* hac 14.61, pp608 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10403 018 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10404 019 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10405 020 /* b cannot be negative */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10406 021 if (b->sign == MP_NEG || mp_iszero(b) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10407 022 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10408 023 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10409 024
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10410 025 #ifdef BN_FAST_MP_INVMOD_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10411 026 /* if the modulus is odd we can use a faster routine instead */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10412 027 if (mp_isodd (b) == 1) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10413 028 return fast_mp_invmod (a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10414 029 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10415 030 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10416 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10417 032 #ifdef BN_MP_INVMOD_SLOW_C
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10418 033 return mp_invmod_slow(a, b, c);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10419 034 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10420 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10421 036 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10422 037 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10423 038 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10424 039
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10425 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10426 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10427
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10428 \subsubsection{Odd Moduli}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10429
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10430 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10431 the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10432
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10433 The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10434 optimization will halve the time required to compute the modular inverse.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10435
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10436 \section{Primality Tests}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10437
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10438 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10439 since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10440
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10441 Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10442 not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10443 probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10444 prime the algorithm may be incorrect.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10445
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10446 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10447 well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10448
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10449 \subsection{Trial Division}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10450
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10451 Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10452 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10453 would require a prohibitive amount of time as $n$ grows.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10454
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10455 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10456 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10457
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10458 The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10459 discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10460 $1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10461 $3 \le q \le 100$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10462
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10463 At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10464 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10465 approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10466 array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10467
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10468 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10469 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10470 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10471 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10472 \hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10473 \textbf{Input}. mp\_int $a$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10474 \textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10475 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10476 1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10477 \hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10478 \hspace{3mm}1.2 If $d = 0$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10479 \hspace{6mm}1.2.1 $c \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10480 \hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10481 2. $c \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10482 3. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10483 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10484 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10485 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10486 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10487 \caption{Algorithm mp\_prime\_is\_divisible}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10488 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10489 \textbf{Algorithm mp\_prime\_is\_divisible.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10490 This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10491
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10492 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10493 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10494 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10495 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10496 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10497 017 /* determines if an integers is divisible by one
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10498 018 * of the first PRIME_SIZE primes or not
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10499 019 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10500 020 * sets result to 0 if not, 1 if yes
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10501 021 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10502 022 int mp_prime_is_divisible (mp_int * a, int *result)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10503 023 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10504 024 int err, ix;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10505 025 mp_digit res;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10506 026
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10507 027 /* default to not */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10508 028 *result = MP_NO;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10509 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10510 030 for (ix = 0; ix < PRIME_SIZE; ix++) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10511 031 /* what is a mod LBL_prime_tab[ix] */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10512 032 if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10513 033 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10514 034 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10515 035
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10516 036 /* is the residue zero? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10517 037 if (res == 0) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10518 038 *result = MP_YES;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10519 039 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10520 040 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10521 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10522 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10523 043 return MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10524 044 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10525 045 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10526 046
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10527 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10528 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10529
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10530 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10531 mp\_digit. The table \_\_prime\_tab is defined in the following file.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10532
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10533 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10534 \hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10535 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10536 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10537 016 const mp_digit ltm_prime_tab[] = \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10538 017 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10539 018 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10540 019 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10541 020 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10542 021 #ifndef MP_8BIT
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10543 022 0x0083,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10544 023 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10545 024 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10546 025 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10547 026 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10548 027
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10549 028 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10550 029 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10551 030 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10552 031 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10553 032 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10554 033 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10555 034 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10556 035 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10557 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10558 037 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10559 038 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10560 039 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10561 040 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10562 041 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10563 042 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10564 043 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10565 044 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10566 045
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10567 046 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10568 047 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10569 048 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10570 049 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10571 050 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10572 051 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10573 052 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10574 053 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10575 054 #endif
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10576 055 \};
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10577 056 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10578 057
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10579 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10580 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10581
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10582 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10583 upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10584
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10585 \subsection{The Fermat Test}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10586 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10587 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10588 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10589 $a^1 = a$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10590
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10591 If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10592 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10593 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10594 integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10595 in size.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10596
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10597 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10598 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10599 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10600 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10601 \hline Algorithm \textbf{mp\_prime\_fermat}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10602 \textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10603 \textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10604 \hline \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10605 1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10606 2. If $t = b$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10607 \hspace{3mm}2.1 $c = 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10608 3. else \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10609 \hspace{3mm}3.1 $c = 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10610 4. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10611 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10612 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10613 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10614 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10615 \caption{Algorithm mp\_prime\_fermat}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10616 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10617 \textbf{Algorithm mp\_prime\_fermat.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10618 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10619 determine the result.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10620
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10621 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10622 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10623 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10624 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10625 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10626 017 /* performs one Fermat test.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10627 018 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10628 019 * If "a" were prime then b**a == b (mod a) since the order of
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10629 020 * the multiplicative sub-group would be phi(a) = a-1. That means
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10630 021 * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10631 022 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10632 023 * Sets result to 1 if the congruence holds, or zero otherwise.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10633 024 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10634 025 int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10635 026 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10636 027 mp_int t;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10637 028 int err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10638 029
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10639 030 /* default to composite */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10640 031 *result = MP_NO;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10641 032
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10642 033 /* ensure b > 1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10643 034 if (mp_cmp_d(b, 1) != MP_GT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10644 035 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10645 036 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10646 037
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10647 038 /* init t */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10648 039 if ((err = mp_init (&t)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10649 040 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10650 041 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10651 042
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10652 043 /* compute t = b**a mod a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10653 044 if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10654 045 goto LBL_T;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10655 046 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10656 047
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10657 048 /* is it equal to b? */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10658 049 if (mp_cmp (&t, b) == MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10659 050 *result = MP_YES;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10660 051 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10661 052
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10662 053 err = MP_OKAY;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10663 054 LBL_T:mp_clear (&t);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10664 055 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10665 056 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10666 057 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10667 058
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10668 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10669 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10670
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10671 \subsection{The Miller-Rabin Test}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10672 The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10673 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10674 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10675 some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10676
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10677 \begin{figure}[!here]
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10678 \begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10679 \begin{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10680 \begin{tabular}{l}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10681 \hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10682 \textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10683 \textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10684 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10685 1. $a' \leftarrow a - 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10686 2. $r \leftarrow n1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10687 3. $c \leftarrow 0, s \leftarrow 0$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10688 4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10689 \hspace{3mm}4.1 $s \leftarrow s + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10690 \hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10691 5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10692 6. If $y \nequiv \pm 1$ then \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10693 \hspace{3mm}6.1 $j \leftarrow 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10694 \hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10695 \hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10696 \hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10697 \hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10698 \hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10699 7. $c \leftarrow 1$\\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10700 8. Return(\textit{MP\_OKAY}). \\
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10701 \hline
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10702 \end{tabular}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10703 \end{center}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10704 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10705 \caption{Algorithm mp\_prime\_miller\_rabin}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10706 \end{figure}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10707 \textbf{Algorithm mp\_prime\_miller\_rabin.}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10708 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10709 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$.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10710
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10711 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10712 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$
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10713 is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10714 composite then it is \textit{probably} prime.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10715
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10716 \vspace{+3mm}\begin{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10717 \hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10718 \vspace{-3mm}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10719 \begin{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10720 016
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10721 017 /* Miller-Rabin test of "a" to the base of "b" as described in
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10722 018 * HAC pp. 139 Algorithm 4.24
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10723 019 *
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10724 020 * Sets result to 0 if definitely composite or 1 if probably prime.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10725 021 * Randomly the chance of error is no more than 1/4 and often
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10726 022 * very much lower.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10727 023 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10728 024 int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10729 025 \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10730 026 mp_int n1, y, r;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10731 027 int s, j, err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10732 028
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10733 029 /* default */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10734 030 *result = MP_NO;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10735 031
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10736 032 /* ensure b > 1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10737 033 if (mp_cmp_d(b, 1) != MP_GT) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10738 034 return MP_VAL;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10739 035 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10740 036
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10741 037 /* get n1 = a - 1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10742 038 if ((err = mp_init_copy (&n1, a)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10743 039 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10744 040 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10745 041 if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10746 042 goto LBL_N1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10747 043 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10748 044
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10749 045 /* set 2**s * r = n1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10750 046 if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10751 047 goto LBL_N1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10752 048 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10753 049
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10754 050 /* count the number of least significant bits
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10755 051 * which are zero
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10756 052 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10757 053 s = mp_cnt_lsb(&r);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10758 054
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10759 055 /* now divide n - 1 by 2**s */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10760 056 if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10761 057 goto LBL_R;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10762 058 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10763 059
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10764 060 /* compute y = b**r mod a */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10765 061 if ((err = mp_init (&y)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10766 062 goto LBL_R;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10767 063 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10768 064 if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10769 065 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10770 066 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10771 067
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10772 068 /* if y != 1 and y != n1 do */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10773 069 if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10774 070 j = 1;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10775 071 /* while j <= s-1 and y != n1 */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10776 072 while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10777 073 if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10778 074 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10779 075 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10780 076
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10781 077 /* if y == 1 then composite */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10782 078 if (mp_cmp_d (&y, 1) == MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10783 079 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10784 080 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10785 081
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10786 082 ++j;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10787 083 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10788 084
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10789 085 /* if y != n1 then composite */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10790 086 if (mp_cmp (&y, &n1) != MP_EQ) \{
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10791 087 goto LBL_Y;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10792 088 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10793 089 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10794 090
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10795 091 /* probably prime now */
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10796 092 *result = MP_YES;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10797 093 LBL_Y:mp_clear (&y);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10798 094 LBL_R:mp_clear (&r);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10799 095 LBL_N1:mp_clear (&n1);
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10800 096 return err;
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10801 097 \}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10802 098 #endif
386
97db060d0ef5 Update to LibTomMath 0.40
Matt Johnston <matt@ucc.asn.au>
parents: 282
diff changeset
10803 099
282
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10804 \end{alltt}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10805 \end{small}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10806
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10807
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10808
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10809
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10810 \backmatter
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10811 \appendix
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10812 \begin{thebibliography}{ABCDEF}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10813 \bibitem[1]{TAOCPV2}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10814 Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10815
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10816 \bibitem[2]{HAC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10817 A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10818
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10819 \bibitem[3]{ROSE}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10820 Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10821
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10822 \bibitem[4]{COMBA}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10823 Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10824
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10825 \bibitem[5]{KARA}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10826 A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10827
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10828 \bibitem[6]{KARAP}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10829 Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10830
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10831 \bibitem[7]{BARRETT}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10832 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.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10833
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10834 \bibitem[8]{MONT}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10835 P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985.
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10836
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10837 \bibitem[9]{DRMET}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10838 Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10839
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10840 \bibitem[10]{MMB}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10841 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
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10842
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10843 \bibitem[11]{RSAREF}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10844 R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10845
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10846 \bibitem[12]{DHREF}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10847 Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10848
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10849 \bibitem[13]{IEEE}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10850 IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985)
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10851
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10852 \bibitem[14]{GMP}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10853 GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10854
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10855 \bibitem[15]{MPI}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10856 Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10857
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10858 \bibitem[16]{OPENSSL}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10859 OpenSSL Cryptographic Toolkit, \url{http://openssl.org}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10860
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10861 \bibitem[17]{LIP}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10862 Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10863
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10864 \bibitem[18]{ISOC}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10865 JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.''
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10866
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10867 \bibitem[19]{JAVA}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10868 The Sun Java Website, \url{http://java.sun.com/}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10869
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10870 \end{thebibliography}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10871
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10872 \input{tommath.ind}
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10873
91fbc376f010 Import of libtommath 0.35
Matt Johnston <matt@ucc.asn.au>
parents:
diff changeset
10874 \end{document}