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