chiark / gitweb /
Pile of changes for supporting two's complement properly.
[catacomb] / mp-io.c
1 /* -*-c-*-
2  *
3  * $Id: mp-io.c,v 1.5 2002/10/06 22:52:50 mdw Exp $
4  *
5  * Loading and storing of multiprecision integers
6  *
7  * (c) 1999 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Catacomb.
13  *
14  * Catacomb is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  * 
19  * Catacomb is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  * 
24  * You should have received a copy of the GNU Library General Public
25  * License along with Catacomb; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: mp-io.c,v $
33  * Revision 1.5  2002/10/06 22:52:50  mdw
34  * Pile of changes for supporting two's complement properly.
35  *
36  * Revision 1.4  2000/06/17 11:45:09  mdw
37  * Major memory management overhaul.  Added arena support.  Use the secure
38  * arena for secret integers.  Replace and improve the MP management macros
39  * (e.g., replace MP_MODIFY by MP_DEST).
40  *
41  * Revision 1.3  1999/11/21 22:13:02  mdw
42  * Add mp version of MPX_BITS.
43  *
44  * Revision 1.2  1999/11/19 13:19:06  mdw
45  * Set flags on results correctly.
46  *
47  * Revision 1.1  1999/11/17 18:02:16  mdw
48  * New multiprecision integer arithmetic suite.
49  *
50  */
51
52 /*----- Header files ------------------------------------------------------*/
53
54 #include "mp.h"
55
56 /*----- Main code ---------------------------------------------------------*/
57
58 /* --- @mp_octets@ --- *
59  *
60  * Arguments:   @const mp *m@ = a multiprecision integer
61  *
62  * Returns:     The number of octets required to represent @m@.
63  *
64  * Use:         Calculates the external storage required for a multiprecision
65  *              integer.
66  */
67
68 size_t mp_octets(const mp *m)
69 {
70   size_t sz;
71   MPX_OCTETS(sz, m->v, m->vl);
72   return (sz);
73 }
74
75 /* --- @mp_octets2c@ --- *
76  *
77  * Arguments:   @const mp *m@ = a multiprecision integer
78  *
79  * Returns:     The number of octets required to represent @m@.
80  *
81  * Use:         Calculates the external storage required for a multiprecision
82  *              integer represented as two's complement.
83  */
84
85 size_t mp_octets2c(const mp *m)
86 {
87   size_t sz;
88   MPX_OCTETS2C(sz, m->v, m->vl);
89   return (sz);
90 }
91
92 /* --- @mp_bits@ --- *
93  *
94  * Arguments:   @const mp *m@ = a multiprecision integer
95  *
96  * Returns:     The number of bits required to represent @m@.
97  *
98  * Use:         Calculates the external storage required for a multiprecision
99  *              integer.
100  */
101
102 unsigned long mp_bits(const mp *m)
103 {
104   unsigned long bits;
105   MPX_BITS(bits, m->v, m->vl);
106   return (bits);
107 }
108
109 /* --- @mp_loadl@ --- *
110  *
111  * Arguments:   @mp *d@ = destination
112  *              @const void *pv@ = pointer to source data
113  *              @size_t sz@ = size of the source data
114  *
115  * Returns:     Resulting multiprecision number.
116  *
117  * Use:         Loads a multiprecision number from an array of octets.  The
118  *              first byte in the array is the least significant.  More
119  *              formally, if the bytes are %$b_0, b_1, \ldots, b_{n-1}$%
120  *              then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
121  */
122
123 mp *mp_loadl(mp *d, const void *pv, size_t sz)
124 {
125   MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
126   mpx_loadl(d->v, d->vl, pv, sz);
127   d->f &= ~(MP_UNDEF | MP_NEG);
128   mp_shrink(d);
129   return (d);
130 }
131
132 /* --- @mp_storel@ --- *
133  *
134  * Arguments:   @const mp *m@ = source
135  *              @void *pv@ = pointer to output array
136  *              @size_t sz@ = size of the output array
137  *
138  * Returns:     ---
139  *
140  * Use:         Stores a multiprecision number in an array of octets.  The
141  *              first byte in the array is the least significant.  If the
142  *              array is too small to represent the number, high-order bits
143  *              are truncated; if the array is too large, high order bytes
144  *              are filled with zeros.  More formally, if the number is
145  *              %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
146  *              then the array is %$b_0, b_1, \ldots, b_{n-1}$%.
147  */
148
149 void mp_storel(const mp *m, void *pv, size_t sz)
150 {
151   mpx_storel(m->v, m->vl, pv, sz);
152 }
153
154 /* --- @mp_loadb@ --- *
155  *
156  * Arguments:   @mp *d@ = destination
157  *              @const void *pv@ = pointer to source data
158  *              @size_t sz@ = size of the source data
159  *
160  * Returns:     Resulting multiprecision number.
161  *
162  * Use:         Loads a multiprecision number from an array of octets.  The
163  *              last byte in the array is the least significant.  More
164  *              formally, if the bytes are %$b_{n-1}, b_{n-2}, \ldots, b_0$%
165  *              then the result is %$N = \sum_{0 \le i < n} b_i 2^{8i}$%.
166  */
167
168 mp *mp_loadb(mp *d, const void *pv, size_t sz)
169 {
170   MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
171   mpx_loadb(d->v, d->vl, pv, sz);
172   d->f &= ~(MP_UNDEF | MP_NEG);
173   mp_shrink(d);
174   return (d);
175 }
176
177 /* --- @mp_storeb@ --- *
178  *
179  * Arguments:   @const mp *m@ = source
180  *              @void *pv@ = pointer to output array
181  *              @size_t sz@ = size of the output array
182  *
183  * Returns:     ---
184  *
185  * Use:         Stores a multiprecision number in an array of octets.  The
186  *              last byte in the array is the least significant.  If the
187  *              array is too small to represent the number, high-order bits
188  *              are truncated; if the array is too large, high order bytes
189  *              are filled with zeros.  More formally, if the number is
190  *              %$N = \sum{0 \le i} b_i 2^{8i}$% where %$0 \le b_i < 256$%,
191  *              then the array is %$b_{n-1}, b_{n-2}, \ldots, b_0$%.
192  */
193
194 void mp_storeb(const mp *m, void *pv, size_t sz)
195 {
196   mpx_storeb(m->v, m->vl, pv, sz);
197 }
198
199 /* --- @mp_loadl2c@ --- *
200  *
201  * Arguments:   @mp *d@ = destination
202  *              @const void *pv@ = pointer to source data
203  *              @size_t sz@ = size of the source data
204  *
205  * Returns:     Resulting multiprecision number.
206  *
207  * Use:         Loads a multiprecision number from an array of octets as
208  *              two's complement.  The first byte in the array is the least
209  *              significant.
210  */
211
212 mp *mp_loadl2c(mp *d, const void *pv, size_t sz)
213 {
214   const octet *ov = pv;
215   MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
216   if (!sz || !(ov[sz - 1] & 0x80)) {
217     mpx_loadl(d->v, d->vl, pv, sz);
218     d->f &= ~MP_NEG;
219   } else {
220     mpx_loadl2cn(d->v, d->vl, pv, sz);
221     d->f |= MP_NEG;
222   }
223   d->f &= ~MP_UNDEF;
224   mp_shrink(d);
225   return (d);
226 }
227
228 /* --- @mp_storel2c@ --- *
229  *
230  * Arguments:   @const mp *m@ = source
231  *              @void *pv@ = pointer to output array
232  *              @size_t sz@ = size of the output array
233  *
234  * Returns:     ---
235  *
236  * Use:         Stores a multiprecision number in an array of octets as two's
237  *              complement.  The first byte in the array is the least
238  *              significant.  If the array is too small to represent the
239  *              number, high-order bits are truncated; if the array is too
240  *              large, high order bytes are sign-extended.
241  */
242
243 void mp_storel2c(const mp *m, void *pv, size_t sz)
244 {
245   if (m->f & MP_NEG)
246     mpx_storel2cn(m->v, m->vl, pv, sz);
247   else
248     mpx_storel(m->v, m->vl, pv, sz);
249 }
250
251 /* --- @mp_loadb2c@ --- *
252  *
253  * Arguments:   @mp *d@ = destination
254  *              @const void *pv@ = pointer to source data
255  *              @size_t sz@ = size of the source data
256  *
257  * Returns:     Resulting multiprecision number.
258  *
259  * Use:         Loads a multiprecision number from an array of octets as
260  *              two's complement.  The last byte in the array is the least
261  *              significant.
262  */
263
264 mp *mp_loadb2c(mp *d, const void *pv, size_t sz)
265 {
266   const octet *ov = pv;
267   MP_DEST(d, MPW_RQ(sz), MP_UNDEF);
268   if (!sz || !(ov[0] & 0x80)) {
269     mpx_loadl(d->v, d->vl, pv, sz);
270     d->f &= ~MP_NEG;
271   } else {
272     mpx_loadl2cn(d->v, d->vl, pv, sz);
273     d->f |= MP_NEG;
274   }
275   d->f &= ~MP_UNDEF;
276   mp_shrink(d);
277   return (d);
278 }
279
280 /* --- @mp_storeb2c@ --- *
281  *
282  * Arguments:   @const mp *m@ = source
283  *              @void *pv@ = pointer to output array
284  *              @size_t sz@ = size of the output array
285  *
286  * Returns:     ---
287  *
288  * Use:         Stores a multiprecision number in an array of octets, as
289  *              two's complement.  The last byte in the array is the least
290  *              significant.  If the array is too small to represent the
291  *              number, high-order bits are truncated; if the array is too
292  *              large, high order bytes are sign-extended.
293  */
294
295 void mp_storeb2c(const mp *m, void *pv, size_t sz)
296 {
297   if (m->f & MP_NEG)
298     mpx_storeb2cn(m->v, m->vl, pv, sz);
299   else
300     mpx_storeb(m->v, m->vl, pv, sz);
301 }
302
303 /*----- That's all, folks -------------------------------------------------*/