1 /* mpz_sqrt(root, u) -- Set ROOT to floor(sqrt(U)).
3 Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2005 Free Software Foundation,
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MP Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 #include <stdio.h> /* for NULL */
26 mpz_sqrt (mpz_ptr root
, mpz_srcptr op
)
28 mp_size_t op_size
, root_size
;
29 mp_ptr root_ptr
, op_ptr
;
30 mp_ptr free_me
= NULL
;
31 mp_size_t free_me_size
;
35 op_size
= op
->_mp_size
;
44 /* The size of the root is accurate after this simple calculation. */
45 root_size
= (op_size
+ 1) / 2;
47 root_ptr
= root
->_mp_d
;
50 if (root
->_mp_alloc
< root_size
)
52 if (root_ptr
== op_ptr
)
55 free_me_size
= root
->_mp_alloc
;
58 (*__gmp_free_func
) (root_ptr
, root
->_mp_alloc
* BYTES_PER_MP_LIMB
);
60 root
->_mp_alloc
= root_size
;
61 root_ptr
= (mp_ptr
) (*__gmp_allocate_func
) (root_size
* BYTES_PER_MP_LIMB
);
62 root
->_mp_d
= root_ptr
;
66 /* Make OP not overlap with ROOT. */
67 if (root_ptr
== op_ptr
)
69 /* ROOT and OP are identical. Allocate temporary space for OP. */
70 op_ptr
= (mp_ptr
) TMP_ALLOC (op_size
* BYTES_PER_MP_LIMB
);
71 /* Copy to the temporary space. Hack: Avoid temporary variable
73 MPN_COPY (op_ptr
, root_ptr
, op_size
);
77 mpn_sqrtrem (root_ptr
, NULL
, op_ptr
, op_size
);
79 root
->_mp_size
= root_size
;
82 (*__gmp_free_func
) (free_me
, free_me_size
* BYTES_PER_MP_LIMB
);