1 /*
2     Copyright (C) 2009 William Hart
3 
4     This file is part of FLINT.
5 
6     FLINT is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #include <stdlib.h>
13 #include <gmp.h>
14 #include "flint.h"
15 #include "fmpz.h"
16 
_fmpz_new_mpz(void)17 __mpz_struct * _fmpz_new_mpz(void)
18 {
19     __mpz_struct * mpz_ptr = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct));
20     mpz_init2(mpz_ptr, 2*FLINT_BITS);
21     return mpz_ptr;
22 }
23 
_fmpz_clear_mpz(fmpz f)24 void _fmpz_clear_mpz(fmpz f)
25 {
26     mpz_clear(COEFF_TO_PTR(f));
27     flint_free(COEFF_TO_PTR(f));
28 }
29 
_fmpz_cleanup_mpz_content(void)30 void _fmpz_cleanup_mpz_content(void)
31 {
32 }
33 
_fmpz_cleanup(void)34 void _fmpz_cleanup(void)
35 {
36 }
37 
_fmpz_promote(fmpz_t f)38 __mpz_struct * _fmpz_promote(fmpz_t f)
39 {
40     if (!COEFF_IS_MPZ(*f))  /* f is small so promote it first */
41     {
42         __mpz_struct * mpz_ptr = _fmpz_new_mpz();
43         *f = PTR_TO_COEFF(mpz_ptr);
44         return mpz_ptr;
45     }
46     else  /* f is large already, just return the pointer */
47         return COEFF_TO_PTR(*f);
48 }
49 
_fmpz_promote_val(fmpz_t f)50 __mpz_struct * _fmpz_promote_val(fmpz_t f)
51 {
52     fmpz c = *f;
53     if (!COEFF_IS_MPZ(c))  /* f is small so promote it */
54     {
55         __mpz_struct * mpz_ptr = _fmpz_new_mpz();
56         *f = PTR_TO_COEFF(mpz_ptr);
57         flint_mpz_set_si(mpz_ptr, c);
58         return mpz_ptr;
59     }
60     else  /* f is large already, just return the pointer */
61         return COEFF_TO_PTR(*f);
62 }
63 
_fmpz_demote_val(fmpz_t f)64 void _fmpz_demote_val(fmpz_t f)
65 {
66     __mpz_struct * mpz_ptr = COEFF_TO_PTR(*f);
67     int size = mpz_ptr->_mp_size;
68 
69     if (!(((unsigned int) size + 1U) & ~2U))  /* size +-1 */
70     {
71         ulong uval = mpz_ptr->_mp_d[0];
72 
73         if (uval <= (ulong) COEFF_MAX)
74         {
75             _fmpz_clear_mpz(*f);
76             *f = size * (fmpz) uval;
77         }
78     }
79     else if (size == 0)  /* value is 0 */
80     {
81         _fmpz_clear_mpz(*f);
82         *f = 0;
83     }
84 
85     /* don't do anything if value has to be multi precision */
86 }
87 
_fmpz_init_readonly_mpz(fmpz_t f,const mpz_t z)88 void _fmpz_init_readonly_mpz(fmpz_t f, const mpz_t z)
89 {
90    __mpz_struct * mpz_ptr = (__mpz_struct *) flint_malloc(sizeof(__mpz_struct));
91     *f = PTR_TO_COEFF(mpz_ptr);
92     *mpz_ptr = *z;
93 }
94 
_fmpz_clear_readonly_mpz(mpz_t z)95 void _fmpz_clear_readonly_mpz(mpz_t z)
96 {
97     if (((z->_mp_size == 1 || z->_mp_size == -1) && (z->_mp_d[0] <= COEFF_MAX))
98         || (z->_mp_size == 0))
99     {
100         mpz_clear(z);
101     }
102 }
103