1274074Sngie/* mpq_inv(dest,src) -- invert a rational number, i.e. set DEST to SRC
2274074Sngie   with the numerator and denominator swapped.
3274074Sngie
4274074SngieCopyright 1991, 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
5274074Sngie
6292278SngieThis file is part of the GNU MP Library.
7274074Sngie
8292278SngieThe GNU MP Library is free software; you can redistribute it and/or modify
9274074Sngieit under the terms of the GNU Lesser General Public License as published by
10292278Sngiethe Free Software Foundation; either version 3 of the License, or (at your
11292278Sngieoption) any later version.
12274074Sngie
13274074SngieThe GNU MP Library is distributed in the hope that it will be useful, but
14274074SngieWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15274074Sngieor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16274074SngieLicense for more details.
17274074Sngie
18274074SngieYou should have received a copy of the GNU Lesser General Public License
19274074Sngiealong with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
20274074Sngie
21274074Sngie#include "gmp.h"
22274074Sngie#include "gmp-impl.h"
23274074Sngie
24274074Sngievoid
25274074Sngiempq_inv (MP_RAT *dest, const MP_RAT *src)
26274074Sngie{
27274074Sngie  mp_size_t num_size = src->_mp_num._mp_size;
28274074Sngie  mp_size_t den_size = src->_mp_den._mp_size;
29274074Sngie
30274074Sngie  if (num_size == 0)
31274074Sngie    DIVIDE_BY_ZERO;
32274074Sngie
33274074Sngie  if (num_size < 0)
34274074Sngie    {
35274074Sngie      num_size = -num_size;
36274074Sngie      den_size = -den_size;
37274074Sngie    }
38274074Sngie  dest->_mp_den._mp_size = num_size;
39274074Sngie  dest->_mp_num._mp_size = den_size;
40274074Sngie
41274074Sngie  /* If dest == src we may just swap the numerator and denominator, but
42274074Sngie     we have to ensure the new denominator is positive.  */
43
44  if (dest == src)
45    {
46      mp_size_t alloc = dest->_mp_num._mp_alloc;
47      mp_ptr limb_ptr = dest->_mp_num._mp_d;
48
49      dest->_mp_num._mp_alloc = dest->_mp_den._mp_alloc;
50      dest->_mp_num._mp_d = dest->_mp_den._mp_d;
51
52      dest->_mp_den._mp_alloc = alloc;
53      dest->_mp_den._mp_d = limb_ptr;
54    }
55  else
56    {
57      den_size = ABS (den_size);
58      if (dest->_mp_num._mp_alloc < den_size)
59	_mpz_realloc (&(dest->_mp_num), den_size);
60
61      if (dest->_mp_den._mp_alloc < num_size)
62	_mpz_realloc (&(dest->_mp_den), num_size);
63
64      MPN_COPY (dest->_mp_num._mp_d, src->_mp_den._mp_d, den_size);
65      MPN_COPY (dest->_mp_den._mp_d, src->_mp_num._mp_d, num_size);
66    }
67}
68