Bump GDB's version number to 15.0.91.DATE-git.
[binutils-gdb.git] / gdb / gmp-utils.h
blob51e06abc0504dfd2c5503dafb12bea8edd92f4b7
1 /* Miscellaneous routines making it easier to use GMP within GDB's framework.
3 Copyright (C) 2019-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #ifndef GMP_UTILS_H
21 #define GMP_UTILS_H
23 /* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get
24 access to GMP's various formatting functions. */
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <gmp.h>
28 #include "gdbsupport/traits.h"
30 /* Same as gmp_asprintf, but returning an std::string. */
32 std::string gmp_string_printf (const char *fmt, ...);
34 struct gdb_mpq;
35 struct gdb_mpf;
37 /* A class to make it easier to use GMP's mpz_t values within GDB. */
39 struct gdb_mpz
41 /* Constructors. */
42 gdb_mpz () { mpz_init (m_val); }
44 explicit gdb_mpz (const mpz_t &from_val)
46 mpz_init (m_val);
47 mpz_set (m_val, from_val);
50 gdb_mpz (const gdb_mpz &from)
52 mpz_init (m_val);
53 mpz_set (m_val, from.m_val);
56 /* Initialize using the given integral value.
58 The main advantage of this method is that it handles both signed
59 and unsigned types, with no size restriction. */
60 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
61 explicit gdb_mpz (T src)
63 mpz_init (m_val);
64 set (src);
67 explicit gdb_mpz (gdb_mpz &&from)
69 mpz_init (m_val);
70 mpz_swap (m_val, from.m_val);
74 gdb_mpz &operator= (const gdb_mpz &from)
76 mpz_set (m_val, from.m_val);
77 return *this;
80 gdb_mpz &operator= (gdb_mpz &&other)
82 mpz_swap (m_val, other.m_val);
83 return *this;
86 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
87 gdb_mpz &operator= (T src)
89 set (src);
90 return *this;
93 gdb_mpz &operator= (bool src)
95 mpz_set_ui (m_val, (unsigned long) src);
96 return *this;
99 /* Initialize this value from a string and a base. Returns true if
100 the string was parsed successfully, false otherwise. */
101 bool set (const char *str, int base)
103 return mpz_set_str (m_val, str, base) != -1;
106 /* Return a new value that is BASE**EXP. */
107 static gdb_mpz pow (unsigned long base, unsigned long exp)
109 gdb_mpz result;
110 mpz_ui_pow_ui (result.m_val, base, exp);
111 return result;
114 /* Return a new value that is this value raised to EXP. */
115 gdb_mpz pow (unsigned long exp) const
117 gdb_mpz result;
118 mpz_pow_ui (result.m_val, m_val, exp);
119 return result;
122 /* Convert this value to an integer of the given type.
124 The return type can signed or unsigned, with no size restriction. */
125 template<typename T> T as_integer () const;
127 /* Convert this value to an integer of the given type. If this
128 value is too large, it is truncated.
130 The return type can signed or unsigned, with no size restriction. */
131 template<typename T> T as_integer_truncate () const;
133 /* Set VAL by importing the number stored in the byte array (BUF),
134 using the given BYTE_ORDER. The size of the data to read is
135 the byte array's size.
137 UNSIGNED_P indicates whether the number has an unsigned type. */
138 void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order,
139 bool unsigned_p);
141 /* Write VAL into BUF as a number whose byte size is the size of BUF,
142 using the given BYTE_ORDER.
144 UNSIGNED_P indicates whether the number has an unsigned type. */
145 void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
146 bool unsigned_p) const
148 export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
149 unsigned_p, true /* safe */);
152 /* Like write, but truncates the value to the desired number of
153 bytes. */
154 void truncate (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
155 bool unsigned_p) const
157 export_bits (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
158 unsigned_p, false /* safe */);
161 /* Return a string containing VAL. */
162 std::string str () const { return gmp_string_printf ("%Zd", m_val); }
164 /* The destructor. */
165 ~gdb_mpz () { mpz_clear (m_val); }
167 /* Negate this value in place. */
168 void negate ()
170 mpz_neg (m_val, m_val);
173 /* Take the one's complement in place. */
174 void complement ()
175 { mpz_com (m_val, m_val); }
177 /* Mask this value to N bits, in place. */
178 void mask (unsigned n)
179 { mpz_tdiv_r_2exp (m_val, m_val, n); }
181 /* Return the sign of this value. This returns -1 for a negative
182 value, 0 if the value is 0, and 1 for a positive value. */
183 int sgn () const
184 { return mpz_sgn (m_val); }
186 explicit operator bool () const
187 { return sgn () != 0; }
189 gdb_mpz &operator*= (long other)
191 mpz_mul_si (m_val, m_val, other);
192 return *this;
195 gdb_mpz operator* (const gdb_mpz &other) const
197 gdb_mpz result;
198 mpz_mul (result.m_val, m_val, other.m_val);
199 return result;
202 gdb_mpz operator/ (const gdb_mpz &other) const
204 gdb_mpz result;
205 mpz_tdiv_q (result.m_val, m_val, other.m_val);
206 return result;
209 gdb_mpz operator% (const gdb_mpz &other) const
211 gdb_mpz result;
212 mpz_tdiv_r (result.m_val, m_val, other.m_val);
213 return result;
216 gdb_mpz &operator+= (unsigned long other)
218 mpz_add_ui (m_val, m_val, other);
219 return *this;
222 gdb_mpz &operator+= (const gdb_mpz &other)
224 mpz_add (m_val, m_val, other.m_val);
225 return *this;
228 gdb_mpz operator+ (const gdb_mpz &other) const
230 gdb_mpz result;
231 mpz_add (result.m_val, m_val, other.m_val);
232 return result;
235 gdb_mpz &operator-= (unsigned long other)
237 mpz_sub_ui (m_val, m_val, other);
238 return *this;
241 gdb_mpz &operator-= (const gdb_mpz &other)
243 mpz_sub (m_val, m_val, other.m_val);
244 return *this;
247 gdb_mpz operator- (const gdb_mpz &other) const
249 gdb_mpz result;
250 mpz_sub (result.m_val, m_val, other.m_val);
251 return result;
254 gdb_mpz operator- () const
256 gdb_mpz result;
257 mpz_neg (result.m_val, m_val);
258 return result;
261 gdb_mpz &operator<<= (unsigned long nbits)
263 mpz_mul_2exp (m_val, m_val, nbits);
264 return *this;
267 gdb_mpz operator<< (unsigned long nbits) const &
269 gdb_mpz result;
270 mpz_mul_2exp (result.m_val, m_val, nbits);
271 return result;
274 gdb_mpz operator<< (unsigned long nbits) &&
276 mpz_mul_2exp (m_val, m_val, nbits);
277 return *this;
280 gdb_mpz operator>> (unsigned long nbits) const
282 gdb_mpz result;
283 mpz_tdiv_q_2exp (result.m_val, m_val, nbits);
284 return result;
287 gdb_mpz &operator>>= (unsigned long nbits)
289 mpz_tdiv_q_2exp (m_val, m_val, nbits);
290 return *this;
293 gdb_mpz operator& (const gdb_mpz &other) const
295 gdb_mpz result;
296 mpz_and (result.m_val, m_val, other.m_val);
297 return result;
300 gdb_mpz operator| (const gdb_mpz &other) const
302 gdb_mpz result;
303 mpz_ior (result.m_val, m_val, other.m_val);
304 return result;
307 gdb_mpz operator^ (const gdb_mpz &other) const
309 gdb_mpz result;
310 mpz_xor (result.m_val, m_val, other.m_val);
311 return result;
314 bool operator> (const gdb_mpz &other) const
316 return mpz_cmp (m_val, other.m_val) > 0;
319 bool operator>= (const gdb_mpz &other) const
321 return mpz_cmp (m_val, other.m_val) >= 0;
324 bool operator< (const gdb_mpz &other) const
326 return mpz_cmp (m_val, other.m_val) < 0;
329 bool operator<= (const gdb_mpz &other) const
331 return mpz_cmp (m_val, other.m_val) <= 0;
334 bool operator< (long other) const
336 return mpz_cmp_si (m_val, other) < 0;
339 /* We want an operator== that can handle all integer types. For
340 types that are 'long' or narrower, we can use a GMP function and
341 avoid boxing the RHS. But, because overloading based on integer
342 type is a pain in C++, we accept all such types here and check
343 the size in the body. */
344 template<typename T, typename = gdb::Requires<std::is_integral<T>>>
345 bool operator== (T other) const
347 if (std::is_signed<T>::value)
349 if (sizeof (T) <= sizeof (long))
350 return mpz_cmp_si (m_val, other) == 0;
352 else
354 if (sizeof (T) <= sizeof (unsigned long))
355 return mpz_cmp_ui (m_val, other) == 0;
357 return *this == gdb_mpz (other);
360 bool operator== (const gdb_mpz &other) const
362 return mpz_cmp (m_val, other.m_val) == 0;
365 bool operator!= (const gdb_mpz &other) const
367 return mpz_cmp (m_val, other.m_val) != 0;
370 private:
372 /* Helper template for constructor and operator=. */
373 template<typename T> void set (T src);
375 /* Low-level function to export VAL into BUF as a number whose byte size
376 is the size of BUF.
378 If UNSIGNED_P is true, then export VAL into BUF as an unsigned value.
379 Otherwise, export it as a signed value.
381 The API is inspired from GMP's mpz_export, hence the naming and types
382 of the following parameter:
383 - ENDIAN should be:
384 . 1 for most significant byte first; or
385 . -1 for least significant byte first; or
386 . 0 for native endianness.
388 If SAFE is true, an error is raised if BUF is not large enough to
389 contain the value being exported. If SAFE is false, the value is
390 truncated to fit in BUF. */
391 void export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
392 bool safe) const;
394 friend struct gdb_mpq;
395 friend struct gdb_mpf;
397 mpz_t m_val;
400 /* A class to make it easier to use GMP's mpq_t values within GDB. */
402 struct gdb_mpq
404 /* Constructors. */
405 gdb_mpq () { mpq_init (m_val); }
407 explicit gdb_mpq (const mpq_t &from_val)
409 mpq_init (m_val);
410 mpq_set (m_val, from_val);
413 gdb_mpq (const gdb_mpq &from)
415 mpq_init (m_val);
416 mpq_set (m_val, from.m_val);
419 explicit gdb_mpq (gdb_mpq &&from)
421 mpq_init (m_val);
422 mpq_swap (m_val, from.m_val);
425 gdb_mpq (const gdb_mpz &num, const gdb_mpz &denom)
427 mpq_init (m_val);
428 mpz_set (mpq_numref (m_val), num.m_val);
429 mpz_set (mpq_denref (m_val), denom.m_val);
430 mpq_canonicalize (m_val);
433 gdb_mpq (long num, long denom)
435 mpq_init (m_val);
436 mpq_set_si (m_val, num, denom);
437 mpq_canonicalize (m_val);
440 /* Copy assignment operator. */
441 gdb_mpq &operator= (const gdb_mpq &from)
443 mpq_set (m_val, from.m_val);
444 return *this;
447 gdb_mpq &operator= (gdb_mpq &&from)
449 mpq_swap (m_val, from.m_val);
450 return *this;
453 gdb_mpq &operator= (const gdb_mpz &from)
455 mpq_set_z (m_val, from.m_val);
456 return *this;
459 gdb_mpq &operator= (double d)
461 mpq_set_d (m_val, d);
462 return *this;
465 /* Return the sign of this value. This returns -1 for a negative
466 value, 0 if the value is 0, and 1 for a positive value. */
467 int sgn () const
468 { return mpq_sgn (m_val); }
470 gdb_mpq operator+ (const gdb_mpq &other) const
472 gdb_mpq result;
473 mpq_add (result.m_val, m_val, other.m_val);
474 return result;
477 gdb_mpq operator- (const gdb_mpq &other) const
479 gdb_mpq result;
480 mpq_sub (result.m_val, m_val, other.m_val);
481 return result;
484 gdb_mpq operator* (const gdb_mpq &other) const
486 gdb_mpq result;
487 mpq_mul (result.m_val, m_val, other.m_val);
488 return result;
491 gdb_mpq operator/ (const gdb_mpq &other) const
493 gdb_mpq result;
494 mpq_div (result.m_val, m_val, other.m_val);
495 return result;
498 gdb_mpq &operator*= (const gdb_mpq &other)
500 mpq_mul (m_val, m_val, other.m_val);
501 return *this;
504 gdb_mpq &operator/= (const gdb_mpq &other)
506 mpq_div (m_val, m_val, other.m_val);
507 return *this;
510 bool operator== (const gdb_mpq &other) const
512 return mpq_cmp (m_val, other.m_val) == 0;
515 bool operator< (const gdb_mpq &other) const
517 return mpq_cmp (m_val, other.m_val) < 0;
520 /* Return a string representing VAL as "<numerator> / <denominator>". */
521 std::string str () const { return gmp_string_printf ("%Qd", m_val); }
523 /* Return VAL rounded to the nearest integer. */
524 gdb_mpz get_rounded () const;
526 /* Return this value as an integer, rounded toward zero. */
527 gdb_mpz as_integer () const
529 gdb_mpz result;
530 mpz_tdiv_q (result.m_val, mpq_numref (m_val), mpq_denref (m_val));
531 return result;
534 /* Return this value converted to a host double. */
535 double as_double () const
536 { return mpq_get_d (m_val); }
538 /* Set VAL from the contents of the given byte array (BUF), which
539 contains the unscaled value of a fixed point type object.
540 The byte size of the data is the size of BUF.
542 BYTE_ORDER provides the byte_order to use when reading the data.
544 UNSIGNED_P indicates whether the number has an unsigned type.
545 SCALING_FACTOR is the scaling factor to apply after having
546 read the unscaled value from our buffer. */
547 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
548 enum bfd_endian byte_order, bool unsigned_p,
549 const gdb_mpq &scaling_factor);
551 /* Write VAL into BUF as fixed point value following the given BYTE_ORDER.
552 The size of BUF is used as the length to write the value into.
554 UNSIGNED_P indicates whether the number has an unsigned type.
555 SCALING_FACTOR is the scaling factor to apply before writing
556 the unscaled value to our buffer. */
557 void write_fixed_point (gdb::array_view<gdb_byte> buf,
558 enum bfd_endian byte_order, bool unsigned_p,
559 const gdb_mpq &scaling_factor) const;
561 /* The destructor. */
562 ~gdb_mpq () { mpq_clear (m_val); }
564 private:
566 friend struct gdb_mpf;
568 mpq_t m_val;
571 /* A class to make it easier to use GMP's mpf_t values within GDB.
573 Should MPFR become a required dependency, we should probably
574 drop this class in favor of using MPFR. */
576 struct gdb_mpf
578 /* Constructors. */
579 gdb_mpf () { mpf_init (m_val); }
581 DISABLE_COPY_AND_ASSIGN (gdb_mpf);
583 /* Set VAL from the contents of the given buffer (BUF), which
584 contains the unscaled value of a fixed point type object
585 with the given size (LEN) and byte order (BYTE_ORDER).
587 UNSIGNED_P indicates whether the number has an unsigned type.
588 SCALING_FACTOR is the scaling factor to apply after having
589 read the unscaled value from our buffer. */
590 void read_fixed_point (gdb::array_view<const gdb_byte> buf,
591 enum bfd_endian byte_order, bool unsigned_p,
592 const gdb_mpq &scaling_factor)
594 gdb_mpq tmp_q;
596 tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor);
597 mpf_set_q (m_val, tmp_q.m_val);
600 /* Convert this value to a string. FMT is the format to use, and
601 should have a single '%' substitution. */
602 std::string str (const char *fmt) const
603 { return gmp_string_printf (fmt, m_val); }
605 /* The destructor. */
606 ~gdb_mpf () { mpf_clear (m_val); }
608 private:
610 mpf_t m_val;
613 /* See declaration above. */
615 template<typename T>
616 void
617 gdb_mpz::set (T src)
619 mpz_import (m_val, 1 /* count */, -1 /* order */,
620 sizeof (T) /* size */, 0 /* endian (0 = native) */,
621 0 /* nails */, &src /* op */);
622 if (std::is_signed<T>::value && src < 0)
624 /* mpz_import does not handle the sign, so our value was imported
625 as an unsigned. Adjust that imported value so as to make it
626 the correct negative value. */
627 gdb_mpz neg_offset;
629 mpz_ui_pow_ui (neg_offset.m_val, 2, sizeof (T) * HOST_CHAR_BIT);
630 mpz_sub (m_val, m_val, neg_offset.m_val);
634 /* See declaration above. */
636 template<typename T>
638 gdb_mpz::as_integer () const
640 T result;
642 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
643 0 /* endian (0 = native) */,
644 !std::is_signed<T>::value /* unsigned_p */,
645 true /* safe */);
647 return result;
650 /* See declaration above. */
652 template<typename T>
654 gdb_mpz::as_integer_truncate () const
656 T result;
658 this->export_bits ({(gdb_byte *) &result, sizeof (result)},
659 0 /* endian (0 = native) */,
660 !std::is_signed<T>::value /* unsigned_p */,
661 false /* safe */);
663 return result;
666 #endif