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