📄 tommath.src
字号:
when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means thata subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In eachiteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occuredthe loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate decrementally.EXAM,bn_mp_init.cOne immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The call to mp\_init() is used only to initialize the members of the structure to a known default state. Here we see (line @23,XMALLOC@) the memory allocation is performed first. This allows us to exit cleanly and quicklyif there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate therewas a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a functionbut a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--inmemory allocation routine.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 beenaccomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a portable fashion you have to actually assign the value. The for loop (line @28,for@) performs this requiredoperation.After the memory has been successfully initialized the remainder of the members are initialized (lines @29,used@ through @31,sign@) to their respective default states. At this point the algorithm has succeeded anda success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the mp\_int structure has been properly initialized and is safe to use with other functions within the library. \subsection{Clearing an mp\_int}When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be returned to the application's memory pool with the mp\_clear algorithm.\begin{figure}[here]\begin{center}\begin{tabular}{l}\hline Algorithm \textbf{mp\_clear}. \\\textbf{Input}. An mp\_int $a$ \\\textbf{Output}. The memory for $a$ shall be deallocated. \\\hline \\1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\2. for $n$ from 0 to $a.used - 1$ do \\\hspace{3mm}2.1 $a_n \leftarrow 0$ \\3. Free the memory allocated for the digits of $a$. \\4. $a.used \leftarrow 0$ \\5. $a.alloc \leftarrow 0$ \\6. $a.sign \leftarrow MP\_ZPOS$ \\7. Return(\textit{MP\_OKAY}). \\\hline\end{tabular}\end{center}\caption{Algorithm mp\_clear}\end{figure}\textbf{Algorithm mp\_clear.}This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goalis to free the allocated memory.The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to thisalgorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid digit pointer \textbf{dp} setting.Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithmwith the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear.EXAM,bn_mp_clear.cThe algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line @23,a->dp != NULL@)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\textbf{NULL} in which case the if statement will evaluate to true.The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit. Similar to mp\_init()the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable. The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates toa standard C library function. In this case the free() function. Since free() only deallocates the memory the pointerstill has to be reset to \textbf{NULL} manually (line @33,NULL@). Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@).\section{Maintenance Algorithms}The previous sections describes how to initialize and clear an mp\_int structure. To further support operationsthat are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must beable to augment the precision of an mp\_int and initialize mp\_ints with differing initial conditions. These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher levelalgorithms such as addition, multiplication and modular exponentiation.\subsection{Augmenting an mp\_int's Precision}When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality.\newpage\begin{figure}[here]\begin{center}\begin{tabular}{l}\hline Algorithm \textbf{mp\_grow}. \\\textbf{Input}. An mp\_int $a$ and an integer $b$. \\\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\\hline \\1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\4. Re-allocate the array of digits $a$ to size $v$ \\5. If the allocation failed then return(\textit{MP\_MEM}). \\6. for n from a.alloc to $v - 1$ do \\\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\7. $a.alloc \leftarrow v$ \\8. Return(\textit{MP\_OKAY}) \\\hline\end{tabular}\end{center}\caption{Algorithm mp\_grow}\end{figure}\textbf{Algorithm mp\_grow.}It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow. The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three). This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values. It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are assumed to contain undefined values they are initially set to zero.EXAM,bn_mp_grow.cA quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line @23,if@) checksif the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc}the function skips the re-allocation part thus saving time.When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count ispadded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@). The XREALLOC function is usedto re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The reallocfunction leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as beforethe re-allocation. All that is left is to clear the newly allocated digits and return.Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to returnan error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That wouldresult in a memory leak if XREALLOC ever failed. \subsection{Initializing Variable Precision mp\_ints}Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it will allocate \textit{at least} a specified number of digits. \begin{figure}[here]\begin{small}\begin{center}\begin{tabular}{l}\hline Algorithm \textbf{mp\_init\_size}. \\\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\\hline \\1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\3. Allocate $v$ digits. \\4. for $n$ from $0$ to $v - 1$ do \\\hspace{3mm}4.1 $a_n \leftarrow 0$ \\5. $a.sign \leftarrow MP\_ZPOS$\\6. $a.used \leftarrow 0$\\7. $a.alloc \leftarrow v$\\8. Return(\textit{MP\_OKAY})\\\hline\end{tabular}\end{center}\end{small}\caption{Algorithm mp\_init\_size}\end{figure}\textbf{Algorithm mp\_init\_size.}This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial allocations from becoming a bottleneck in the rest of the algorithms.Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation iscorrect no further memory re-allocations are required to work with the mp\_int.EXAM,bn_mp_init_size.cThe number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of \textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be returned (line @27,return@). The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The \textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@). If the function returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the functions to work with.\subsection{Multiple Integer Initializations and Clearings}Occasionally a function will require a series of mp\_int data types to be made available simultaneously. The purpose of algorithm mp\_i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -