xref: /dflybsd-src/contrib/gmp/mpq/inv.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /* mpq_inv(dest,src) -- invert a rational number, i.e. set DEST to SRC
2*86d7f5d3SJohn Marino    with the numerator and denominator swapped.
3*86d7f5d3SJohn Marino 
4*86d7f5d3SJohn Marino Copyright 1991, 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
5*86d7f5d3SJohn Marino 
6*86d7f5d3SJohn Marino This file is part of the GNU MP Library.
7*86d7f5d3SJohn Marino 
8*86d7f5d3SJohn Marino The GNU MP Library is free software; you can redistribute it and/or modify
9*86d7f5d3SJohn Marino it under the terms of the GNU Lesser General Public License as published by
10*86d7f5d3SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
11*86d7f5d3SJohn Marino option) any later version.
12*86d7f5d3SJohn Marino 
13*86d7f5d3SJohn Marino The GNU MP Library is distributed in the hope that it will be useful, but
14*86d7f5d3SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15*86d7f5d3SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16*86d7f5d3SJohn Marino License for more details.
17*86d7f5d3SJohn Marino 
18*86d7f5d3SJohn Marino You should have received a copy of the GNU Lesser General Public License
19*86d7f5d3SJohn Marino along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
20*86d7f5d3SJohn Marino 
21*86d7f5d3SJohn Marino #include "gmp.h"
22*86d7f5d3SJohn Marino #include "gmp-impl.h"
23*86d7f5d3SJohn Marino 
24*86d7f5d3SJohn Marino void
mpq_inv(MP_RAT * dest,const MP_RAT * src)25*86d7f5d3SJohn Marino mpq_inv (MP_RAT *dest, const MP_RAT *src)
26*86d7f5d3SJohn Marino {
27*86d7f5d3SJohn Marino   mp_size_t num_size = src->_mp_num._mp_size;
28*86d7f5d3SJohn Marino   mp_size_t den_size = src->_mp_den._mp_size;
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino   if (num_size == 0)
31*86d7f5d3SJohn Marino     DIVIDE_BY_ZERO;
32*86d7f5d3SJohn Marino 
33*86d7f5d3SJohn Marino   if (num_size < 0)
34*86d7f5d3SJohn Marino     {
35*86d7f5d3SJohn Marino       num_size = -num_size;
36*86d7f5d3SJohn Marino       den_size = -den_size;
37*86d7f5d3SJohn Marino     }
38*86d7f5d3SJohn Marino   dest->_mp_den._mp_size = num_size;
39*86d7f5d3SJohn Marino   dest->_mp_num._mp_size = den_size;
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino   /* If dest == src we may just swap the numerator and denominator, but
42*86d7f5d3SJohn Marino      we have to ensure the new denominator is positive.  */
43*86d7f5d3SJohn Marino 
44*86d7f5d3SJohn Marino   if (dest == src)
45*86d7f5d3SJohn Marino     {
46*86d7f5d3SJohn Marino       mp_size_t alloc = dest->_mp_num._mp_alloc;
47*86d7f5d3SJohn Marino       mp_ptr limb_ptr = dest->_mp_num._mp_d;
48*86d7f5d3SJohn Marino 
49*86d7f5d3SJohn Marino       dest->_mp_num._mp_alloc = dest->_mp_den._mp_alloc;
50*86d7f5d3SJohn Marino       dest->_mp_num._mp_d = dest->_mp_den._mp_d;
51*86d7f5d3SJohn Marino 
52*86d7f5d3SJohn Marino       dest->_mp_den._mp_alloc = alloc;
53*86d7f5d3SJohn Marino       dest->_mp_den._mp_d = limb_ptr;
54*86d7f5d3SJohn Marino     }
55*86d7f5d3SJohn Marino   else
56*86d7f5d3SJohn Marino     {
57*86d7f5d3SJohn Marino       den_size = ABS (den_size);
58*86d7f5d3SJohn Marino       if (dest->_mp_num._mp_alloc < den_size)
59*86d7f5d3SJohn Marino 	_mpz_realloc (&(dest->_mp_num), den_size);
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino       if (dest->_mp_den._mp_alloc < num_size)
62*86d7f5d3SJohn Marino 	_mpz_realloc (&(dest->_mp_den), num_size);
63*86d7f5d3SJohn Marino 
64*86d7f5d3SJohn Marino       MPN_COPY (dest->_mp_num._mp_d, src->_mp_den._mp_d, den_size);
65*86d7f5d3SJohn Marino       MPN_COPY (dest->_mp_den._mp_d, src->_mp_num._mp_d, num_size);
66*86d7f5d3SJohn Marino     }
67*86d7f5d3SJohn Marino }
68