Home | History | Annotate | Line # | Download | only in gdb
gmp-utils.h revision 1.1.1.2
      1      1.1  christos /* Miscellaneous routines making it easier to use GMP within GDB's framework.
      2      1.1  christos 
      3  1.1.1.2  christos    Copyright (C) 2019-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of GDB.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19      1.1  christos 
     20      1.1  christos #ifndef GMP_UTILS_H
     21      1.1  christos #define GMP_UTILS_H
     22      1.1  christos 
     23      1.1  christos /* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get
     24      1.1  christos    access to GMP's various formatting functions.  */
     25      1.1  christos #include <stdio.h>
     26      1.1  christos #include <stdarg.h>
     27      1.1  christos #include <gmp.h>
     28      1.1  christos #include "gdbsupport/traits.h"
     29      1.1  christos 
     30      1.1  christos /* Same as gmp_asprintf, but returning an std::string.  */
     31      1.1  christos 
     32      1.1  christos std::string gmp_string_printf (const char *fmt, ...);
     33      1.1  christos 
     34  1.1.1.2  christos struct gdb_mpq;
     35  1.1.1.2  christos struct gdb_mpf;
     36  1.1.1.2  christos 
     37      1.1  christos /* A class to make it easier to use GMP's mpz_t values within GDB.  */
     38      1.1  christos 
     39      1.1  christos struct gdb_mpz
     40      1.1  christos {
     41      1.1  christos   /* Constructors.  */
     42  1.1.1.2  christos   gdb_mpz () { mpz_init (m_val); }
     43      1.1  christos 
     44      1.1  christos   explicit gdb_mpz (const mpz_t &from_val)
     45      1.1  christos   {
     46  1.1.1.2  christos     mpz_init (m_val);
     47  1.1.1.2  christos     mpz_set (m_val, from_val);
     48      1.1  christos   }
     49      1.1  christos 
     50      1.1  christos   gdb_mpz (const gdb_mpz &from)
     51      1.1  christos   {
     52  1.1.1.2  christos     mpz_init (m_val);
     53  1.1.1.2  christos     mpz_set (m_val, from.m_val);
     54      1.1  christos   }
     55      1.1  christos 
     56      1.1  christos   /* Initialize using the given integral value.
     57      1.1  christos 
     58      1.1  christos      The main advantage of this method is that it handles both signed
     59      1.1  christos      and unsigned types, with no size restriction.  */
     60      1.1  christos   template<typename T, typename = gdb::Requires<std::is_integral<T>>>
     61      1.1  christos   explicit gdb_mpz (T src)
     62      1.1  christos   {
     63  1.1.1.2  christos     mpz_init (m_val);
     64      1.1  christos     set (src);
     65      1.1  christos   }
     66      1.1  christos 
     67      1.1  christos   explicit gdb_mpz (gdb_mpz &&from)
     68      1.1  christos   {
     69  1.1.1.2  christos     mpz_init (m_val);
     70  1.1.1.2  christos     mpz_swap (m_val, from.m_val);
     71      1.1  christos   }
     72      1.1  christos 
     73      1.1  christos 
     74      1.1  christos   gdb_mpz &operator= (const gdb_mpz &from)
     75      1.1  christos   {
     76  1.1.1.2  christos     mpz_set (m_val, from.m_val);
     77      1.1  christos     return *this;
     78      1.1  christos   }
     79      1.1  christos 
     80      1.1  christos   gdb_mpz &operator= (gdb_mpz &&other)
     81      1.1  christos   {
     82  1.1.1.2  christos     mpz_swap (m_val, other.m_val);
     83      1.1  christos     return *this;
     84      1.1  christos   }
     85      1.1  christos 
     86      1.1  christos   template<typename T, typename = gdb::Requires<std::is_integral<T>>>
     87      1.1  christos   gdb_mpz &operator= (T src)
     88      1.1  christos   {
     89      1.1  christos     set (src);
     90      1.1  christos     return *this;
     91      1.1  christos   }
     92      1.1  christos 
     93  1.1.1.2  christos   gdb_mpz &operator= (bool src)
     94  1.1.1.2  christos   {
     95  1.1.1.2  christos     mpz_set_ui (m_val, (unsigned long) src);
     96  1.1.1.2  christos     return *this;
     97  1.1.1.2  christos   }
     98  1.1.1.2  christos 
     99  1.1.1.2  christos   /* Initialize this value from a string and a base.  Returns true if
    100  1.1.1.2  christos      the string was parsed successfully, false otherwise.  */
    101  1.1.1.2  christos   bool set (const char *str, int base)
    102  1.1.1.2  christos   {
    103  1.1.1.2  christos     return mpz_set_str (m_val, str, base) != -1;
    104  1.1.1.2  christos   }
    105  1.1.1.2  christos 
    106  1.1.1.2  christos   /* Return a new value that is BASE**EXP.  */
    107  1.1.1.2  christos   static gdb_mpz pow (unsigned long base, unsigned long exp)
    108  1.1.1.2  christos   {
    109  1.1.1.2  christos     gdb_mpz result;
    110  1.1.1.2  christos     mpz_ui_pow_ui (result.m_val, base, exp);
    111  1.1.1.2  christos     return result;
    112  1.1.1.2  christos   }
    113  1.1.1.2  christos 
    114  1.1.1.2  christos   /* Return a new value that is this value raised to EXP.  */
    115  1.1.1.2  christos   gdb_mpz pow (unsigned long exp) const
    116  1.1.1.2  christos   {
    117  1.1.1.2  christos     gdb_mpz result;
    118  1.1.1.2  christos     mpz_pow_ui (result.m_val, m_val, exp);
    119  1.1.1.2  christos     return result;
    120  1.1.1.2  christos   }
    121  1.1.1.2  christos 
    122  1.1.1.2  christos   /* Convert this value to an integer of the given type.
    123      1.1  christos 
    124      1.1  christos      The return type can signed or unsigned, with no size restriction.  */
    125      1.1  christos   template<typename T> T as_integer () const;
    126      1.1  christos 
    127  1.1.1.2  christos   /* Convert this value to an integer of the given type.  If this
    128  1.1.1.2  christos      value is too large, it is truncated.
    129  1.1.1.2  christos 
    130  1.1.1.2  christos      The return type can signed or unsigned, with no size restriction.  */
    131  1.1.1.2  christos   template<typename T> T as_integer_truncate () const;
    132  1.1.1.2  christos 
    133      1.1  christos   /* Set VAL by importing the number stored in the byte array (BUF),
    134      1.1  christos      using the given BYTE_ORDER.  The size of the data to read is
    135      1.1  christos      the byte array's size.
    136      1.1  christos 
    137      1.1  christos      UNSIGNED_P indicates whether the number has an unsigned type.  */
    138      1.1  christos   void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order,
    139      1.1  christos 	     bool unsigned_p);
    140      1.1  christos 
    141      1.1  christos   /* Write VAL into BUF as a number whose byte size is the size of BUF,
    142      1.1  christos      using the given BYTE_ORDER.
    143      1.1  christos 
    144      1.1  christos      UNSIGNED_P indicates whether the number has an unsigned type.  */
    145      1.1  christos   void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
    146  1.1.1.2  christos 	      bool unsigned_p) const
    147  1.1.1.2  christos   {
    148  1.1.1.2  christos     export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
    149  1.1.1.2  christos 		 unsigned_p, true /* safe */);
    150  1.1.1.2  christos   }
    151  1.1.1.2  christos 
    152  1.1.1.2  christos   /* Like write, but truncates the value to the desired number of
    153  1.1.1.2  christos      bytes.  */
    154  1.1.1.2  christos   void truncate (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
    155  1.1.1.2  christos 		 bool unsigned_p) const
    156  1.1.1.2  christos   {
    157  1.1.1.2  christos     export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
    158  1.1.1.2  christos 		 unsigned_p, false /* safe */);
    159  1.1.1.2  christos   }
    160      1.1  christos 
    161      1.1  christos   /* Return a string containing VAL.  */
    162  1.1.1.2  christos   std::string str () const { return gmp_string_printf ("%Zd", m_val); }
    163      1.1  christos 
    164      1.1  christos   /* The destructor.  */
    165  1.1.1.2  christos   ~gdb_mpz () { mpz_clear (m_val); }
    166  1.1.1.2  christos 
    167  1.1.1.2  christos   /* Negate this value in place.  */
    168  1.1.1.2  christos   void negate ()
    169  1.1.1.2  christos   {
    170  1.1.1.2  christos     mpz_neg (m_val, m_val);
    171  1.1.1.2  christos   }
    172  1.1.1.2  christos 
    173  1.1.1.2  christos   /* Take the one's complement in place.  */
    174  1.1.1.2  christos   void complement ()
    175  1.1.1.2  christos   { mpz_com (m_val, m_val); }
    176  1.1.1.2  christos 
    177  1.1.1.2  christos   /* Mask this value to N bits, in place.  */
    178  1.1.1.2  christos   void mask (unsigned n)
    179  1.1.1.2  christos   { mpz_tdiv_r_2exp (m_val, m_val, n); }
    180  1.1.1.2  christos 
    181  1.1.1.2  christos   /* Return the sign of this value.  This returns -1 for a negative
    182  1.1.1.2  christos      value, 0 if the value is 0, and 1 for a positive value.  */
    183  1.1.1.2  christos   int sgn () const
    184  1.1.1.2  christos   { return mpz_sgn (m_val); }
    185  1.1.1.2  christos 
    186  1.1.1.2  christos   explicit operator bool () const
    187  1.1.1.2  christos   { return sgn () != 0; }
    188  1.1.1.2  christos 
    189  1.1.1.2  christos   gdb_mpz &operator*= (long other)
    190  1.1.1.2  christos   {
    191  1.1.1.2  christos     mpz_mul_si (m_val, m_val, other);
    192  1.1.1.2  christos     return *this;
    193  1.1.1.2  christos   }
    194  1.1.1.2  christos 
    195  1.1.1.2  christos   gdb_mpz operator* (const gdb_mpz &other) const
    196  1.1.1.2  christos   {
    197  1.1.1.2  christos     gdb_mpz result;
    198  1.1.1.2  christos     mpz_mul (result.m_val, m_val, other.m_val);
    199  1.1.1.2  christos     return result;
    200  1.1.1.2  christos   }
    201  1.1.1.2  christos 
    202  1.1.1.2  christos   gdb_mpz operator/ (const gdb_mpz &other) const
    203  1.1.1.2  christos   {
    204  1.1.1.2  christos     gdb_mpz result;
    205  1.1.1.2  christos     mpz_tdiv_q (result.m_val, m_val, other.m_val);
    206  1.1.1.2  christos     return result;
    207  1.1.1.2  christos   }
    208  1.1.1.2  christos 
    209  1.1.1.2  christos   gdb_mpz operator% (const gdb_mpz &other) const
    210  1.1.1.2  christos   {
    211  1.1.1.2  christos     gdb_mpz result;
    212  1.1.1.2  christos     mpz_tdiv_r (result.m_val, m_val, other.m_val);
    213  1.1.1.2  christos     return result;
    214  1.1.1.2  christos   }
    215  1.1.1.2  christos 
    216  1.1.1.2  christos   gdb_mpz &operator+= (unsigned long other)
    217  1.1.1.2  christos   {
    218  1.1.1.2  christos     mpz_add_ui (m_val, m_val, other);
    219  1.1.1.2  christos     return *this;
    220  1.1.1.2  christos   }
    221  1.1.1.2  christos 
    222  1.1.1.2  christos   gdb_mpz &operator+= (const gdb_mpz &other)
    223  1.1.1.2  christos   {
    224  1.1.1.2  christos     mpz_add (m_val, m_val, other.m_val);
    225  1.1.1.2  christos     return *this;
    226  1.1.1.2  christos   }
    227  1.1.1.2  christos 
    228  1.1.1.2  christos   gdb_mpz operator+ (const gdb_mpz &other) const
    229  1.1.1.2  christos   {
    230  1.1.1.2  christos     gdb_mpz result;
    231  1.1.1.2  christos     mpz_add (result.m_val, m_val, other.m_val);
    232  1.1.1.2  christos     return result;
    233  1.1.1.2  christos   }
    234  1.1.1.2  christos 
    235  1.1.1.2  christos   gdb_mpz &operator-= (unsigned long other)
    236  1.1.1.2  christos   {
    237  1.1.1.2  christos     mpz_sub_ui (m_val, m_val, other);
    238  1.1.1.2  christos     return *this;
    239  1.1.1.2  christos   }
    240  1.1.1.2  christos 
    241  1.1.1.2  christos   gdb_mpz &operator-= (const gdb_mpz &other)
    242  1.1.1.2  christos   {
    243  1.1.1.2  christos     mpz_sub (m_val, m_val, other.m_val);
    244  1.1.1.2  christos     return *this;
    245  1.1.1.2  christos   }
    246  1.1.1.2  christos 
    247  1.1.1.2  christos   gdb_mpz operator- (const gdb_mpz &other) const
    248  1.1.1.2  christos   {
    249  1.1.1.2  christos     gdb_mpz result;
    250  1.1.1.2  christos     mpz_sub (result.m_val, m_val, other.m_val);
    251  1.1.1.2  christos     return result;
    252  1.1.1.2  christos   }
    253  1.1.1.2  christos 
    254  1.1.1.2  christos   gdb_mpz operator- () const
    255  1.1.1.2  christos   {
    256  1.1.1.2  christos     gdb_mpz result;
    257  1.1.1.2  christos     mpz_neg (result.m_val, m_val);
    258  1.1.1.2  christos     return result;
    259  1.1.1.2  christos   }
    260  1.1.1.2  christos 
    261  1.1.1.2  christos   gdb_mpz &operator<<= (unsigned long nbits)
    262  1.1.1.2  christos   {
    263  1.1.1.2  christos     mpz_mul_2exp (m_val, m_val, nbits);
    264  1.1.1.2  christos     return *this;
    265  1.1.1.2  christos   }
    266  1.1.1.2  christos 
    267  1.1.1.2  christos   gdb_mpz operator<< (unsigned long nbits) const &
    268  1.1.1.2  christos   {
    269  1.1.1.2  christos     gdb_mpz result;
    270  1.1.1.2  christos     mpz_mul_2exp (result.m_val, m_val, nbits);
    271  1.1.1.2  christos     return result;
    272  1.1.1.2  christos   }
    273  1.1.1.2  christos 
    274  1.1.1.2  christos   gdb_mpz operator<< (unsigned long nbits) &&
    275  1.1.1.2  christos   {
    276  1.1.1.2  christos     mpz_mul_2exp (m_val, m_val, nbits);
    277  1.1.1.2  christos     return *this;
    278  1.1.1.2  christos   }
    279  1.1.1.2  christos 
    280  1.1.1.2  christos   gdb_mpz operator>> (unsigned long nbits) const
    281  1.1.1.2  christos   {
    282  1.1.1.2  christos     gdb_mpz result;
    283  1.1.1.2  christos     mpz_fdiv_q_2exp (result.m_val, m_val, nbits);
    284  1.1.1.2  christos     return result;
    285  1.1.1.2  christos   }
    286  1.1.1.2  christos 
    287  1.1.1.2  christos   gdb_mpz &operator>>= (unsigned long nbits)
    288  1.1.1.2  christos   {
    289  1.1.1.2  christos     mpz_fdiv_q_2exp (m_val, m_val, nbits);
    290  1.1.1.2  christos     return *this;
    291  1.1.1.2  christos   }
    292  1.1.1.2  christos 
    293  1.1.1.2  christos   gdb_mpz operator& (const gdb_mpz &other) const
    294  1.1.1.2  christos   {
    295  1.1.1.2  christos     gdb_mpz result;
    296  1.1.1.2  christos     mpz_and (result.m_val, m_val, other.m_val);
    297  1.1.1.2  christos     return result;
    298  1.1.1.2  christos   }
    299  1.1.1.2  christos 
    300  1.1.1.2  christos   gdb_mpz operator| (const gdb_mpz &other) const
    301  1.1.1.2  christos   {
    302  1.1.1.2  christos     gdb_mpz result;
    303  1.1.1.2  christos     mpz_ior (result.m_val, m_val, other.m_val);
    304  1.1.1.2  christos     return result;
    305  1.1.1.2  christos   }
    306  1.1.1.2  christos 
    307  1.1.1.2  christos   gdb_mpz operator^ (const gdb_mpz &other) const
    308  1.1.1.2  christos   {
    309  1.1.1.2  christos     gdb_mpz result;
    310  1.1.1.2  christos     mpz_xor (result.m_val, m_val, other.m_val);
    311  1.1.1.2  christos     return result;
    312  1.1.1.2  christos   }
    313  1.1.1.2  christos 
    314  1.1.1.2  christos   bool operator> (const gdb_mpz &other) const
    315  1.1.1.2  christos   {
    316  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) > 0;
    317  1.1.1.2  christos   }
    318  1.1.1.2  christos 
    319  1.1.1.2  christos   bool operator>= (const gdb_mpz &other) const
    320  1.1.1.2  christos   {
    321  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) >= 0;
    322  1.1.1.2  christos   }
    323  1.1.1.2  christos 
    324  1.1.1.2  christos   bool operator< (const gdb_mpz &other) const
    325  1.1.1.2  christos   {
    326  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) < 0;
    327  1.1.1.2  christos   }
    328  1.1.1.2  christos 
    329  1.1.1.2  christos   bool operator<= (const gdb_mpz &other) const
    330  1.1.1.2  christos   {
    331  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) <= 0;
    332  1.1.1.2  christos   }
    333  1.1.1.2  christos 
    334  1.1.1.2  christos   bool operator< (long other) const
    335  1.1.1.2  christos   {
    336  1.1.1.2  christos     return mpz_cmp_si (m_val, other) < 0;
    337  1.1.1.2  christos   }
    338  1.1.1.2  christos 
    339  1.1.1.2  christos   /* We want an operator== that can handle all integer types.  For
    340  1.1.1.2  christos      types that are 'long' or narrower, we can use a GMP function and
    341  1.1.1.2  christos      avoid boxing the RHS.  But, because overloading based on integer
    342  1.1.1.2  christos      type is a pain in C++, we accept all such types here and check
    343  1.1.1.2  christos      the size in the body.  */
    344  1.1.1.2  christos   template<typename T, typename = gdb::Requires<std::is_integral<T>>>
    345  1.1.1.2  christos   bool operator== (T other) const
    346  1.1.1.2  christos   {
    347  1.1.1.2  christos     if (std::is_signed<T>::value)
    348  1.1.1.2  christos       {
    349  1.1.1.2  christos 	if (sizeof (T) <= sizeof (long))
    350  1.1.1.2  christos 	  return mpz_cmp_si (m_val, other) == 0;
    351  1.1.1.2  christos       }
    352  1.1.1.2  christos     else
    353  1.1.1.2  christos       {
    354  1.1.1.2  christos 	if (sizeof (T) <= sizeof (unsigned long))
    355  1.1.1.2  christos 	  return mpz_cmp_ui (m_val, other) == 0;
    356  1.1.1.2  christos       }
    357  1.1.1.2  christos     return *this == gdb_mpz (other);
    358  1.1.1.2  christos   }
    359  1.1.1.2  christos 
    360  1.1.1.2  christos   bool operator== (const gdb_mpz &other) const
    361  1.1.1.2  christos   {
    362  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) == 0;
    363  1.1.1.2  christos   }
    364  1.1.1.2  christos 
    365  1.1.1.2  christos   bool operator!= (const gdb_mpz &other) const
    366  1.1.1.2  christos   {
    367  1.1.1.2  christos     return mpz_cmp (m_val, other.m_val) != 0;
    368  1.1.1.2  christos   }
    369      1.1  christos 
    370      1.1  christos private:
    371      1.1  christos 
    372      1.1  christos   /* Helper template for constructor and operator=.  */
    373      1.1  christos   template<typename T> void set (T src);
    374      1.1  christos 
    375      1.1  christos   /* Low-level function to export VAL into BUF as a number whose byte size
    376      1.1  christos      is the size of BUF.
    377      1.1  christos 
    378      1.1  christos      If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
    379      1.1  christos      Otherwise, export it as a signed value.
    380      1.1  christos 
    381      1.1  christos      The API is inspired from GMP's mpz_export, hence the naming and types
    382      1.1  christos      of the following parameter:
    383      1.1  christos        - ENDIAN should be:
    384  1.1.1.2  christos 	   . 1 for most significant byte first; or
    385      1.1  christos 	   . -1 for least significant byte first; or
    386      1.1  christos 	   . 0 for native endianness.
    387      1.1  christos 
    388  1.1.1.2  christos     If SAFE is true, an error is raised if BUF is not large enough to
    389  1.1.1.2  christos     contain the value being exported.  If SAFE is false, the value is
    390  1.1.1.2  christos     truncated to fit in BUF.  */
    391  1.1.1.2  christos   void export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
    392  1.1.1.2  christos 		    bool safe) const;
    393  1.1.1.2  christos 
    394  1.1.1.2  christos   friend struct gdb_mpq;
    395  1.1.1.2  christos   friend struct gdb_mpf;
    396  1.1.1.2  christos 
    397  1.1.1.2  christos   mpz_t m_val;
    398      1.1  christos };
    399      1.1  christos 
    400      1.1  christos /* A class to make it easier to use GMP's mpq_t values within GDB.  */
    401      1.1  christos 
    402      1.1  christos struct gdb_mpq
    403      1.1  christos {
    404      1.1  christos   /* Constructors.  */
    405  1.1.1.2  christos   gdb_mpq () { mpq_init (m_val); }
    406      1.1  christos 
    407      1.1  christos   explicit gdb_mpq (const mpq_t &from_val)
    408      1.1  christos   {
    409  1.1.1.2  christos     mpq_init (m_val);
    410  1.1.1.2  christos     mpq_set (m_val, from_val);
    411      1.1  christos   }
    412      1.1  christos 
    413      1.1  christos   gdb_mpq (const gdb_mpq &from)
    414      1.1  christos   {
    415  1.1.1.2  christos     mpq_init (m_val);
    416  1.1.1.2  christos     mpq_set (m_val, from.m_val);
    417      1.1  christos   }
    418      1.1  christos 
    419      1.1  christos   explicit gdb_mpq (gdb_mpq &&from)
    420      1.1  christos   {
    421  1.1.1.2  christos     mpq_init (m_val);
    422  1.1.1.2  christos     mpq_swap (m_val, from.m_val);
    423  1.1.1.2  christos   }
    424  1.1.1.2  christos 
    425  1.1.1.2  christos   gdb_mpq (const gdb_mpz &num, const gdb_mpz &denom)
    426  1.1.1.2  christos   {
    427  1.1.1.2  christos     mpq_init (m_val);
    428  1.1.1.2  christos     mpz_set (mpq_numref (m_val), num.m_val);
    429  1.1.1.2  christos     mpz_set (mpq_denref (m_val), denom.m_val);
    430  1.1.1.2  christos     mpq_canonicalize (m_val);
    431  1.1.1.2  christos   }
    432  1.1.1.2  christos 
    433  1.1.1.2  christos   gdb_mpq (long num, long denom)
    434  1.1.1.2  christos   {
    435  1.1.1.2  christos     mpq_init (m_val);
    436  1.1.1.2  christos     mpq_set_si (m_val, num, denom);
    437  1.1.1.2  christos     mpq_canonicalize (m_val);
    438      1.1  christos   }
    439      1.1  christos 
    440      1.1  christos   /* Copy assignment operator.  */
    441      1.1  christos   gdb_mpq &operator= (const gdb_mpq &from)
    442      1.1  christos   {
    443  1.1.1.2  christos     mpq_set (m_val, from.m_val);
    444      1.1  christos     return *this;
    445      1.1  christos   }
    446      1.1  christos 
    447      1.1  christos   gdb_mpq &operator= (gdb_mpq &&from)
    448      1.1  christos   {
    449  1.1.1.2  christos     mpq_swap (m_val, from.m_val);
    450  1.1.1.2  christos     return *this;
    451  1.1.1.2  christos   }
    452  1.1.1.2  christos 
    453  1.1.1.2  christos   gdb_mpq &operator= (const gdb_mpz &from)
    454  1.1.1.2  christos   {
    455  1.1.1.2  christos     mpq_set_z (m_val, from.m_val);
    456  1.1.1.2  christos     return *this;
    457  1.1.1.2  christos   }
    458  1.1.1.2  christos 
    459  1.1.1.2  christos   gdb_mpq &operator= (double d)
    460  1.1.1.2  christos   {
    461  1.1.1.2  christos     mpq_set_d (m_val, d);
    462      1.1  christos     return *this;
    463      1.1  christos   }
    464      1.1  christos 
    465  1.1.1.2  christos   /* Return the sign of this value.  This returns -1 for a negative
    466  1.1.1.2  christos      value, 0 if the value is 0, and 1 for a positive value.  */
    467  1.1.1.2  christos   int sgn () const
    468  1.1.1.2  christos   { return mpq_sgn (m_val); }
    469  1.1.1.2  christos 
    470  1.1.1.2  christos   gdb_mpq operator+ (const gdb_mpq &other) const
    471  1.1.1.2  christos   {
    472  1.1.1.2  christos     gdb_mpq result;
    473  1.1.1.2  christos     mpq_add (result.m_val, m_val, other.m_val);
    474  1.1.1.2  christos     return result;
    475  1.1.1.2  christos   }
    476  1.1.1.2  christos 
    477  1.1.1.2  christos   gdb_mpq operator- (const gdb_mpq &other) const
    478  1.1.1.2  christos   {
    479  1.1.1.2  christos     gdb_mpq result;
    480  1.1.1.2  christos     mpq_sub (result.m_val, m_val, other.m_val);
    481  1.1.1.2  christos     return result;
    482  1.1.1.2  christos   }
    483  1.1.1.2  christos 
    484  1.1.1.2  christos   gdb_mpq operator* (const gdb_mpq &other) const
    485  1.1.1.2  christos   {
    486  1.1.1.2  christos     gdb_mpq result;
    487  1.1.1.2  christos     mpq_mul (result.m_val, m_val, other.m_val);
    488  1.1.1.2  christos     return result;
    489  1.1.1.2  christos   }
    490  1.1.1.2  christos 
    491  1.1.1.2  christos   gdb_mpq operator/ (const gdb_mpq &other) const
    492  1.1.1.2  christos   {
    493  1.1.1.2  christos     gdb_mpq result;
    494  1.1.1.2  christos     mpq_div (result.m_val, m_val, other.m_val);
    495  1.1.1.2  christos     return result;
    496  1.1.1.2  christos   }
    497  1.1.1.2  christos 
    498  1.1.1.2  christos   gdb_mpq &operator*= (const gdb_mpq &other)
    499  1.1.1.2  christos   {
    500  1.1.1.2  christos     mpq_mul (m_val, m_val, other.m_val);
    501  1.1.1.2  christos     return *this;
    502  1.1.1.2  christos   }
    503  1.1.1.2  christos 
    504  1.1.1.2  christos   gdb_mpq &operator/= (const gdb_mpq &other)
    505  1.1.1.2  christos   {
    506  1.1.1.2  christos     mpq_div (m_val, m_val, other.m_val);
    507  1.1.1.2  christos     return *this;
    508  1.1.1.2  christos   }
    509  1.1.1.2  christos 
    510  1.1.1.2  christos   bool operator== (const gdb_mpq &other) const
    511  1.1.1.2  christos   {
    512  1.1.1.2  christos     return mpq_cmp (m_val, other.m_val) == 0;
    513  1.1.1.2  christos   }
    514  1.1.1.2  christos 
    515  1.1.1.2  christos   bool operator< (const gdb_mpq &other) const
    516  1.1.1.2  christos   {
    517  1.1.1.2  christos     return mpq_cmp (m_val, other.m_val) < 0;
    518  1.1.1.2  christos   }
    519  1.1.1.2  christos 
    520      1.1  christos   /* Return a string representing VAL as "<numerator> / <denominator>".  */
    521  1.1.1.2  christos   std::string str () const { return gmp_string_printf ("%Qd", m_val); }
    522      1.1  christos 
    523      1.1  christos   /* Return VAL rounded to the nearest integer.  */
    524      1.1  christos   gdb_mpz get_rounded () const;
    525      1.1  christos 
    526  1.1.1.2  christos   /* Return this value as an integer, rounded toward zero.  */
    527  1.1.1.2  christos   gdb_mpz as_integer () const
    528  1.1.1.2  christos   {
    529  1.1.1.2  christos     gdb_mpz result;
    530  1.1.1.2  christos     mpz_tdiv_q (result.m_val, mpq_numref (m_val), mpq_denref (m_val));
    531  1.1.1.2  christos     return result;
    532  1.1.1.2  christos   }
    533  1.1.1.2  christos 
    534  1.1.1.2  christos   /* Return this value converted to a host double.  */
    535  1.1.1.2  christos   double as_double () const
    536  1.1.1.2  christos   { return mpq_get_d (m_val); }
    537  1.1.1.2  christos 
    538      1.1  christos   /* Set VAL from the contents of the given byte array (BUF), which
    539      1.1  christos      contains the unscaled value of a fixed point type object.
    540      1.1  christos      The byte size of the data is the size of BUF.
    541      1.1  christos 
    542      1.1  christos      BYTE_ORDER provides the byte_order to use when reading the data.
    543      1.1  christos 
    544      1.1  christos      UNSIGNED_P indicates whether the number has an unsigned type.
    545      1.1  christos      SCALING_FACTOR is the scaling factor to apply after having
    546      1.1  christos      read the unscaled value from our buffer.  */
    547      1.1  christos   void read_fixed_point (gdb::array_view<const gdb_byte> buf,
    548      1.1  christos 			 enum bfd_endian byte_order, bool unsigned_p,
    549      1.1  christos 			 const gdb_mpq &scaling_factor);
    550      1.1  christos 
    551      1.1  christos   /* Write VAL into BUF as fixed point value following the given BYTE_ORDER.
    552      1.1  christos      The size of BUF is used as the length to write the value into.
    553      1.1  christos 
    554      1.1  christos      UNSIGNED_P indicates whether the number has an unsigned type.
    555      1.1  christos      SCALING_FACTOR is the scaling factor to apply before writing
    556      1.1  christos      the unscaled value to our buffer.  */
    557      1.1  christos   void write_fixed_point (gdb::array_view<gdb_byte> buf,
    558      1.1  christos 			  enum bfd_endian byte_order, bool unsigned_p,
    559      1.1  christos 			  const gdb_mpq &scaling_factor) const;
    560      1.1  christos 
    561      1.1  christos   /* The destructor.  */
    562  1.1.1.2  christos   ~gdb_mpq () { mpq_clear (m_val); }
    563  1.1.1.2  christos 
    564  1.1.1.2  christos private:
    565  1.1.1.2  christos 
    566  1.1.1.2  christos   friend struct gdb_mpf;
    567  1.1.1.2  christos 
    568  1.1.1.2  christos   mpq_t m_val;
    569      1.1  christos };
    570      1.1  christos 
    571      1.1  christos /* A class to make it easier to use GMP's mpf_t values within GDB.
    572      1.1  christos 
    573      1.1  christos    Should MPFR become a required dependency, we should probably
    574      1.1  christos    drop this class in favor of using MPFR.  */
    575      1.1  christos 
    576      1.1  christos struct gdb_mpf
    577      1.1  christos {
    578      1.1  christos   /* Constructors.  */
    579  1.1.1.2  christos   gdb_mpf () { mpf_init (m_val); }
    580      1.1  christos 
    581      1.1  christos   DISABLE_COPY_AND_ASSIGN (gdb_mpf);
    582      1.1  christos 
    583      1.1  christos   /* Set VAL from the contents of the given buffer (BUF), which
    584      1.1  christos      contains the unscaled value of a fixed point type object
    585      1.1  christos      with the given size (LEN) and byte order (BYTE_ORDER).
    586      1.1  christos 
    587      1.1  christos      UNSIGNED_P indicates whether the number has an unsigned type.
    588      1.1  christos      SCALING_FACTOR is the scaling factor to apply after having
    589      1.1  christos      read the unscaled value from our buffer.  */
    590      1.1  christos   void read_fixed_point (gdb::array_view<const gdb_byte> buf,
    591      1.1  christos 			 enum bfd_endian byte_order, bool unsigned_p,
    592      1.1  christos 			 const gdb_mpq &scaling_factor)
    593      1.1  christos   {
    594      1.1  christos     gdb_mpq tmp_q;
    595      1.1  christos 
    596      1.1  christos     tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor);
    597  1.1.1.2  christos     mpf_set_q (m_val, tmp_q.m_val);
    598      1.1  christos   }
    599      1.1  christos 
    600  1.1.1.2  christos   /* Convert this value to a string.  FMT is the format to use, and
    601  1.1.1.2  christos      should have a single '%' substitution.  */
    602  1.1.1.2  christos   std::string str (const char *fmt) const
    603  1.1.1.2  christos   { return gmp_string_printf (fmt, m_val); }
    604  1.1.1.2  christos 
    605      1.1  christos   /* The destructor.  */
    606  1.1.1.2  christos   ~gdb_mpf () { mpf_clear (m_val); }
    607  1.1.1.2  christos 
    608  1.1.1.2  christos private:
    609  1.1.1.2  christos 
    610  1.1.1.2  christos   mpf_t m_val;
    611      1.1  christos };
    612      1.1  christos 
    613      1.1  christos /* See declaration above.  */
    614      1.1  christos 
    615      1.1  christos template<typename T>
    616      1.1  christos void
    617      1.1  christos gdb_mpz::set (T src)
    618      1.1  christos {
    619  1.1.1.2  christos   mpz_import (m_val, 1 /* count */, -1 /* order */,
    620      1.1  christos 	      sizeof (T) /* size */, 0 /* endian (0 = native) */,
    621      1.1  christos 	      0 /* nails */, &src /* op */);
    622      1.1  christos   if (std::is_signed<T>::value && src < 0)
    623      1.1  christos     {
    624      1.1  christos       /* mpz_import does not handle the sign, so our value was imported
    625      1.1  christos 	 as an unsigned. Adjust that imported value so as to make it
    626      1.1  christos 	 the correct negative value.  */
    627      1.1  christos       gdb_mpz neg_offset;
    628      1.1  christos 
    629  1.1.1.2  christos       mpz_ui_pow_ui (neg_offset.m_val, 2, sizeof (T) * HOST_CHAR_BIT);
    630  1.1.1.2  christos       mpz_sub (m_val, m_val, neg_offset.m_val);
    631      1.1  christos     }
    632      1.1  christos }
    633      1.1  christos 
    634      1.1  christos /* See declaration above.  */
    635      1.1  christos 
    636      1.1  christos template<typename T>
    637      1.1  christos T
    638      1.1  christos gdb_mpz::as_integer () const
    639      1.1  christos {
    640      1.1  christos   T result;
    641      1.1  christos 
    642  1.1.1.2  christos   this->export_bits ({(gdb_byte *) &result, sizeof (result)},
    643  1.1.1.2  christos 		     0 /* endian (0 = native) */,
    644  1.1.1.2  christos 		     !std::is_signed<T>::value /* unsigned_p */,
    645  1.1.1.2  christos 		     true /* safe */);
    646  1.1.1.2  christos 
    647  1.1.1.2  christos   return result;
    648  1.1.1.2  christos }
    649  1.1.1.2  christos 
    650  1.1.1.2  christos /* See declaration above.  */
    651  1.1.1.2  christos 
    652  1.1.1.2  christos template<typename T>
    653  1.1.1.2  christos T
    654  1.1.1.2  christos gdb_mpz::as_integer_truncate () const
    655  1.1.1.2  christos {
    656  1.1.1.2  christos   T result;
    657  1.1.1.2  christos 
    658  1.1.1.2  christos   this->export_bits ({(gdb_byte *) &result, sizeof (result)},
    659      1.1  christos 		     0 /* endian (0 = native) */,
    660  1.1.1.2  christos 		     !std::is_signed<T>::value /* unsigned_p */,
    661  1.1.1.2  christos 		     false /* safe */);
    662      1.1  christos 
    663      1.1  christos   return result;
    664      1.1  christos }
    665      1.1  christos 
    666      1.1  christos #endif
    667