📄 bn.tex
字号:
mp_mul(&a, &a, &c); /* c = a * a */mp_div(&a, &b, &c, &d); /* c = [a/b], d = a mod b */\end{alltt}Another feature of the way the functions have been implemented is that source operands can be destination operands as well.For instance,\begin{alltt}mp_add(&a, &b, &b); /* b = a + b */mp_div(&a, &b, &a, &c); /* a = [a/b], c = a mod b */\end{alltt}This allows operands to be re-used which can make programming simpler.\section{Initialization}\subsection{Single Initialization}A single mp\_int can be initialized with the ``mp\_init'' function. \index{mp\_init}\begin{alltt}int mp_init (mp_int * a);\end{alltt}This function expects a pointer to an mp\_int structure and will initialize the members of the structure so the mp\_intrepresents the default integer which is zero. If the functions returns MP\_OKAY then the mp\_int is ready to be usedby the other LibTomMath functions.\begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number */ return EXIT_SUCCESS;\}\end{alltt} \end{small}\subsection{Single Free}When you are finished with an mp\_int it is ideal to return the heap it used back to the system. The following function provides this functionality.\index{mp\_clear}\begin{alltt}void mp_clear (mp_int * a);\end{alltt}The function expects a pointer to a previously initialized mp\_int structure and frees the heap it uses. It sets the pointer\footnote{The ``dp'' member.} within the mp\_int to \textbf{NULL} which is used to prevent double free situations. Is is legal to call mp\_clear() twice on the same mp\_int in a row. \begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number */ /* We're done with it. */ mp_clear(&number); return EXIT_SUCCESS;\}\end{alltt} \end{small}\subsection{Multiple Initializations}Certain algorithms require more than one large integer. In these instances it is ideal to initialize all of the mp\_intvariables in an ``all or nothing'' fashion. That is, they are either all initialized successfully or they are allnot initialized.The mp\_init\_multi() function provides this functionality.\index{mp\_init\_multi} \index{mp\_clear\_multi}\begin{alltt}int mp_init_multi(mp_int *mp, ...);\end{alltt}It accepts a \textbf{NULL} terminated list of pointers to mp\_int structures. It will attempt to initialize them allat once. If the function returns MP\_OKAY then all of the mp\_int variables are ready to use, otherwise none of themare available for use. A complementary mp\_clear\_multi() function allows multiple mp\_int variables to be free'd from the heap at the same time. \begin{small} \begin{alltt}int main(void)\{ mp_int num1, num2, num3; int result; if ((result = mp_init_multi(&num1, &num2, &num3, NULL)) != MP\_OKAY) \{ printf("Error initializing the numbers. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the numbers */ /* We're done with them. */ mp_clear_multi(&num1, &num2, &num3, NULL); return EXIT_SUCCESS;\}\end{alltt} \end{small}\subsection{Other Initializers}To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided. \index{mp\_init\_copy}\begin{alltt}int mp_init_copy (mp_int * a, mp_int * b);\end{alltt}This function will initialize $a$ and make it a copy of $b$ if all goes well.\begin{small} \begin{alltt}int main(void)\{ mp_int num1, num2; int result; /* initialize and do work on num1 ... */ /* We want a copy of num1 in num2 now */ if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{ printf("Error initializing the copy. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* now num2 is ready and contains a copy of num1 */ /* We're done with them. */ mp_clear_multi(&num1, &num2, NULL); return EXIT_SUCCESS;\}\end{alltt} \end{small}Another less common initializer is mp\_init\_size() which allows the user to initialize an mp\_int with a givendefault number of digits. By default, all initializers allocate \textbf{MP\_PREC} digits. This function letsyou override this behaviour.\index{mp\_init\_size}\begin{alltt}int mp_init_size (mp_int * a, int size);\end{alltt}The $size$ parameter must be greater than zero. If the function succeeds the mp\_int $a$ will be initializedto have $size$ digits (which are all initially zero). \begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; /* we need a 60-digit number */ if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number */ return EXIT_SUCCESS;\}\end{alltt} \end{small}\section{Maintenance Functions}\subsection{Reducing Memory Usage}When an mp\_int is in a state where it won't be changed again\footnote{A Diffie-Hellman modulus for instance.} excessdigits can be removed to return memory to the heap with the mp\_shrink() function.\index{mp\_shrink}\begin{alltt}int mp_shrink (mp_int * a);\end{alltt}This will remove excess digits of the mp\_int $a$. If the operation fails the mp\_int should be intact without theexcess digits being removed. Note that you can use a shrunk mp\_int in further computations, however, such operationswill require heap operations which can be slow. It is not ideal to shrink mp\_int variables that you will furthermodify in the system (unless you are seriously low on memory). \begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number [e.g. pre-computation] */ /* We're done with it for now. */ if ((result = mp_shrink(&number)) != MP_OKAY) \{ printf("Error shrinking the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use it .... */ /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS;\}\end{alltt} \end{small}\subsection{Adding additional digits}Within the mp\_int structure are two parameters which control the limitations of the array of digits that representthe integer the mp\_int is meant to equal. The \textit{used} parameter dictates how many digits are significant, that is,contribute to the value of the mp\_int. The \textit{alloc} parameter dictates how many digits are currently available inthe array. If you need to perform an operation that requires more digits you will have to mp\_grow() the mp\_int toyour desired size. \index{mp\_grow}\begin{alltt}int mp_grow (mp_int * a, int size);\end{alltt}This will grow the array of digits of $a$ to $size$. If the \textit{alloc} parameter is already bigger than$size$ the function will not do anything.\begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number */ /* We need to add 20 digits to the number */ if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{ printf("Error growing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* use the number */ /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS;\}\end{alltt} \end{small}\chapter{Basic Operations}\section{Small Constants}Setting mp\_ints to small constants is a relatively common operation. To accomodate these instances there are twosmall constant assignment functions. The first function is used to set a single digit constant while the second setsan ISO C style ``unsigned long'' constant. The reason for both functions is efficiency. Setting a single digit is quick but thedomain of a digit can change (it's always at least $0 \ldots 127$). \subsection{Single Digit}Setting a single digit can be accomplished with the following function.\index{mp\_set}\begin{alltt}void mp_set (mp_int * a, mp_digit b);\end{alltt}This will zero the contents of $a$ and make it represent an integer equal to the value of $b$. Note that thisfunction has a return type of \textbf{void}. It cannot cause an error so it is safe to assume the functionsucceeded.\begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* set the number to 5 */ mp_set(&number, 5); /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS;\}\end{alltt} \end{small}\subsection{Long Constants}To set a constant that is the size of an ISO C ``unsigned long'' and larger than a single digit the following function can be used.\index{mp\_set\_int}\begin{alltt}int mp_set_int (mp_int * a, unsigned long b);\end{alltt}This will assign the value of the 32-bit variable $b$ to the mp\_int $a$. Unlike mp\_set() this function will alwaysaccept a 32-bit input regardless of the size of a single digit. However, since the value may span several digits this function can fail if it runs out of heap memory.To get the ``unsigned long'' copy of an mp\_int the following function can be used.\index{mp\_get\_int}\begin{alltt}unsigned long mp_get_int (mp_int * a);\end{alltt}This will return the 32 least significant bits of the mp\_int $a$. \begin{small} \begin{alltt}int main(void)\{ mp_int number; int result; if ((result = mp_init(&number)) != MP_OKAY) \{ printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* set the number to 654321 (note this is bigger than 127) */ if ((result = mp_set_int(&number, 654321)) != MP_OKAY) \{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -