source: git/MP/MP/MP_SacBigInt.c @ 22b156

fieker-DuValspielwiese
Last change on this file since 22b156 was 341696, checked in by Hans Schönemann <hannes@…>, 15 years ago
Adding Id property to all files git-svn-id: file:///usr/local/Singular/svn/trunk@12231 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.2 KB
Line 
1/*******************************************************************
2 *                                                                 
3 *                    MP version 1.1.2:  Multi Protocol
4 *                    Kent State University, Kent, OH
5 *                 Authors:  S. Gray, N. Kajler, P. Wang
6 *          (C) 1993, 1994, 1995, 1996, 1997 All Rights Reserved
7 *
8 *                                 NOTICE
9 *
10 *  Permission to use, copy, modify, and distribute this software and
11 *  its documentation for non-commercial purposes and without fee is
12 *  hereby granted provided that the above copyright notice appear in all
13 *  copies and that both the copyright notice and this permission notice
14 *  appear in supporting documentation.
15 * 
16 *  Neither Kent State University nor the Authors make any representations
17 *  about the suitability of this software for any purpose.  The MP Library
18 *  is distributed in the hope that it will be useful, but is provided  "as
19 *  is" and without any warranty of any kind and without even the implied 
20 *  warranty of merchantability or fitness for a particular purpose.
21 *
22 *    IMPORTANT ADDITION: as of September 2006, MP is also licenced under GPL
23 *
24 *   IMPLEMENTATION FILE:  MP_SacBigInt.c
25 *
26 *      The default BigInt package is the Gnu Multiple Precision
27 *      package.  Here we have the routines to put/get/print a SAC bigint
28 *      and to convert between the SAC and GMP bigints.
29 *
30 *   NOTE: This is a short explanation of the the way MP deals with
31 *         arbtrary precision numbers.  For now this really only applies
32 *         to Big Ints. When the sender and receiver are using the same
33 *         format, we don't want to force them to have to convert to a
34 *         common format to do the exchange.  So we provide conversion
35 *         routines for some common formats (SAC <-> GMP, PARI <-> GMP).
36 *         The BigNum format to be used is characterized by routines to
37 *         Put(), Get(), and Print() these formats.  The routines are
38 *         kept in a BigInt ops struct (see MP_Env.h).  The user may
39 *         replace the default GMP ops in an MP env with those of some
40 *         other format by calling MP_SetEnvBigIntFormat() and sending
41 *         in the address of the struct containing the proper routines
42 *         and the "name" of the format to be used.  It must be one of
43 *         the formats supported (as defined in MP_Types.h).
44 *         In any event, we want the sender to always have at least the
45 *         illusion that it is sending in its "native" format, so all
46 *         necessary conversions between representations are hidden in
47 *         supplied ops structs.  See below for examples!!!  Observe
48 *         that if SAC supported a straightforward conversion to string
49 *         routine, we wouldn't have to do all this messy convert to GMP
50 *         format first.  For TCP connections, the two endpoints negotiate
51 *         which format to use.  If both use the same format (GMP or other-
52 *         wise) then transmission should be "optimal".  But if they use
53 *         different formats, the non-GMP side (may be both sides), must
54 *         do conversions.  For other transport devices (e.g., files,
55 *         PVM, ToolBus), there is no negotiation.  There is no miracle
56 *         here, the programmer must be aware of the needs of the other
57 *         applications involved and know if they all support the same
58 *         format, setting the environment accordingly.
59 *         --> BTW: This approach is consistent with and similar to how
60 *             we deal with new transport devices.
61 *
62 *  Change Log:
63 *      4/22/96 sgray Life begins for this file.
64 *      4/23/96 sgray Completed and tested.  Seems okay. :-)
65 *
66 ************************************************************************/
67
68#ifndef lint
69static char vcid[] = "@(#) $Id$";
70#endif /* lint */
71
72#include "MP.h"
73
74#ifdef MP_HAVE_SAC
75
76/*#define MP_DEBUG */
77
78MP_BigIntOps_t imp_sac_bigint_ops = {
79  IMP_PutSacBigInt,
80  IMP_GetSacBigInt,
81  IMP_SacBigIntToStr,
82  IMP_SacBigIntAsciiSize
83};
84
85#if MP_DEFAULT_APINT_FORMAT == MP_SAC
86MP_BigIntOps_t imp_default_bigint_ops = {
87  IMP_PutSacBigInt,
88  IMP_GetSacBigInt,
89  IMP_SacBigIntToStr,
90  IMP_SacBigIntAsciiSize
91};
92MP_BigNumFormat_t imp_default_bigint_format = MP_SAC;
93#endif
94
95
96/*
97 * macro to determine if the GMP bignum is negative
98 */
99#define mpz_is_neg(mp_int) ((mp_int->_mp_size < 0))
100
101
102/*
103 * sac_to_gmp() assumes that the incoming integer really is a bignum and is
104 * not representable as a machine precision integer.  If the argument sac is
105 * machine precision, the while loop becomes infinite (this is bad).
106 *
107 * On entry I also assume that the caller has initialized gmp_int.
108 */
109static void sac_to_gmp(mpz_ptr gmp_int, Word sac)
110{
111    short set_neg_flag = -1; /* when set, this will be 0 or 1 */
112    MP_INT pwr, temp;
113    Word lsac, d;
114#ifdef MP_DEBUG   
115    fprintf(stderr, "sac_to_gmp: entering, the bignum here is ");
116    IWRITE(sac);printf("\n"); fflush(stderr);
117#endif
118
119    if (ISATOM(sac)) {
120      if (sac < 0) {
121         set_neg_flag = 1;
122         sac = -sac;
123         }
124      else set_neg_flag = 0;
125      mpz_set_si(gmp_int, (int) sac);
126      if (set_neg_flag) mpz_neg(gmp_int, gmp_int);
127      return;
128     }
129    ADV(sac, &d, &lsac);
130    mpz_init(&pwr); mpz_set_si(&pwr, 1);
131   
132    if (d != 0) {
133      set_neg_flag = (d < 0) ? 1 : 0;
134      if (set_neg_flag) d = -d;
135      }
136
137    mpz_set_si(gmp_int, d);
138    mpz_init(&temp);
139    while (!ISNIL(lsac)) {
140        mpz_mul_ui(&pwr, &pwr, BETA);
141        ADV(lsac, &d, &lsac);
142        if (d != 0) {
143            mpz_clear(&temp); 
144            /* Argh!!  We need to keep checking because we may have
145               had all leading zeroes to this point! */
146            if (set_neg_flag == -1) set_neg_flag = (d < 0) ? 1 : 0;
147            if (set_neg_flag) d = -d;
148            mpz_mul_ui(&temp, &pwr, d);
149            mpz_add(gmp_int, gmp_int, &temp);
150        }
151    }
152    if (set_neg_flag) mpz_neg(gmp_int, gmp_int);
153
154#ifdef MP_DEBUG
155    fprintf(stderr,"sac_to_gmp: exiting\n");fflush(stderr);
156#endif
157   return;
158}
159
160
161
162static void gmp_to_sac(Word *sac_int, mpz_ptr gmp_int)
163{
164    MP_INT  n, q, r;
165    Word    i = 0;
166    long    d;
167    short   set_neg_flag = mpz_is_neg(gmp_int);
168
169    if (abs(gmp_int->_mp_size) == 1) {
170      d = mpz_get_si(gmp_int);
171      if (set_neg_flag && (d > 0)) d = -d;
172      if (abs(d) < BETA) {
173        *sac_int = d;
174        return;
175        }
176    }
177    mpz_init(&n); 
178    mpz_set(&n, gmp_int);
179    mpz_init(&q); mpz_init(&r);
180    if (set_neg_flag) n._mp_size = -n._mp_size;
181    *sac_int = NIL;
182    while (1) {
183        d = mpz_fdiv_qr_ui(&q, &r, &n, BETA);
184        if (set_neg_flag && (d > 0)) d = -d;
185        *sac_int =  LEINST(*sac_int, i, d); i++;
186        d = mpz_cmp_si(&q, BETA);
187        if (mpz_cmp_si(&q, BETA) < 0) 
188            break; 
189        mpz_clear(&n);
190        mpz_set(&n, &q);
191    }
192    /*
193     * now get the last value from q
194     */
195    d = mpz_get_si(&q);
196    if (set_neg_flag && (d > 0)) d = -d;
197    *sac_int = LEINST(*sac_int, i, d); 
198}
199
200
201
202/* Generic routine to recursively put a SAC list */
203#ifdef __STDC__
204int IMP_PutSacList(MP_Link_pt link,
205                   Word L)
206#else
207int IMP_PutSacList(link, L)
208    MP_Link_pt link;
209    Word L;
210#endif
211{
212#ifdef MP_DEBUG
213    fprintf(stderr, "IMP_PutSacList: entering\n"); fflush(stderr);
214#endif
215
216    if ( L == NIL || ISATOM(L) ) { /* Packing atom*/
217        if (MP_PutSint32Packet(link, L, 0) != MP_Success)
218            return(-1);
219    }
220    else {                       /* Packing s-exp*/
221        if (MP_PutCommonOperatorPacket(link, MP_BasicDict, 
222                   MP_CopBasicList, 0, 1)
223            != MP_Success)
224            return(-1);
225        if (IMP_PutSacList(link, FIRST(L)) < 0 ) 
226            return(-1);
227        if (IMP_PutSacList(link, RED(L)) < 0 )
228            return(-1);
229    }
230
231#ifdef MP_DEBUG
232   fprintf(stderr, "IMP_PutSacList: exiting\n");  fflush(stderr);
233#endif
234
235    return(0);
236}
237
238
239
240#ifdef __STDC__
241Word IMP_GetSacList(MP_Link_pt link)
242#else
243Word IMP_GetSacList(link)
244    MP_Link_pt link;
245#endif
246{
247    Word a, b;
248    MP_NodeType_t ntype;
249    MP_NumAnnot_t na;
250    MP_NumChild_t nc;
251    MP_DictTag_t  dtag;
252    MP_Common_t   cv;
253#ifdef MP_DEBUG
254     fprintf(stderr, "IMP_GetSacList: entering\n");fflush(stderr); 
255#endif
256
257    if (IMP_GetNodeHeader(link, &ntype, 
258                          &dtag, &cv, &na, &nc) != MP_Success){
259        MP_PrintError(link);
260        return(-1); 
261    }
262    if (ntype == MP_Sint32Type) {  /* Unpack atom */
263        if (IMP_GetSint32(link, (MP_Sint32_t *) &a) != MP_Success) {
264          MP_PrintError(link);
265          return -1;
266          }
267        return(a);
268        }
269    else if (ntype == MP_CommonOperatorType && dtag == MP_BasicDict &&
270                   cv == MP_CopBasicList) { 
271        /* Unpack s-exp */
272        a = IMP_GetSacList(link);
273        b = IMP_GetSacList(link);
274        return(COMP(a,b));
275    } else { /* error */
276        fprintf(stderr, "IMP_GetSacList: invalid s-expression\n");
277        fflush(stderr);
278        return -1;
279      }
280}
281
282
283
284#ifdef __STDC__
285MP_Status_t IMP_PutSacBigInt(MP_Link_pt link, MP_ApInt_t sac_int)
286#else
287MP_Status_t IMP_PutSacBigInt(link, sac_int)
288    MP_Link_pt link;
289    MP_ApInt_t sac_int;
290#endif
291{
292    Word n = *((Word *)sac_int);
293    MP_INT  gmp_int;
294#ifdef MP_DEBUG
295    fprintf(stderr, "IMP_PutSacBigInt: entering, n is \n");fflush(stderr);
296    IWRITE (n); printf("\n"); fflush(stdout);
297#endif
298
299    if (link->link_bigint_format == MP_SAC) 
300        return(IMP_PutSacList(link, n));
301    else {
302        mpz_init(&gmp_int);
303        sac_to_gmp(&gmp_int, n);
304        ERR_CHK(IMP_PutGmpInt(link, (MP_ApInt_t)&gmp_int));
305        mpz_clear(&gmp_int);  /* sloppy, we don't cleanup on failure */
306    }
307    RETURN_OK(link);
308}
309
310
311
312
313#ifdef __STDC__
314MP_Status_t IMP_GetSacBigInt(MP_Link_pt link, MP_ApInt_pt sac_int)
315#else
316MP_Status_t IMP_GetSacBigInt(link, sac_int)
317    MP_Link_pt link;
318    MP_ApInt_pt sac_int;
319#endif
320{
321    mpz_ptr gmp_int = NULL;
322    Word    sac_tmp = 0, *sacptr;
323
324#ifdef MP_DEBUG
325    fprintf(stderr,"IMP_GetSacBigInt: entering\n");
326    fprintf(stderr, "\tbigint_format is %d\n", link->link_bigint_format);
327    fflush(stderr);
328#endif
329
330
331    if (link->link_bigint_format == MP_SAC) {
332        sacptr = (Word *)*sac_int; 
333        *sacptr = IMP_GetSacList(link);
334        if (*sacptr == -1) 
335            return MP_Failure; 
336        else 
337          RETURN_OK(link); 
338    } else {
339        ERR_CHK(IMP_GetGmpInt(link, (MP_ApInt_t *)&gmp_int));
340/*          gmp_to_sac((Word *)sac_int, gmp_int);  */
341         gmp_to_sac((Word)*((Word *)sac_int), gmp_int); 
342        mpz_clear(gmp_int);  /* sloppy, we don't cleanup on failure */
343    }
344
345#ifdef MP_DEBUG
346    fprintf(stderr, "IMP_GetSacBigInt: returning\n");fflush(stderr);
347#endif
348
349    RETURN_OK(link);
350}
351
352
353
354char * 
355#ifdef __STDC__
356IMP_SacBigIntToStr(MP_ApInt_t big_int, char *buffer)
357#else
358IMP_SacBigIntToStr(big_int, buffer)
359MP_ApInt_t  big_int;
360char       *buffer;
361#endif
362{
363    MP_INT gmp_int;
364#ifdef MP_DEBUG
365    fprintf(stderr,"IMP_SacBigIntToStr: entering.\n");
366    fflush(stderr);  fprintf(stderr, "\tthe bignum is ");
367    IWRITE(*(Word*)big_int);fprintf(stderr, "\n");fflush(stdout);
368#endif
369
370    mpz_init(&gmp_int);
371    sac_to_gmp(&gmp_int, *(Word*)big_int); 
372    mpz_get_str(buffer, 10, &gmp_int);
373    mpz_clear(&gmp_int);
374
375#ifdef MP_DEBUG
376    fprintf(stderr,"IMP_SacBigIntToStr: exiting\n");fflush(stderr);
377#endif
378
379    return buffer;
380}
381
382
383#ifdef __STDC__
384long IMP_SacBigIntAsciiSize(MP_ApInt_t mp_apint)
385#else
386long IMP_SacBigIntAsciiSize(mp_apint)
387    MP_ApInt_t mp_apint;
388#endif
389{
390  int len = 0;
391  Word tmp = *((Word *)mp_apint);
392
393  if (ISATOM(tmp)) return 9;
394
395  len = LENGTH(tmp);
396  return len * 9;
397}
398
399
400
401char * OLD_IMP_SacBigIntToStrOriginal(MP_Link_pt link, MP_ApInt_t big_int,
402 int direction)
403{
404    char *str = NULL;
405    mpz_ptr gmp_int = NULL;
406
407
408    fprintf(stderr,"IMP_SacBigIntToStr: entering\n");
409    if (direction == MP_SEND || 
410        link->link_bigint_format == MP_SAC) {
411        fprintf(stderr,"\thave to convert - SAC format\n");
412        mpz_init(gmp_int);
413        sac_to_gmp(gmp_int, *((Word *)big_int));
414        printf("\tdone conversion\n");
415        str = mpz_get_str(NULL, 10, gmp_int);
416        printf("\thave the string, cleaning up\n");
417        mpz_clear(gmp_int);
418    } else {  /* must be receiving in GMP format */
419        fprintf(stderr,"\tdont' have to convert - GMP format\n");
420        str = mpz_get_str(NULL, 10, (mpz_ptr)big_int);
421    }
422    fprintf(stderr,"IMP_SacBigIntToStr: exiting\n");fflush(stderr);
423 
424    return str;
425}
426
427
428#endif /* MP_HAVE_SAC */
Note: See TracBrowser for help on using the repository browser.