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 12273458 : _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 12273458 : x = *s1_ptr++;
49 12273458 : s2_limb += x;
50 12273458 : *res_ptr++ = s2_limb;
51 12273458 : if( s2_limb < x ) { /* sum is less than the left operand: handle carry */
52 965 : while( --s1_size ) {
53 810 : x = *s1_ptr++ + 1; /* add carry */
54 810 : *res_ptr++ = x; /* and store */
55 810 : if( x ) /* not 0 (no overflow): we can stop */
56 155 : goto leave;
57 : }
58 0 : return 1; /* return carry (size of s1 to small) */
59 : }
60 :
61 : leave:
62 12273458 : if( res_ptr != s1_ptr ) { /* not the same variable */
63 : mpi_size_t i; /* copy the rest */
64 1972885 : for( i=0; i < s1_size-1; i++ )
65 1644236 : res_ptr[i] = s1_ptr[i];
66 : }
67 12273458 : return 0; /* no carry */
68 : }
69 :
70 :
71 :
72 : G10_MPI_INLINE_DECL mpi_limb_t
73 10717726 : _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 10717726 : mpi_limb_t cy = 0;
77 :
78 10717726 : if( s2_size )
79 10717726 : cy = _gcry_mpih_add_n( res_ptr, s1_ptr, s2_ptr, s2_size );
80 :
81 10717726 : if( s1_size - s2_size )
82 125211 : cy = _gcry_mpih_add_1( res_ptr + s2_size, s1_ptr + s2_size,
83 : s1_size - s2_size, cy);
84 10717726 : return cy;
85 : }
86 :
87 :
88 : G10_MPI_INLINE_DECL mpi_limb_t
89 1096440 : _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 1096440 : x = *s1_ptr++;
95 1096440 : s2_limb = x - s2_limb;
96 1096440 : *res_ptr++ = s2_limb;
97 1096440 : if( s2_limb > x ) {
98 90 : while( --s1_size ) {
99 45 : x = *s1_ptr++;
100 45 : *res_ptr++ = x - 1;
101 45 : if( x )
102 43 : goto leave;
103 : }
104 1 : return 1;
105 : }
106 :
107 : leave:
108 1096439 : if( res_ptr != s1_ptr ) {
109 : mpi_size_t i;
110 3419498 : for( i=0; i < s1_size-1; i++ )
111 2332278 : res_ptr[i] = s1_ptr[i];
112 : }
113 1096439 : return 0;
114 : }
115 :
116 :
117 :
118 : G10_MPI_INLINE_DECL mpi_limb_t
119 1076983 : _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 1076983 : mpi_limb_t cy = 0;
123 :
124 1076983 : if( s2_size )
125 1076983 : cy = _gcry_mpih_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
126 :
127 1076983 : if( s1_size - s2_size )
128 1076983 : cy = _gcry_mpih_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
129 : s1_size - s2_size, cy);
130 1076983 : 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 60088949 : _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 65319980 : for( i = size - 1; i >= 0 ; i--) {
146 65256975 : op1_word = op1_ptr[i];
147 65256975 : op2_word = op2_ptr[i];
148 65256975 : if( op1_word != op2_word )
149 60025944 : goto diff;
150 : }
151 63005 : 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 60025944 : return (op1_word > op2_word) ? 1 : -1;
158 : }
159 :
160 :
161 : #endif /*G10_MPI_INLINE_H*/
|