1 //------------------------------------------------------------------------------
2 // SLIP_LU/SLIP_gmp.c: interface to the gmp library
3 //------------------------------------------------------------------------------
4 
5 // SLIP_LU: (c) 2019-2020, Chris Lourenco, Jinhao Chen, Erick Moreno-Centeno,
6 // Timothy A. Davis, Texas A&M University.  All Rights Reserved.  See
7 // SLIP_LU/License for the license.
8 
9 //------------------------------------------------------------------------------
10 
11 // Purpose: This file (SLIP_gmp.c) provides a wrapper for all functions in the
12 // GMP library used by SLIP_LU.  The wrappers enable memory failures to be
13 // caught and handled properly.  GMP, by default, aborts the user's application
14 // if any internal malloc fails.  This is not acceptable in a robust end-user
15 // application.  Fortunately, GMP allows the user package (SLIP_LU in this
16 // case) to pass in function pointers for malloc, calloc, realloc, and free.
17 // These functions are defined below.  If they fail, they do not return to GMP.
18 // Instead, they use the ANSI C longjmp feature to trap the error, and return
19 // the error condition to the caller.
20 
21 // Note that not all functions in the GMP library are wrapped by these
22 // functions, but just the ones used by SLIP_LU.  However, most of the wrapper
23 // functions follow the same structure, and this method would easily extend to
24 // all GMP functions.  To that end, the wrapper mechanism (here, and in
25 // SLIP_gmp.h) is described below.
26 
27 // For a given GMP function 'gmpfunc' with no return value, the SLIP wrapper is
28 // SLIP_gmpfunc, with the same arguments:
29 
30 /*
31     SLIP_info SLIP_gmpfunc (args)
32     {
33         SLIP_GMP_WRAPPER_START ;
34         gmpfunc (args) ;
35         SLIP_GMP_WRAPPER_FINISH ;
36         return SLIP_OK ;
37     }
38 */
39 
40 // The SLIP_GMP*_WRAPPER_START and SLIP_GMP_WRAPPER_FINISH macros work together
41 // to establish a try/catch mechanism, via setjmp and longjmp.  If a memory
42 // error occurs, a NULL is not returned to GMP (which would terminate the user
43 // application).  Instead, the malloc wrapper traps the error via the longjmp,
44 // and an out-of-memory condition is returned to the caller of SLIP_gmpfunc.
45 
46 // If the gmpfunc has a return value, as in r = mpz_cmp (x,y), the return value
47 // is passed as the first argument to the SLIP_gmpfunc:
48 
49 /*
50     SLIP_info SLIP_gmfunc (result, args)
51     {
52         SLIP_GMP_WRAPPER_START ;
53         (*result) = gmpfunc (args) ;
54         SLIP_GMP_WRAPPER_FINISH ;
55         return SLIP_OK ;
56     }
57 */
58 
59 // The SLIP_GMP*_WRAPPER_START macros also take an single 'archive' parameter,
60 // for the current mpz, mpq, or mpfr object being operated on.  A pointer
61 // parameter to this parameter is kept so that it can be safely freed in case
62 // a memory error occurs (avoiding a double-free), in SLIP_GMP_SAFE_FREE.
63 
64 #include "slip_internal.h"
65 #include "SLIP_gmp.h"
66 
67 // ignore warnings about unused parameters in this file
68 #pragma GCC diagnostic ignored "-Wunused-parameter"
69 
70 //------------------------------------------------------------------------------
71 // global variables
72 //------------------------------------------------------------------------------
73 
74 jmp_buf slip_gmp_environment ;  // for setjmp and longjmp
75 int64_t slip_gmp_nmalloc = 0 ;  // number of malloc'd objects in SLIP_gmp_list
76 int64_t slip_gmp_nlist = 0 ;    // size of the SLIP_gmp_list
77 void **slip_gmp_list = NULL ;   // list of malloc'd objects
78 
79 int64_t slip_gmp_ntrials = -1 ; // number of malloc's allowed (for
80                                 // testing only): -1 means unlimited.
81 
82 mpz_t  *slip_gmpz_archive  = NULL ;    // current mpz object
83 mpq_t  *slip_gmpq_archive  = NULL ;    // current mpq object
84 mpfr_t *slip_gmpfr_archive = NULL ;    // current mpfr object
85 
86 //------------------------------------------------------------------------------
87 // slip_gmp_init: initialize gmp
88 //------------------------------------------------------------------------------
89 
90 /* Purpose: Create the list of malloc'd objects. This should be called before
91  * calling any GMP function. It is also called by SLIP_gmp_allocate when
92  * SLIP_gmp_list is NULL
93  */
94 
slip_gmp_init()95 bool slip_gmp_init ( )
96 {
97     slip_gmp_nmalloc = 0 ;
98     slip_gmp_nlist = SLIP_GMP_LIST_INIT ;
99     slip_gmp_list = (void **) SLIP_malloc (slip_gmp_nlist * sizeof (void *)) ;
100     return (slip_gmp_list != NULL) ;
101 }
102 
103 //------------------------------------------------------------------------------
104 // SLIP_gmp_finalize: finalize gmp
105 //------------------------------------------------------------------------------
106 
107 /* Purpose: Free the list. Must be called when all use of GMP is done */
slip_gmp_finalize()108 void slip_gmp_finalize ( )
109 {
110     slip_gmpz_archive = NULL ;
111     slip_gmpq_archive = NULL ;
112     slip_gmpfr_archive = NULL ;
113     slip_gmp_nmalloc = 0 ;
114     slip_gmp_nlist = 0 ;
115     SLIP_FREE (slip_gmp_list) ;
116 }
117 
118 //------------------------------------------------------------------------------
119 // SLIP_gmp_allocate: malloc space for gmp
120 //------------------------------------------------------------------------------
121 
122 /* Purpose: malloc space for gmp. A NULL pointer is never returned to the GMP
123  * library. If the allocation fails, all memory allocated since the start of
124  * the SLIP_gmp_wrapper is freed and an error is thrown to the GMP wrapper via
125  * longjmp
126  */
127 
slip_gmp_allocate(size_t size)128 void *slip_gmp_allocate
129 (
130     size_t size // Amount of memory to be allocated
131 )
132 {
133 
134     #ifdef SLIP_GMP_MEMORY_DEBUG
135     SLIP_PRINTF ("slip_gmp_malloc (%g): ", (double) size) ;
136     #endif
137 
138     //--------------------------------------------------------------------------
139     // for testing only:
140     //--------------------------------------------------------------------------
141 
142     if (slip_gmp_ntrials == 0)
143     {
144         // pretend to fail
145         #ifdef SLIP_GMP_MEMORY_DEBUG
146         SLIP_PRINTF ("slip_gmp_allocate pretends to fail\n") ;
147         #endif
148         longjmp (slip_gmp_environment, 1) ;
149     }
150     else if (slip_gmp_ntrials > 0)
151     {
152         // one more malloc has been used up
153         slip_gmp_ntrials-- ;
154     }
155 
156     //--------------------------------------------------------------------------
157     // ensure the SLIP_gmp_list is large enough
158     //--------------------------------------------------------------------------
159 
160     if (slip_gmp_list == NULL)
161     {
162         // create the initial SLIP_gmp_list
163         if (!slip_gmp_init ( ))
164         {
165             // failure to create the SLIP_gmp_list
166             longjmp (slip_gmp_environment, 2) ;
167         }
168     }
169     else if (slip_gmp_nmalloc == slip_gmp_nlist)
170     {
171         // double the size of the SLIP_gmp_list
172         bool ok ;
173         int64_t newsize = 2 * slip_gmp_nlist ;
174         slip_gmp_list = (void **)
175             SLIP_realloc (newsize, slip_gmp_nlist, sizeof (void *),
176             slip_gmp_list, &ok) ;
177         if (!ok)
178         {
179             // failure to double the size of the SLIP_gmp_list.
180             // The existing SLIP_gmp_list is still valid, with the old size,
181             // (SLIP_gmp_nlist).  This is required so that the error handler
182             // can traverse the SLIP_gmp_list to free all objects there.
183             longjmp (slip_gmp_environment, 3) ;
184         }
185         // success; the old SLIP_gmp_list has been freed, and replaced with
186         // the larger newlist.
187         slip_gmp_nlist = newsize ;
188     }
189 
190     //--------------------------------------------------------------------------
191     // malloc the block
192     //--------------------------------------------------------------------------
193 
194     void *p = SLIP_malloc (size) ;
195 
196     if (p == NULL)
197     {
198         // failure to allocate the new block
199         longjmp (slip_gmp_environment, 4) ;
200     }
201 
202     //--------------------------------------------------------------------------
203     // save p in the SLIP_gmp_list and return result to GMP
204     //--------------------------------------------------------------------------
205 
206     slip_gmp_list [slip_gmp_nmalloc++] = p ;
207 
208     #ifdef SLIP_GMP_MEMORY_DEBUG
209     SLIP_PRINTF (" %p\n", p) ;
210     slip_gmp_dump ( ) ;
211     #endif
212 
213     // return p to SLIP_gmp_function (NEVER return a NULL pointer to GMP!)
214     ASSERT (p != NULL) ;
215     return (p) ;
216 }
217 
218 //------------------------------------------------------------------------------
219 // slip_gmp_free: free space for gmp
220 //------------------------------------------------------------------------------
221 
222 /* Purpose: Free space for GMP */
slip_gmp_free(void * p,size_t size)223 void slip_gmp_free
224 (
225     void *p,        // Block to be freed
226     size_t size     // Size of p (currently an unused parameter)
227 )
228 {
229     #ifdef SLIP_GMP_MEMORY_DEBUG
230     SLIP_PRINTF ("\n=================== free %p\n", p) ;
231     slip_gmp_dump ( ) ;
232     #endif
233 
234     if (p != NULL && slip_gmp_list != NULL)
235     {
236         // remove p from the SLIP_gmp_list
237         for (int64_t i = 0 ; i < slip_gmp_nmalloc ; i++)
238         {
239             if (slip_gmp_list [i] == p)
240             {
241                 #ifdef SLIP_GMP_MEMORY_DEBUG
242                 SLIP_PRINTF ("    found at i = %d\n", i) ;
243                 #endif
244                 slip_gmp_list [i] = slip_gmp_list [--slip_gmp_nmalloc] ;
245                 break ;
246             }
247         }
248     }
249 
250     #ifdef SLIP_GMP_MEMORY_DEBUG
251     slip_gmp_dump ( ) ;
252     #endif
253 
254     // free p, even if it is not found in the SLIP_gmp_list.  p is only in the
255     // SLIP_gmp_list if it was allocated inside the current GMP function.
256     // If the block was allocated by one GMP function and freed by another,
257     // it is not in the list.
258     SLIP_GMP_SAFE_FREE (p) ;
259 }
260 
261 //------------------------------------------------------------------------------
262 // slip_gmp_reallocate:  wrapper for realloc
263 //------------------------------------------------------------------------------
264 
265 /* Purpose: Wrapper for GMP to call reallocation */
slip_gmp_reallocate(void * p_old,size_t old_size,size_t new_size)266 void *slip_gmp_reallocate
267 (
268     void *p_old,        // Pointer to be realloc'd
269     size_t old_size,    // Old size of p
270     size_t new_size     // New size of p
271 )
272 {
273     #ifdef SLIP_GMP_MEMORY_DEBUG
274     SLIP_PRINTF ("slip_gmp_realloc (%p, %g, %g)\n", p_old,
275         (double) old_size, (double) new_size) ;
276     #endif
277 
278     if (p_old == NULL)
279     {
280         // realloc (NULL, size) is the same as malloc (size)
281         return (slip_gmp_allocate (new_size)) ;
282     }
283     else if (new_size == 0)
284     {
285         // realloc (p, 0) is the same as free (p), and returns NULL
286         slip_gmp_free (p_old, old_size) ;
287         return (NULL) ;
288     }
289     else
290     {
291         // change the size of the block
292         void *p_new = slip_gmp_allocate (new_size) ;
293         // Note that p_new will never be NULL here, since SLIP_gmp_allocate
294         // does not return if it fails.
295         memcpy (p_new, p_old, SLIP_MIN (old_size, new_size)) ;
296         slip_gmp_free (p_old, old_size) ;
297         return (p_new) ;
298     }
299 }
300 
301 //------------------------------------------------------------------------------
302 // slip_gmp_dump: debug function
303 //------------------------------------------------------------------------------
304 
305 /* Purpose: Dump the list of malloc'd objects */
306 #ifdef SLIP_GMP_MEMORY_DEBUG
slip_gmp_dump()307 void slip_gmp_dump ( )
308 {
309     // dump the SLIP_gmp_list
310     SLIP_PRINTF ("nmalloc = %g, SLIP_gmp_nlist = %g\n",
311         (double) slip_gmp_nmalloc, (double) slip_gmp_nlist) ;
312     if (slip_gmp_list != NULL)
313     {
314         for (int64_t i = 0 ; i < slip_gmp_nmalloc ; i++)
315         {
316             SLIP_PRINTF ("    slip_gmp_list [%d] = %p\n", i, slip_gmp_list [i]);
317         }
318     }
319 }
320 #endif
321 
322 //------------------------------------------------------------------------------
323 // slip_gmp_failure: catch an error
324 //------------------------------------------------------------------------------
325 
326 /* Purpose: Catch an error from longjmp */
slip_gmp_failure(int status)327 void slip_gmp_failure
328 (
329     int status      // Status returned from longjmp
330                     // (unused parameter unless debugging)
331 )
332 {
333     #ifdef SLIP_GMP_MEMORY_DEBUG
334     SLIP_PRINTF ("failure from longjmp: status: %d\n", status) ;
335     #endif
336 
337     // first free all caches
338     mpfr_free_cache ( ) ;
339 
340     // Free the list
341     if (slip_gmp_list != NULL)
342     {
343         for (int64_t i = 0 ; i < slip_gmp_nmalloc ; i++)
344         {
345             SLIP_GMP_SAFE_FREE (slip_gmp_list [i]) ;
346         }
347     }
348     slip_gmp_finalize ( ) ;
349 }
350 
351 //------------------------------------------------------------------------------
352 //------------------------------------------------------------------------------
353 //----------------------------Print and Scan functions--------------------------
354 //------------------------------------------------------------------------------
355 //------------------------------------------------------------------------------
356 
357 //------------------------------------------------------------------------------
358 // SLIP_gmp_fprintf
359 //------------------------------------------------------------------------------
360 
361 /* Safely print to the stream fp. Return positive value (the number of
362  * characters written) upon success, otherwise return negative value (error
363  * code) */
364 
365 #if 0
366 /* This function is currently unused, but kept here for future reference. */
367 
368 SLIP_info SLIP_gmp_fprintf
369 (
370     FILE *fp,
371     const char *format,
372     ...
373 )
374 {
375     // Start the GMP wrapper
376     SLIP_GMP_WRAPPER_START ;
377 
378     // call gmp_vfprintf
379     va_list args;
380     va_start (args, format) ;
381     int n = gmp_vfprintf (fp, format, args) ;
382     va_end (args) ;
383 
384     // Finish the wrapper
385     SLIP_GMP_WRAPPER_FINISH ;
386     // gmp_vfprintf returns -1 if an error occurred.
387     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
388 }
389 #endif
390 
391 //------------------------------------------------------------------------------
392 // SLIP_gmp_printf
393 //------------------------------------------------------------------------------
394 
395 /* Safely print to the standard output stdout. Return positive value (the number
396  * of characters written) upon success, otherwise return negative value (error
397  * code) */
398 #if 0
399 /* This function is currently unused, but kept here for future reference. */
400 SLIP_info SLIP_gmp_printf
401 (
402     const char *format,
403     ...
404 )
405 {
406     // Start the GMP wrapper
407     SLIP_GMP_WRAPPER_START ;
408 
409     // call gmp_vprintf
410     va_list args;
411     va_start (args, format) ;
412     int n = gmp_vprintf (format, args) ;
413     va_end (args) ;
414 
415     // Finish the wrapper
416     SLIP_GMP_WRAPPER_FINISH ;
417     // gmp_vprintf returns -1 if an error occurred.
418     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
419 }
420 #endif
421 
422 //------------------------------------------------------------------------------
423 // SLIP_gmp_asprintf
424 //------------------------------------------------------------------------------
425 
426 /* Safely write the output as a null terminated string in a block of memory,
427  * which is pointed to by a pointer stored in str. The block of memory must be
428  * freed using SLIP_free. The return value is the number of characters
429  * written in the string, excluding the null-terminator, or a negative value if
430  * an error occurred */
431 
432 #if 0
433 /* This function is currently unused, but kept here for future reference. */
434 /* Its functionality is provided by SLIP_mpfr_asprintf. */
435 SLIP_info SLIP_gmp_asprintf (char **str, const char *format, ... )
436 {
437     // Start the GMP wrapper
438     SLIP_GMP_WRAPPER_START ;
439 
440     // call gmp_vasprintf
441     va_list args;
442     va_start (args, format) ;
443     int n = gmp_vasprintf (str, format, args) ;
444     va_end (args) ;
445 
446     // Finish the wrapper
447     SLIP_GMP_WRAPPER_FINISH ;
448     // gmp_vasprintf returns a negative value if an error occurred
449     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
450 }
451 #endif
452 
453 //------------------------------------------------------------------------------
454 // SLIP_gmp_fscanf
455 //------------------------------------------------------------------------------
456 
457 /* Safely scan the stream fp. Return positive value (the number of fields
458  * successfully parsed and stored), otherwise return negative value (error
459  * code) */
460 
SLIP_gmp_fscanf(FILE * fp,const char * format,...)461 SLIP_info SLIP_gmp_fscanf
462 (
463     FILE *fp,
464     const char *format,
465     ...
466 )
467 {
468     // Start the GMP wrapper
469     SLIP_GMP_WRAPPER_START ;
470 
471     // call gmp_vfscanf
472     va_list args;
473     va_start (args, format) ;
474     int n = gmp_vfscanf (fp, format, args) ;
475     va_end (args) ;
476 
477     // Finish the wrapper
478     SLIP_GMP_WRAPPER_FINISH ;
479     // If end of input (or a file error) is reached before a character
480     // for a field or a literal, and if no previous non-suppressed fields have
481     // matched, then the return value is EOF instead of 0
482     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
483 }
484 
485 //------------------------------------------------------------------------------
486 // SLIP_mpfr_asprintf
487 //------------------------------------------------------------------------------
488 
489 /* Safely write the output as a null terminated string in a block of memory,
490  * which is pointed to by a pointer stored in str. The block of memory must be
491  * freed using SLIP_mpfr_free_str. The return value is the number of characters
492  * written in the string, excluding the null-terminator, or a negative value if
493  * an error occurred */
494 
SLIP_mpfr_asprintf(char ** str,const char * format,...)495 SLIP_info SLIP_mpfr_asprintf (char **str, const char *format, ... )
496 {
497     // Start the GMP wrapper
498     SLIP_GMP_WRAPPER_START ;
499 
500     // call mpfr_vasprintf
501     va_list args;
502     va_start (args, format) ;
503     int n = mpfr_vasprintf (str, format, args) ;
504     va_end (args) ;
505 
506     // Finish the wrapper
507     SLIP_GMP_WRAPPER_FINISH ;
508     // mpfr_vasprintf returns a negative value if an error occurred
509     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
510 }
511 
512 //------------------------------------------------------------------------------
513 // SLIP_mpfr_free_str
514 //------------------------------------------------------------------------------
515 
516 /* Safely free a string allocated by SLIP_mpfr_asprintf. */
517 /* DONT TRY TO FREE NULL PONITER USING THIS FUNCTION*/
518 
SLIP_mpfr_free_str(char * str)519 SLIP_info SLIP_mpfr_free_str (char *str)
520 {
521     // Start the GMP wrapper
522     SLIP_GMP_WRAPPER_START ;
523 
524     // call mpfr_free_str
525     mpfr_free_str (str) ;
526 
527     // Finish the wrapper and return 0 if successful
528     SLIP_GMP_WRAPPER_FINISH ;
529     return (SLIP_OK) ;
530 }
531 
532 //------------------------------------------------------------------------------
533 // SLIP_mpfr_fprintf
534 //------------------------------------------------------------------------------
535 
536 /* Safely print to the stream fp. Return positive value (the number of
537  * characters written) upon success, otherwise return negative value (error
538  * code) */
539 
540 #if 0
541 /* This function is currently unused, but kept here for future reference. */
542 
543 SLIP_info SLIP_mpfr_fprintf
544 (
545     FILE *fp,
546     const char *format,
547     ...
548 )
549 {
550     // Start the GMP wrapper
551     SLIP_GMP_WRAPPER_START ;
552 
553     // call mpfr_vfprintf
554     va_list args;
555     va_start (args, format) ;
556     int n = mpfr_vfprintf (fp, format, args) ;
557     va_end (args) ;
558     // Free cache from mpfr_vfprintf. Even though mpfr_free_cache is
559     // called in SLIP_LU_final ( ), it has to be called here to
560     // prevent memory leak in some rare situations.
561     mpfr_free_cache ( ) ;
562 
563     // Finish the wrapper
564     SLIP_GMP_WRAPPER_FINISH ;
565     // mpfr_vfprintf returns -1 if an error occurred.
566     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
567 }
568 #endif
569 
570 //------------------------------------------------------------------------------
571 // SLIP_mpfr_printf
572 //------------------------------------------------------------------------------
573 
574 /* Safely print to the standard output stdout. Return positive value (the number
575  * of characters written) upon success, otherwise return negative value (error
576  * code) */
577 
578 #if 0
579 /* This function is currently unused, but kept here for future reference. */
580 SLIP_info SLIP_mpfr_printf
581 (
582     const char *format,
583     ...
584 )
585 {
586     // Start the GMP wrapper
587     SLIP_GMP_WRAPPER_START ;
588 
589     // call mpfr_vprintf
590     va_list args;
591     va_start (args, format) ;
592     int n = mpfr_vprintf (format, args) ;
593     va_end (args) ;
594     // Free cache from mpfr_vprintf. Even though mpfr_free_cache is
595     // called in SLIP_LU_final ( ), it has to be called here to
596     // prevent memory leak in some rare situations.
597     mpfr_free_cache ( ) ;
598 
599     // Finish the wrapper
600     SLIP_GMP_WRAPPER_FINISH ;
601     // mpfr_vprintf returns -1 if an error occurred.
602     return ((n < 0) ? SLIP_INCORRECT_INPUT : SLIP_OK) ;
603 }
604 #endif
605 //------------------------------------------------------------------------------
606 //------------------------------------------------------------------------------
607 //-------------------------Integer (mpz_t type) functions-----------------------
608 //------------------------------------------------------------------------------
609 //------------------------------------------------------------------------------
610 
611 //------------------------------------------------------------------------------
612 // SLIP_mpz_init
613 //------------------------------------------------------------------------------
614 
615 /* Purpose: Safely initialize an mpz_t number */
616 
SLIP_mpz_init(mpz_t x)617 SLIP_info SLIP_mpz_init
618 (
619     mpz_t x
620 )
621 {
622     SLIP_GMPZ_WRAPPER_START (x) ;
623     mpz_init (x) ;
624     SLIP_GMP_WRAPPER_FINISH ;
625     return (SLIP_OK) ;
626 }
627 
628 //------------------------------------------------------------------------------
629 // SLIP_mpz_init2
630 //------------------------------------------------------------------------------
631 
632 /* Purpose: Safely initialize an mpz_t number with space for size bits */
633 
SLIP_mpz_init2(mpz_t x,const size_t size)634 SLIP_info SLIP_mpz_init2
635 (
636     mpz_t x,                // Number to be initialized
637     const size_t size       // size of the number
638 )
639 {
640     SLIP_GMPZ_WRAPPER_START (x) ;
641     mpz_init2 (x, (mp_bitcnt_t) size) ;
642     SLIP_GMP_WRAPPER_FINISH ;
643     return (SLIP_OK) ;
644 }
645 
646 //------------------------------------------------------------------------------
647 // SLIP_mpz_set
648 //------------------------------------------------------------------------------
649 
650 /* Purpose: Safely set an mpz number = to an mpz number, i.e., x = y */
651 
SLIP_mpz_set(mpz_t x,const mpz_t y)652 SLIP_info SLIP_mpz_set
653 (
654     mpz_t x,
655     const mpz_t y
656 )
657 {
658     SLIP_GMPZ_WRAPPER_START (x) ;
659     mpz_set (x, y) ;
660     SLIP_GMP_WRAPPER_FINISH ;
661     return (SLIP_OK) ;
662 }
663 
664 //------------------------------------------------------------------------------
665 // SLIP_mpz_set_ui
666 //------------------------------------------------------------------------------
667 
668 /* Purpose: Safely set an mpz number = to uint64_t, i.e., x = y */
669 
SLIP_mpz_set_ui(mpz_t x,const uint64_t y)670 SLIP_info SLIP_mpz_set_ui
671 (
672     mpz_t x,
673     const uint64_t y
674 )
675 {
676     SLIP_GMPZ_WRAPPER_START (x) ;
677     mpz_set_ui (x, (unsigned long int) y) ;
678     SLIP_GMP_WRAPPER_FINISH ;
679     return (SLIP_OK) ;
680 }
681 
682 //------------------------------------------------------------------------------
683 // SLIP_mpz_set_si
684 //------------------------------------------------------------------------------
685 
686 /* Purpose: Safely set an mpz number = a signed int64_t */
687 
SLIP_mpz_set_si(mpz_t x,const int64_t y)688 SLIP_info SLIP_mpz_set_si
689 (
690     mpz_t x,
691     const int64_t y
692 )
693 {
694     SLIP_GMPZ_WRAPPER_START (x) ;
695     mpz_set_si (x, (signed long int) y) ;
696     SLIP_GMP_WRAPPER_FINISH ;
697     return (SLIP_OK) ;
698 }
699 #if 0
700 /* This function is currently unused, but kept here for future reference. */
701 //------------------------------------------------------------------------------
702 // SLIP_mpz_set_d
703 //------------------------------------------------------------------------------
704 
705 /* Purpose: Safely set an mpz number = a double */
706 
707 SLIP_info SLIP_mpz_set_d
708 (
709     mpz_t x,
710     const double y
711 )
712 {
713     SLIP_GMPZ_WRAPPER_START (x) ;
714     mpz_set_d (x, y) ;
715     SLIP_GMP_WRAPPER_FINISH ;
716     return (SLIP_OK) ;
717 }
718 #endif
719 
720 //------------------------------------------------------------------------------
721 // SLIP_mpz_get_d
722 //------------------------------------------------------------------------------
723 
724 /* Purpose: Safely set a double number = a mpz */
725 
SLIP_mpz_get_d(double * x,const mpz_t y)726 SLIP_info SLIP_mpz_get_d
727 (
728     double *x,
729     const mpz_t y
730 )
731 {
732     SLIP_GMP_WRAPPER_START ;
733     *x = mpz_get_d (y) ;
734     SLIP_GMP_WRAPPER_FINISH ;
735     return (SLIP_OK) ;
736 }
737 
738 //------------------------------------------------------------------------------
739 // SLIP_mpz_get_si
740 //------------------------------------------------------------------------------
741 
742 /* Purpose: Safely set an int64_t = a mpz */
743 
SLIP_mpz_get_si(int64_t * x,const mpz_t y)744 SLIP_info SLIP_mpz_get_si
745 (
746     int64_t *x,
747     const mpz_t y
748 )
749 {
750     SLIP_GMP_WRAPPER_START ;
751     *x = mpz_get_si (y) ;
752     SLIP_GMP_WRAPPER_FINISH ;
753     return (SLIP_OK) ;
754 }
755 
756 //------------------------------------------------------------------------------
757 // SLIP_mpz_set_q
758 //------------------------------------------------------------------------------
759 
760 /* Purpose: Safely set an mpz number = mpq number */
761 
SLIP_mpz_set_q(mpz_t x,const mpq_t y)762 SLIP_info SLIP_mpz_set_q
763 (
764     mpz_t x,
765     const mpq_t y
766 )
767 {
768     SLIP_GMPZ_WRAPPER_START (x) ;
769     mpz_set_q (x, y) ;
770     SLIP_GMP_WRAPPER_FINISH ;
771     return (SLIP_OK) ;
772 }
773 
774 //------------------------------------------------------------------------------
775 // SLIP_mpz_mul
776 //------------------------------------------------------------------------------
777 
778 /* Purpose: Safely compute a = b*c */
779 
SLIP_mpz_mul(mpz_t a,const mpz_t b,const mpz_t c)780 SLIP_info SLIP_mpz_mul
781 (
782     mpz_t a,
783     const mpz_t b,
784     const mpz_t c
785 )
786 {
787     SLIP_GMPZ_WRAPPER_START (a) ;
788     mpz_mul (a, b, c) ;
789     SLIP_GMP_WRAPPER_FINISH ;
790     return (SLIP_OK) ;
791 }
792 
793 //------------------------------------------------------------------------------
794 // SLIP_mpz_add
795 //------------------------------------------------------------------------------
796 
797 /* Purpose: Safely compute a = b+c */
798 
799 #if 0
800 /* This function is currently unused, but kept here for future reference. */
801 
802 SLIP_info SLIP_mpz_add
803 (
804     mpz_t a,
805     const mpz_t b,
806     const mpz_t c
807 )
808 {
809     SLIP_GMPZ_WRAPPER_START (a) ;
810     mpz_add (a,b,c) ;
811     SLIP_GMP_WRAPPER_FINISH ;
812     return (SLIP_OK) ;
813 }
814 #endif
815 
816 //------------------------------------------------------------------------------
817 // SLIP_mpz_addmul
818 //------------------------------------------------------------------------------
819 
820 /* Purpose: Safely set an mpz number += product of two mpz numbers,
821  * i.e., x = x + y*z */
822 
823 #if 0
824 /* This function is currently unused, but kept here for future reference. */
825 SLIP_info SLIP_mpz_addmul
826 (
827     mpz_t x,
828     const mpz_t y,
829     const mpz_t z
830 )
831 {
832     SLIP_GMPZ_WRAPPER_START (x) ;
833     mpz_addmul (x, y, z) ;
834     SLIP_GMP_WRAPPER_FINISH ;
835     return (SLIP_OK) ;
836 }
837 #endif
838 
839 //------------------------------------------------------------------------------
840 // SLIP_mpz_submul
841 //------------------------------------------------------------------------------
842 
843 /* Purpose: Safely set an mpz number = itself minus a product of
844  * mpz numbers, i.e., x = x - y*z
845  */
846 
SLIP_mpz_submul(mpz_t x,const mpz_t y,const mpz_t z)847 SLIP_info SLIP_mpz_submul
848 (
849     mpz_t x,
850     const mpz_t y,
851     const mpz_t z
852 )
853 {
854     SLIP_GMPZ_WRAPPER_START (x) ;
855     mpz_submul (x, y, z) ;
856     SLIP_GMP_WRAPPER_FINISH ;
857     return (SLIP_OK) ;
858 }
859 
860 //------------------------------------------------------------------------------
861 // SLIP_mpz_divexact
862 //------------------------------------------------------------------------------
863 
864 /* Purpose: Safe version of exact integer division, i.e., x = y / z */
865 
SLIP_mpz_divexact(mpz_t x,const mpz_t y,const mpz_t z)866 SLIP_info SLIP_mpz_divexact
867 (
868     mpz_t x,
869     const mpz_t y,
870     const mpz_t z
871 )
872 {
873     SLIP_GMPZ_WRAPPER_START (x) ;
874     mpz_divexact (x, y, z) ;
875     SLIP_GMP_WRAPPER_FINISH ;
876     return (SLIP_OK) ;
877 }
878 
879 //------------------------------------------------------------------------------
880 // SLIP_mpz_gcd
881 //------------------------------------------------------------------------------
882 
883 /* Purpose: Safely compute the gcd of two mpz_t numbers, i.e., x = gcd (y, z) */
884 
SLIP_mpz_gcd(mpz_t x,const mpz_t y,const mpz_t z)885 SLIP_info SLIP_mpz_gcd
886 (
887     mpz_t x,
888     const mpz_t y,
889     const mpz_t z
890 )
891 {
892     SLIP_GMPZ_WRAPPER_START (x) ;
893     mpz_gcd (x, y, z) ;
894     SLIP_GMP_WRAPPER_FINISH ;
895     return (SLIP_OK) ;
896 }
897 
898 //------------------------------------------------------------------------------
899 // SLIP_mpz_lcm
900 //------------------------------------------------------------------------------
901 
902 /* Purpose: Safely compute the lcm of two mpz numbers */
903 
SLIP_mpz_lcm(mpz_t lcm,const mpz_t x,const mpz_t y)904 SLIP_info SLIP_mpz_lcm
905 (
906     mpz_t lcm,   // lcm of x and y
907     const mpz_t x,
908     const mpz_t y
909 )
910 {
911     SLIP_GMPZ_WRAPPER_START (lcm) ;
912     mpz_lcm (lcm, x, y) ;
913     SLIP_GMP_WRAPPER_FINISH ;
914     return (SLIP_OK) ;
915 }
916 
917 //------------------------------------------------------------------------------
918 // SLIP_mpz_abs
919 //------------------------------------------------------------------------------
920 
921 /* Purpose: Safely set x = |y| */
922 
SLIP_mpz_abs(mpz_t x,const mpz_t y)923 SLIP_info SLIP_mpz_abs
924 (
925     mpz_t x,
926     const mpz_t y
927 )
928 {
929     SLIP_GMPZ_WRAPPER_START (x) ;
930     mpz_abs (x, y) ;
931     SLIP_GMP_WRAPPER_FINISH ;
932     return (SLIP_OK) ;
933 }
934 
935 //------------------------------------------------------------------------------
936 // SLIP_mpz_cmp
937 //------------------------------------------------------------------------------
938 
939 /* Purpose: Safely compare two mpz numbers,
940  * r > 0 if x > y, r = 0 if x = y, and r < 0 if x < y */
941 
SLIP_mpz_cmp(int * r,const mpz_t x,const mpz_t y)942 SLIP_info SLIP_mpz_cmp
943 (
944     int *r,
945     const mpz_t x,
946     const mpz_t y
947 )
948 {
949     SLIP_GMP_WRAPPER_START ;
950     *r = mpz_cmp (x, y) ;
951     SLIP_GMP_WRAPPER_FINISH ;
952     return (SLIP_OK) ;
953 }
954 
955 //------------------------------------------------------------------------------
956 // SLIP_mpz_cmpabs
957 //------------------------------------------------------------------------------
958 
959 /* Purpose: Safely compare the absolute value of two mpz numbers,
960  * r > 0 if |x| > |y|, r = 0 if |x| = |y|, and r < 0 if |x| < |y| */
961 
SLIP_mpz_cmpabs(int * r,const mpz_t x,const mpz_t y)962 SLIP_info SLIP_mpz_cmpabs
963 (
964     int *r,
965     const mpz_t x,
966     const mpz_t y
967 )
968 {
969     SLIP_GMP_WRAPPER_START ;
970     *r = mpz_cmpabs (x, y) ;
971     SLIP_GMP_WRAPPER_FINISH ;
972     return (SLIP_OK) ;
973 }
974 
975 //------------------------------------------------------------------------------
976 // SLIP_mpz_cmp_ui
977 //------------------------------------------------------------------------------
978 
979 /* Purpose: Safely compare a mpz number with a uint64_t integer
980  * r > 0 if x > y, r = 0 if x = y, and r < 0 if x < y */
SLIP_mpz_cmp_ui(int * r,const mpz_t x,const uint64_t y)981 SLIP_info SLIP_mpz_cmp_ui
982 (
983     int *r,
984     const mpz_t x,
985     const uint64_t y
986 )
987 {
988     SLIP_GMP_WRAPPER_START ;
989     *r = mpz_cmp_ui (x, (unsigned long int) y) ;
990     SLIP_GMP_WRAPPER_FINISH ;
991     return (SLIP_OK) ;
992 }
993 
994 //------------------------------------------------------------------------------
995 // SLIP_mpz_sgn
996 //------------------------------------------------------------------------------
997 
998 /* Purpose: Safely set sgn = 0 if x = 0, otherwise, sgn = x/|x| */
999 
SLIP_mpz_sgn(int * sgn,const mpz_t x)1000 SLIP_info SLIP_mpz_sgn
1001 (
1002     int *sgn,
1003     const mpz_t x
1004 )
1005 {
1006     SLIP_GMP_WRAPPER_START ;
1007     *sgn = mpz_sgn (x) ;
1008     SLIP_GMP_WRAPPER_FINISH ;
1009     return (SLIP_OK) ;
1010 }
1011 
1012 //------------------------------------------------------------------------------
1013 // SLIP_mpz_sizeinbase
1014 //------------------------------------------------------------------------------
1015 
1016 /* Purpose: Safely return the size of x measured in number of digits
1017  * in the given base */
SLIP_mpz_sizeinbase(size_t * size,const mpz_t x,int64_t base)1018 SLIP_info SLIP_mpz_sizeinbase
1019 (
1020     size_t *size,
1021     const mpz_t x,
1022     int64_t base
1023 )
1024 {
1025     SLIP_GMP_WRAPPER_START ;
1026     *size = mpz_sizeinbase (x, (int) base) ;
1027     SLIP_GMP_WRAPPER_FINISH ;
1028     return (SLIP_OK) ;
1029 }
1030 
1031 //------------------------------------------------------------------------------
1032 //------------------------------------------------------------------------------
1033 //-------------------------Rational  (mpq type) functions------------------------
1034 //------------------------------------------------------------------------------
1035 //------------------------------------------------------------------------------
1036 
1037 //------------------------------------------------------------------------------
1038 // SLIP_mpq_init
1039 //------------------------------------------------------------------------------
1040 
1041 /* Purpose: Safely initialize an mpq_t number */
1042 
SLIP_mpq_init(mpq_t x)1043 SLIP_info SLIP_mpq_init
1044 (
1045     mpq_t x
1046 )
1047 {
1048     SLIP_GMPQ_WRAPPER_START (x) ;
1049     mpq_init (x) ;
1050     SLIP_GMP_WRAPPER_FINISH ;
1051     return (SLIP_OK) ;
1052 }
1053 
1054 //------------------------------------------------------------------------------
1055 // SLIP_mpq_set
1056 //------------------------------------------------------------------------------
1057 
1058 /* Purpose: Safely set an mpq number = to an mpq number, i.e., x = y */
1059 
SLIP_mpq_set(mpq_t x,const mpq_t y)1060 SLIP_info SLIP_mpq_set
1061 (
1062     mpq_t x,
1063     const mpq_t y
1064 )
1065 {
1066     SLIP_GMPQ_WRAPPER_START (x) ;
1067     mpq_set (x, y) ;
1068     SLIP_GMP_WRAPPER_FINISH ;
1069     return (SLIP_OK) ;
1070 }
1071 
1072 //------------------------------------------------------------------------------
1073 // SLIP_mpq_set_z
1074 //------------------------------------------------------------------------------
1075 
1076 /* Purpose: Safely set an mpq number = an mpz number. i.e., x = y */
1077 
SLIP_mpq_set_z(mpq_t x,const mpz_t y)1078 SLIP_info SLIP_mpq_set_z
1079 (
1080     mpq_t x,
1081     const mpz_t y
1082 )
1083 {
1084     SLIP_GMPQ_WRAPPER_START (x) ;
1085     mpq_set_z (x, y) ;
1086     SLIP_GMP_WRAPPER_FINISH ;
1087     return (SLIP_OK) ;
1088 }
1089 
1090 //------------------------------------------------------------------------------
1091 // SLIP_mpq_set_d
1092 //------------------------------------------------------------------------------
1093 
1094 /* Purpose: Safely set an mpq number = a double */
1095 
SLIP_mpq_set_d(mpq_t x,const double y)1096 SLIP_info SLIP_mpq_set_d
1097 (
1098     mpq_t x,
1099     const double y
1100 )
1101 {
1102     SLIP_GMPQ_WRAPPER_START (x) ;
1103     mpq_set_d (x, y) ;
1104     SLIP_GMP_WRAPPER_FINISH ;
1105     return (SLIP_OK) ;
1106 }
1107 
1108 //------------------------------------------------------------------------------
1109 // SLIP_mpq_set_ui
1110 //------------------------------------------------------------------------------
1111 
1112 /* Purpose: Safely set an mpq number as the fraction of two
1113  * unsigned ints. i.e., x = y / z
1114  */
1115 
SLIP_mpq_set_ui(mpq_t x,const uint64_t y,const uint64_t z)1116 SLIP_info SLIP_mpq_set_ui
1117 (
1118     mpq_t x,
1119     const uint64_t y,
1120     const uint64_t z
1121 )
1122 {
1123     SLIP_GMPQ_WRAPPER_START (x) ;
1124     mpq_set_ui (x, (unsigned long int) y, (unsigned long int) z) ;
1125     SLIP_GMP_WRAPPER_FINISH ;
1126     return (SLIP_OK) ;
1127 }
1128 
1129 //------------------------------------------------------------------------------
1130 // SLIP_mpq_set_si
1131 //------------------------------------------------------------------------------
1132 
1133 /* Purpose: Safely set an mpq number = an int64_t */
1134 
SLIP_mpq_set_si(mpq_t x,const int64_t y,const uint64_t z)1135 SLIP_info SLIP_mpq_set_si
1136 (
1137     mpq_t x,
1138     const int64_t y,
1139     const uint64_t z
1140 )
1141 {
1142     SLIP_GMPQ_WRAPPER_START (x) ;
1143     mpq_set_si (x, (signed long int) y, (unsigned long int) x) ;
1144     SLIP_GMP_WRAPPER_FINISH ;
1145     return (SLIP_OK) ;
1146 }
1147 
1148 //------------------------------------------------------------------------------
1149 // SLIP_mpq_set_num
1150 //------------------------------------------------------------------------------
1151 
1152 /* Purpose: Safely set the numerator of an mpq number */
1153 
SLIP_mpq_set_num(mpq_t x,const mpz_t y)1154 SLIP_info SLIP_mpq_set_num
1155 (
1156     mpq_t x,
1157     const mpz_t y
1158 )
1159 {
1160     SLIP_GMPQ_WRAPPER_START (x) ;
1161     mpq_set_num (x, y) ;
1162     SLIP_GMP_WRAPPER_FINISH ;
1163     return (SLIP_OK) ;
1164 }
1165 
1166 //------------------------------------------------------------------------------
1167 // SLIP_mpq_set_den
1168 //------------------------------------------------------------------------------
1169 
1170 /* Purpose: Safely set the denominator of an mpq number */
1171 
SLIP_mpq_set_den(mpq_t x,const mpz_t y)1172 SLIP_info SLIP_mpq_set_den
1173 (
1174     mpq_t x,
1175     const mpz_t y
1176 )
1177 {
1178     SLIP_GMPQ_WRAPPER_START (x) ;
1179     mpq_set_den (x, y) ;
1180     SLIP_GMP_WRAPPER_FINISH ;
1181     return (SLIP_OK) ;
1182 }
1183 
1184 //------------------------------------------------------------------------------
1185 // SLIP_mpq_get_den
1186 //------------------------------------------------------------------------------
1187 
1188 /* Purpose: Safely set an mpz number = denominator of an mpq number */
1189 
SLIP_mpq_get_den(mpz_t x,const mpq_t y)1190 SLIP_info SLIP_mpq_get_den
1191 (
1192     mpz_t x,
1193     const mpq_t y
1194 )
1195 {
1196     SLIP_GMPZ_WRAPPER_START (x) ;
1197     mpq_get_den (x, y) ;
1198     SLIP_GMP_WRAPPER_FINISH ;
1199     return (SLIP_OK) ;
1200 }
1201 
1202 //------------------------------------------------------------------------------
1203 // SLIP_mpq_get_d
1204 //------------------------------------------------------------------------------
1205 
1206 /* Purpose: Safely set a double = a mpq number*/
1207 
SLIP_mpq_get_d(double * x,const mpq_t y)1208 SLIP_info SLIP_mpq_get_d
1209 (
1210     double *x,
1211     const mpq_t y
1212 )
1213 {
1214     SLIP_GMP_WRAPPER_START ;
1215     *x = mpq_get_d (y) ;
1216     SLIP_GMP_WRAPPER_FINISH ;
1217     return (SLIP_OK) ;
1218 }
1219 
1220 //------------------------------------------------------------------------------
1221 // SLIP_mpq_abs
1222 //------------------------------------------------------------------------------
1223 
1224 /* Purpose: Safely set an mpq number = absolute value of mpq */
1225 
SLIP_mpq_abs(mpq_t x,const mpq_t y)1226 SLIP_info SLIP_mpq_abs
1227 (
1228     mpq_t x,
1229     const mpq_t y
1230 )
1231 {
1232     SLIP_GMPQ_WRAPPER_START (x) ;
1233     mpq_abs (x, y) ;
1234     SLIP_GMP_WRAPPER_FINISH ;
1235     return (SLIP_OK) ;
1236 }
1237 
1238 //------------------------------------------------------------------------------
1239 // SLIP_mpq_add
1240 //------------------------------------------------------------------------------
1241 
1242 /* Purpose: Safely add two mpq numbers, i.e., x = y+z */
1243 
SLIP_mpq_add(mpq_t x,const mpq_t y,const mpq_t z)1244 SLIP_info SLIP_mpq_add
1245 (
1246     mpq_t x,
1247     const mpq_t y,
1248     const mpq_t z
1249 )
1250 {
1251     SLIP_GMPQ_WRAPPER_START (x) ;
1252     mpq_add (x, y, z) ;
1253     SLIP_GMP_WRAPPER_FINISH ;
1254     return (SLIP_OK) ;
1255 }
1256 
1257 //------------------------------------------------------------------------------
1258 // SLIP_mpq_mul
1259 //------------------------------------------------------------------------------
1260 
1261 /* Purpose: Safely multiply two mpq numbers, i.e., x = y*z */
SLIP_mpq_mul(mpq_t x,const mpq_t y,const mpq_t z)1262 SLIP_info SLIP_mpq_mul
1263 (
1264     mpq_t x,
1265     const mpq_t y,
1266     const mpq_t z
1267 )
1268 {
1269     SLIP_GMPQ_WRAPPER_START (x) ;
1270     mpq_mul (x, y, z) ;
1271     SLIP_GMP_WRAPPER_FINISH ;
1272     return (SLIP_OK) ;
1273 }
1274 
1275 //------------------------------------------------------------------------------
1276 // SLIP_mpq_div
1277 //------------------------------------------------------------------------------
1278 
1279 /* Purpose: Safely divide two mpq numbers, i.e., x = y/z */
1280 
SLIP_mpq_div(mpq_t x,const mpq_t y,const mpq_t z)1281 SLIP_info SLIP_mpq_div
1282 (
1283     mpq_t x,
1284     const mpq_t y,
1285     const mpq_t z
1286 )
1287 {
1288     SLIP_GMPQ_WRAPPER_START (x) ;
1289     mpq_div (x, y, z) ;
1290     SLIP_GMP_WRAPPER_FINISH ;
1291     return (SLIP_OK) ;
1292 }
1293 
1294 //------------------------------------------------------------------------------
1295 // SLIP_mpq_cmp
1296 //------------------------------------------------------------------------------
1297 
1298 /* Purpose: Safely compare two mpq numbers,
1299  * r > 0 if x > y, r = 0 if x = y, and r < 0 if x < y */
1300 
SLIP_mpq_cmp(int * r,const mpq_t x,const mpq_t y)1301 SLIP_info SLIP_mpq_cmp
1302 (
1303     int *r,
1304     const mpq_t x,
1305     const mpq_t y
1306 )
1307 {
1308     SLIP_GMP_WRAPPER_START ;
1309     *r = mpq_cmp (x, y) ;
1310     SLIP_GMP_WRAPPER_FINISH ;
1311     return (SLIP_OK) ;
1312 }
1313 
1314 //------------------------------------------------------------------------------
1315 // SLIP_mpq_cmp_ui
1316 //------------------------------------------------------------------------------
1317 
1318 /* Purpose: Safely compare x and num/den. r > 0 if x > num/den,
1319  * r = 0 if x = num/den, and r < 0 if x < num/den */
1320 
SLIP_mpq_cmp_ui(int * r,const mpq_t x,const uint64_t num,const uint64_t den)1321 SLIP_info SLIP_mpq_cmp_ui
1322 (
1323     int *r,
1324     const mpq_t x,
1325     const uint64_t num,
1326     const uint64_t den
1327 )
1328 {
1329     SLIP_GMP_WRAPPER_START ;
1330     *r = mpq_cmp_ui (x, (unsigned long int) num, (unsigned long int) den) ;
1331     SLIP_GMP_WRAPPER_FINISH ;
1332     return (SLIP_OK) ;
1333 }
1334 
1335 //------------------------------------------------------------------------------
1336 // SLIP_mpq_equal
1337 //------------------------------------------------------------------------------
1338 
1339 /* Purpose: Safely check if two mpq numbers equal,
1340  * r = 0 (r = false) if x != y, r != 0 (r = true) if x = y */
1341 
SLIP_mpq_equal(int * r,const mpq_t x,const mpq_t y)1342 SLIP_info SLIP_mpq_equal
1343 (
1344     int *r,
1345     const mpq_t x,
1346     const mpq_t y
1347 )
1348 {
1349     SLIP_GMP_WRAPPER_START ;
1350     *r = mpq_equal (x, y) ;
1351     SLIP_GMP_WRAPPER_FINISH ;
1352     return (SLIP_OK) ;
1353 }
1354 
1355 //------------------------------------------------------------------------------
1356 // SLIP_mpq_sgn
1357 //------------------------------------------------------------------------------
1358 
1359 /* Purpose: Safely set sgn = 0 if x = 0, otherwise, sgn = x/|x| */
1360 
SLIP_mpq_sgn(int * sgn,const mpq_t x)1361 SLIP_info SLIP_mpq_sgn
1362 (
1363     int *sgn,
1364     const mpq_t x
1365 )
1366 {
1367     SLIP_GMP_WRAPPER_START ;
1368     *sgn = mpq_sgn (x) ;
1369     SLIP_GMP_WRAPPER_FINISH ;
1370     return (SLIP_OK) ;
1371 }
1372 
1373 //------------------------------------------------------------------------------
1374 //------------------------------------------------------------------------------
1375 //-------------------------Floating Point (mpfr type) functions-----------------
1376 //------------------------------------------------------------------------------
1377 //------------------------------------------------------------------------------
1378 
1379 //------------------------------------------------------------------------------
1380 // SLIP_mpfr_init2
1381 //------------------------------------------------------------------------------
1382 
1383 /* Purpose: Safely initialize an mpfr_t number */
1384 
SLIP_mpfr_init2(mpfr_t x,uint64_t size)1385 SLIP_info SLIP_mpfr_init2
1386 (
1387     mpfr_t x,       // Floating point number to initialize
1388     uint64_t size    // # of bits in x
1389 )
1390 {
1391     SLIP_GMPFR_WRAPPER_START (x) ;
1392     mpfr_init2 (x, (unsigned long int) size) ;
1393     SLIP_GMP_WRAPPER_FINISH ;
1394     return (SLIP_OK) ;
1395 }
1396 
1397 //------------------------------------------------------------------------------
1398 // SLIP_mpfr_set
1399 //------------------------------------------------------------------------------
1400 
1401 /* Purpose: Safely set an mpfr number = to an mpfr number, i.e., x = y */
1402 
SLIP_mpfr_set(mpfr_t x,const mpfr_t y,const mpfr_rnd_t rnd)1403 SLIP_info SLIP_mpfr_set
1404 (
1405     mpfr_t x,
1406     const mpfr_t y,
1407     const mpfr_rnd_t rnd
1408 )
1409 {
1410     SLIP_GMPFR_WRAPPER_START (x) ;
1411     mpfr_set (x, y, rnd) ;
1412     SLIP_GMP_WRAPPER_FINISH ;
1413     return (SLIP_OK) ;
1414 }
1415 
1416 //------------------------------------------------------------------------------
1417 // SLIP_mpfr_set_d
1418 //------------------------------------------------------------------------------
1419 
1420 /* Purpose: Safely set an mpfr number = to a double, i.e., x = y */
1421 
SLIP_mpfr_set_d(mpfr_t x,const double y,const mpfr_rnd_t rnd)1422 SLIP_info SLIP_mpfr_set_d
1423 (
1424     mpfr_t x,
1425     const double y,
1426     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1427 )
1428 {
1429     SLIP_GMPFR_WRAPPER_START (x) ;
1430     mpfr_set_d (x, y, rnd) ;
1431     SLIP_GMP_WRAPPER_FINISH ;
1432     return (SLIP_OK) ;
1433 }
1434 
1435 
1436 //------------------------------------------------------------------------------
1437 // SLIP_mpfr_set_si
1438 //------------------------------------------------------------------------------
1439 
1440 /* Purpose: Safely set an mpfr number = to a signed int, i.e., x = y */
1441 
SLIP_mpfr_set_si(mpfr_t x,int64_t y,const mpfr_rnd_t rnd)1442 SLIP_info SLIP_mpfr_set_si
1443 (
1444     mpfr_t x,
1445     int64_t y,
1446     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1447 )
1448 {
1449     SLIP_GMPFR_WRAPPER_START (x) ;
1450     mpfr_set_si (x, y, rnd) ;
1451     SLIP_GMP_WRAPPER_FINISH ;
1452     return (SLIP_OK) ;
1453 }
1454 
1455 //------------------------------------------------------------------------------
1456 // SLIP_mpfr_set_q
1457 //------------------------------------------------------------------------------
1458 
1459 /* Purpose: Safely set an mpfr number = to an mpq number */
1460 
SLIP_mpfr_set_q(mpfr_t x,const mpq_t y,const mpfr_rnd_t rnd)1461 SLIP_info SLIP_mpfr_set_q
1462 (
1463     mpfr_t x,
1464     const mpq_t y,
1465     const mpfr_rnd_t rnd
1466 )
1467 {
1468     SLIP_GMPFR_WRAPPER_START (x) ;
1469     mpfr_set_q (x, y, rnd) ;
1470     SLIP_GMP_WRAPPER_FINISH ;
1471     return (SLIP_OK) ;
1472 }
1473 
1474 //------------------------------------------------------------------------------
1475 // SLIP_mpfr_set_z
1476 //------------------------------------------------------------------------------
1477 
1478 /* Purpose: Safely set an mpfr number = to an mpz number */
1479 
SLIP_mpfr_set_z(mpfr_t x,const mpz_t y,const mpfr_rnd_t rnd)1480 SLIP_info SLIP_mpfr_set_z
1481 (
1482     mpfr_t x,
1483     const mpz_t y,
1484     const mpfr_rnd_t rnd
1485 )
1486 {
1487     SLIP_GMPFR_WRAPPER_START (x) ;
1488     mpfr_set_z (x, y, rnd) ;
1489     SLIP_GMP_WRAPPER_FINISH ;
1490     return (SLIP_OK) ;
1491 }
1492 
1493 //------------------------------------------------------------------------------
1494 // SLIP_mpfr_get_z
1495 //------------------------------------------------------------------------------
1496 
1497 /* Purpose: Safely set an mpz number = to an mpfr number, i.e., x = y */
1498 
SLIP_mpfr_get_z(mpz_t x,const mpfr_t y,const mpfr_rnd_t rnd)1499 SLIP_info SLIP_mpfr_get_z
1500 (
1501     mpz_t x,
1502     const mpfr_t y,
1503     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1504 )
1505 {
1506     SLIP_GMPZ_WRAPPER_START (x) ;
1507     mpfr_get_z (x, y, rnd) ;
1508     SLIP_GMP_WRAPPER_FINISH ;
1509     return (SLIP_OK) ;
1510 }
1511 
1512 //------------------------------------------------------------------------------
1513 // SLIP_mpfr_get_q
1514 //------------------------------------------------------------------------------
1515 
1516 /* Purpose: Safely set an mpq number = to an mpfr number, i.e., x = y */
1517 
SLIP_mpfr_get_q(mpq_t x,const mpfr_t y,const mpfr_rnd_t rnd)1518 SLIP_info SLIP_mpfr_get_q
1519 (
1520     mpq_t x,
1521     const mpfr_t y,
1522     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1523 )
1524 {
1525     SLIP_GMPQ_WRAPPER_START (x) ;
1526     mpfr_get_q (x, y) ;
1527     SLIP_GMP_WRAPPER_FINISH ;
1528     return (SLIP_OK) ;
1529 }
1530 
1531 //------------------------------------------------------------------------------
1532 // SLIP_mpfr_get_d
1533 //------------------------------------------------------------------------------
1534 
1535 /* Purpose: Safely set a double = to a mpfr number, i.e., x = y */
1536 
SLIP_mpfr_get_d(double * x,const mpfr_t y,const mpfr_rnd_t rnd)1537 SLIP_info SLIP_mpfr_get_d
1538 (
1539     double *x,
1540     const mpfr_t y,
1541     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1542 )
1543 {
1544     SLIP_GMP_WRAPPER_START ;
1545     *x = mpfr_get_d (y, rnd) ;
1546     SLIP_GMP_WRAPPER_FINISH ;
1547     return (SLIP_OK) ;
1548 }
1549 
1550 //------------------------------------------------------------------------------
1551 // SLIP_mpfr_get_si
1552 //------------------------------------------------------------------------------
1553 
1554 /* Purpose: Safely set a signed int = to a mpfr number, i.e., x = y */
1555 
SLIP_mpfr_get_si(int64_t * x,const mpfr_t y,const mpfr_rnd_t rnd)1556 SLIP_info SLIP_mpfr_get_si
1557 (
1558     int64_t *x,
1559     const mpfr_t y,
1560     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1561 )
1562 {
1563     SLIP_GMP_WRAPPER_START ;
1564     *x = mpfr_get_si (y, rnd) ;
1565     SLIP_GMP_WRAPPER_FINISH ;
1566     return (SLIP_OK) ;
1567 }
1568 
1569 //------------------------------------------------------------------------------
1570 // SLIP_mpfr_mul
1571 //------------------------------------------------------------------------------
1572 
1573 /* Purpose: Safely multiply mpfr numbers, x = y*z */
1574 
SLIP_mpfr_mul(mpfr_t x,const mpfr_t y,const mpfr_t z,const mpfr_rnd_t rnd)1575 SLIP_info SLIP_mpfr_mul
1576 (
1577     mpfr_t x,
1578     const mpfr_t y,
1579     const mpfr_t z,
1580     const mpfr_rnd_t rnd  // MPFR rounding mode
1581 )
1582 {
1583     SLIP_GMPFR_WRAPPER_START (x) ;
1584     mpfr_mul (x, y, z, rnd) ;
1585     SLIP_GMP_WRAPPER_FINISH ;
1586     return (SLIP_OK) ;
1587 }
1588 
1589 //------------------------------------------------------------------------------
1590 // SLIP_mpfr_mul_d
1591 //------------------------------------------------------------------------------
1592 
1593 /* Purpose: Safely set an mpfr number = to a product of an mpfr_t and double,
1594  * i.e., x = y*z
1595  */
1596 
SLIP_mpfr_mul_d(mpfr_t x,const mpfr_t y,const double z,const mpfr_rnd_t rnd)1597 SLIP_info SLIP_mpfr_mul_d
1598 (
1599     mpfr_t x,
1600     const mpfr_t y,
1601     const double z,
1602     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1603 )
1604 {
1605     SLIP_GMPFR_WRAPPER_START (x) ;
1606     mpfr_mul_d (x, y, z, rnd) ;
1607     SLIP_GMP_WRAPPER_FINISH ;
1608     return (SLIP_OK) ;
1609 }
1610 
1611 //------------------------------------------------------------------------------
1612 // SLIP_mpfr_div_d
1613 //------------------------------------------------------------------------------
1614 
1615 /* Purpose: Safely set a mpfr number = a mpfr number divided by a double,
1616  * i.e., x = y/z
1617  */
1618 
SLIP_mpfr_div_d(mpfr_t x,const mpfr_t y,const double z,const mpfr_rnd_t rnd)1619 SLIP_info SLIP_mpfr_div_d
1620 (
1621     mpfr_t x,
1622     const mpfr_t y,
1623     const double z,
1624     const mpfr_rnd_t rnd  // MPFR rounding scheme used
1625 )
1626 {
1627     SLIP_GMPFR_WRAPPER_START (x) ;
1628     mpfr_div_d (x, y, z, rnd) ;
1629     SLIP_GMP_WRAPPER_FINISH ;
1630     return (SLIP_OK) ;
1631 }
1632 
1633 //------------------------------------------------------------------------------
1634 // SLIP_mpfr_ui_pow_ui
1635 //------------------------------------------------------------------------------
1636 
1637 /* Purpose: Safely set an mpfr number = power of two ints, i.e.,
1638  * x = y^z
1639  */
1640 
SLIP_mpfr_ui_pow_ui(mpfr_t x,const uint64_t y,const uint64_t z,const mpfr_rnd_t rnd)1641 SLIP_info SLIP_mpfr_ui_pow_ui
1642 (
1643     mpfr_t x,
1644     const uint64_t y,
1645     const uint64_t z,
1646     const mpfr_rnd_t rnd  // MPFR rounding mode
1647 )
1648 {
1649     SLIP_GMPFR_WRAPPER_START (x) ;
1650     mpfr_ui_pow_ui (x, (unsigned long int) y, (unsigned long int) z, rnd) ;
1651     SLIP_GMP_WRAPPER_FINISH ;
1652     return (SLIP_OK) ;
1653 }
1654 
1655 //------------------------------------------------------------------------------
1656 // SLIP_mpfr_log2
1657 //------------------------------------------------------------------------------
1658 
1659 /* Purpose: Safely take the log2 of an mpfr number */
1660 
1661 #if 0
1662 /* This function is currently unused, but kept here for future reference. */
1663 
1664 SLIP_info SLIP_mpfr_log2
1665 (
1666     mpfr_t x,
1667     const mpfr_t y,
1668     const mpfr_rnd_t rnd
1669 )
1670 {
1671     SLIP_GMPFR_WRAPPER_START (x) ;
1672     mpfr_log2 (x, y, rnd) ;
1673     SLIP_GMP_WRAPPER_FINISH ;
1674     return (SLIP_OK) ;
1675 }
1676 
1677 #endif
1678 
1679 //------------------------------------------------------------------------------
1680 // SLIP_mpfr_sgn
1681 //------------------------------------------------------------------------------
1682 
1683 /* Purpose: Safely set sgn = 0 if x = 0, otherwise, sgn = x/|x| */
1684 
SLIP_mpfr_sgn(int * sgn,const mpfr_t x)1685 SLIP_info SLIP_mpfr_sgn
1686 (
1687     int *sgn,
1688     const mpfr_t x
1689 )
1690 {
1691     SLIP_GMP_WRAPPER_START ;
1692     *sgn = mpfr_sgn (x) ;
1693     SLIP_GMP_WRAPPER_FINISH ;
1694     return (SLIP_OK) ;
1695 }
1696 
1697 //------------------------------------------------------------------------------
1698 // SLIP_mpfr_free_cache
1699 //------------------------------------------------------------------------------
1700 
1701 /* Purpose: Safely free all caches and pools used by MPFR internally */
1702 
SLIP_mpfr_free_cache(void)1703 SLIP_info SLIP_mpfr_free_cache ( void )
1704 {
1705     SLIP_GMP_WRAPPER_START ;
1706     mpfr_free_cache ( ) ;
1707     SLIP_GMP_WRAPPER_FINISH ;
1708     return (SLIP_OK) ;
1709 }
1710 
1711