Line data Source code
1 : /* mpi-inline.h - Internal to the Multi Precision Integers
2 : * Copyright (C) 1994, 1996, 1998, 1999,
3 : * 2001, 2002 Free Software Foundation, Inc.
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, write to the Free Software
19 : * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 : *
21 : * Note: This code is heavily based on the GNU MP Library.
22 : * Actually it's the same code with only minor changes in the
23 : * way the data is stored; this is to support the abstraction
24 : * of an optional secure memory allocation which may be used
25 : * to avoid revealing of sensitive data due to paging etc.
26 : */
27 :
28 : #ifndef G10_MPI_INLINE_H
29 : #define G10_MPI_INLINE_H
30 :
31 : /* Starting with gcc 4.3 "extern inline" conforms in c99 mode to the
32 : c99 semantics. To keep the useful old semantics we use an
33 : attribute. */
34 : #ifndef G10_MPI_INLINE_DECL
35 : # ifdef __GNUC_STDC_INLINE__
36 : # define G10_MPI_INLINE_DECL extern inline __attribute__ ((__gnu_inline__))
37 : # else
38 : # define G10_MPI_INLINE_DECL extern __inline__
39 : # endif
40 : #endif
41 :
42 : G10_MPI_INLINE_DECL mpi_limb_t
43 3983429 : _gcry_mpih_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
44 : mpi_size_t s1_size, mpi_limb_t s2_limb)
45 : {
46 : mpi_limb_t x;
47 :
48 3983429 : x = *s1_ptr++;
49 3983429 : s2_limb += x;
50 3983429 : *res_ptr++ = s2_limb;
51 3983429 : if( s2_limb < x ) { /* sum is less than the left operand: handle carry */
52 965 : while( --s1_size ) {
53 813 : x = *s1_ptr++ + 1; /* add carry */
54 813 : *res_ptr++ = x; /* and store */
55 813 : if( x ) /* not 0 (no overflow): we can stop */
56 152 : goto leave;
57 : }
58 0 : return 1; /* return carry (size of s1 to small) */
59 : }
60 :
61 : leave:
62 3983429 : if( res_ptr != s1_ptr ) { /* not the same variable */
63 : mpi_size_t i; /* copy the rest */
64 239558 : for( i=0; i < s1_size-1; i++ )
65 158772 : res_ptr[i] = s1_ptr[i];
66 : }
67 3983429 : return 0; /* no carry */
68 : }
69 :
70 :
71 :
72 : G10_MPI_INLINE_DECL mpi_limb_t
73 10008100 : _gcry_mpih_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
74 : mpi_ptr_t s2_ptr, mpi_size_t s2_size)
75 : {
76 10008100 : mpi_limb_t cy = 0;
77 :
78 10008100 : if( s2_size )
79 10008100 : cy = _gcry_mpih_add_n( res_ptr, s1_ptr, s2_ptr, s2_size );
80 :
81 10008100 : if( s1_size - s2_size )
82 67494 : cy = _gcry_mpih_add_1( res_ptr + s2_size, s1_ptr + s2_size,
83 : s1_size - s2_size, cy);
84 10008100 : return cy;
85 : }
86 :
87 :
88 : G10_MPI_INLINE_DECL mpi_limb_t
89 949030 : _gcry_mpih_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
90 : mpi_size_t s1_size, mpi_limb_t s2_limb )
91 : {
92 : mpi_limb_t x;
93 :
94 949030 : x = *s1_ptr++;
95 949030 : s2_limb = x - s2_limb;
96 949030 : *res_ptr++ = s2_limb;
97 949030 : if( s2_limb > x ) {
98 86 : while( --s1_size ) {
99 43 : x = *s1_ptr++;
100 43 : *res_ptr++ = x - 1;
101 43 : if( x )
102 43 : goto leave;
103 : }
104 0 : return 1;
105 : }
106 :
107 : leave:
108 949030 : if( res_ptr != s1_ptr ) {
109 : mpi_size_t i;
110 2678679 : for( i=0; i < s1_size-1; i++ )
111 1736783 : res_ptr[i] = s1_ptr[i];
112 : }
113 949030 : return 0;
114 : }
115 :
116 :
117 :
118 : G10_MPI_INLINE_DECL mpi_limb_t
119 981047 : _gcry_mpih_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
120 : mpi_ptr_t s2_ptr, mpi_size_t s2_size)
121 : {
122 981047 : mpi_limb_t cy = 0;
123 :
124 981047 : if( s2_size )
125 981047 : cy = _gcry_mpih_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
126 :
127 981047 : if( s1_size - s2_size )
128 936127 : cy = _gcry_mpih_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
129 : s1_size - s2_size, cy);
130 981047 : return cy;
131 : }
132 :
133 : /****************
134 : * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
135 : * There are no restrictions on the relative sizes of
136 : * the two arguments.
137 : * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2.
138 : */
139 : G10_MPI_INLINE_DECL int
140 30545546 : _gcry_mpih_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size )
141 : {
142 : mpi_size_t i;
143 : mpi_limb_t op1_word, op2_word;
144 :
145 32826785 : for( i = size - 1; i >= 0 ; i--) {
146 32792970 : op1_word = op1_ptr[i];
147 32792970 : op2_word = op2_ptr[i];
148 32792970 : if( op1_word != op2_word )
149 30511731 : goto diff;
150 : }
151 33815 : return 0;
152 :
153 : diff:
154 : /* This can *not* be simplified to
155 : * op2_word - op2_word
156 : * since that expression might give signed overflow. */
157 30511731 : return (op1_word > op2_word) ? 1 : -1;
158 : }
159 :
160 :
161 : #endif /*G10_MPI_INLINE_H*/
|