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