799410836e8b5bd8cea1b96752714ff937661f40
1 /* Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 This file is part of GDB.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 #include "gmp-utils.h"
20 /* See gmp-utils.h. */
23 gmp_string_printf (const char *fmt
, ...)
28 int size
= gmp_vsnprintf (NULL
, 0, fmt
, vp
);
31 std::string
str (size
, '\0');
33 /* C++11 and later guarantee std::string uses contiguous memory and
34 always includes the terminating '\0'. */
36 gmp_vsprintf (&str
[0], fmt
, vp
);
42 /* See gmp-utils.h. */
45 gdb_mpz::read (gdb::array_view
<const gdb_byte
> buf
, enum bfd_endian byte_order
,
48 mpz_import (val
, 1 /* count */, -1 /* order */, buf
.size () /* size */,
49 byte_order
== BFD_ENDIAN_BIG
? 1 : -1 /* endian */,
50 0 /* nails */, buf
.data () /* op */);
54 /* The value was imported as if it was a positive value,
55 as mpz_import does not handle signs. If the original value
56 was in fact negative, we need to adjust VAL accordingly. */
59 mpz_ui_pow_ui (max
.val
, 2, buf
.size () * TARGET_CHAR_BIT
- 1);
60 if (mpz_cmp (val
, max
.val
) >= 0)
61 mpz_submul_ui (val
, max
.val
, 2);
65 /* See gmp-utils.h. */
68 gdb_mpz::write (gdb::array_view
<gdb_byte
> buf
, enum bfd_endian byte_order
,
69 bool unsigned_p
) const
71 gdb_mpz
exported_val (val
);
73 if (mpz_cmp_ui (val
, 0) < 0)
75 /* mpz_export does not handle signed values, so create a positive
76 value whose bit representation as an unsigned of the same length
77 would be the same as our negative value. */
80 mpz_ui_pow_ui (neg_offset
.val
, 2, buf
.size () * TARGET_CHAR_BIT
);
81 mpz_add (exported_val
.val
, exported_val
.val
, neg_offset
.val
);
84 /* Start by clearing the buffer, as mpz_export only writes as many
85 bytes as it needs (including none, if the value to export is zero. */
86 memset (buf
.data (), 0, buf
.size ());
87 mpz_export (buf
.data (), NULL
/* count */, -1 /* order */,
88 buf
.size () /* size */,
89 byte_order
== BFD_ENDIAN_BIG
? 1 : -1 /* endian */,
90 0 /* nails */, exported_val
.val
);
93 /* See gmp-utils.h. */
96 gdb_mpq::get_rounded () const
98 /* Work with a positive number so as to make the "floor" rounding
99 always round towards zero. */
101 gdb_mpq
abs_val (val
);
102 mpq_abs (abs_val
.val
, abs_val
.val
);
104 /* Convert our rational number into a quotient and remainder,
105 with "floor" rounding, which in our case means rounding
108 gdb_mpz quotient
, remainder
;
109 mpz_fdiv_qr (quotient
.val
, remainder
.val
,
110 mpq_numref (abs_val
.val
), mpq_denref (abs_val
.val
));
112 /* Multiply the remainder by 2, and see if it is greater or equal
113 to abs_val's denominator. If yes, round to the next integer. */
115 mpz_mul_ui (remainder
.val
, remainder
.val
, 2);
116 if (mpz_cmp (remainder
.val
, mpq_denref (abs_val
.val
)) >= 0)
117 mpz_add_ui (quotient
.val
, quotient
.val
, 1);
119 /* Re-apply the sign if needed. */
120 if (mpq_sgn (val
) < 0)
121 mpz_neg (quotient
.val
, quotient
.val
);
126 /* See gmp-utils.h. */
129 gdb_mpq::read_fixed_point (gdb::array_view
<const gdb_byte
> buf
,
130 enum bfd_endian byte_order
, bool unsigned_p
,
131 const gdb_mpq
&scaling_factor
)
134 vz
.read (buf
, byte_order
, unsigned_p
);
136 mpq_set_z (val
, vz
.val
);
137 mpq_mul (val
, val
, scaling_factor
.val
);
140 /* See gmp-utils.h. */
143 gdb_mpq::write_fixed_point (gdb::array_view
<gdb_byte
> buf
,
144 enum bfd_endian byte_order
, bool unsigned_p
,
145 const gdb_mpq
&scaling_factor
) const
147 gdb_mpq
unscaled (val
);
149 mpq_div (unscaled
.val
, unscaled
.val
, scaling_factor
.val
);
151 gdb_mpz unscaled_z
= unscaled
.get_rounded ();
152 unscaled_z
.write (buf
, byte_order
, unsigned_p
);
155 /* A wrapper around xrealloc that we can then register with GMP
156 as the "realloc" function. */
159 xrealloc_for_gmp (void *ptr
, size_t old_size
, size_t new_size
)
161 return xrealloc (ptr
, new_size
);
164 /* A wrapper around xfree that we can then register with GMP
165 as the "free" function. */
168 xfree_for_gmp (void *ptr
, size_t size
)
173 void _initialize_gmp_utils ();
176 _initialize_gmp_utils ()
178 /* Tell GMP to use GDB's memory management routines. */
179 mp_set_memory_functions (xmalloc
, xrealloc_for_gmp
, xfree_for_gmp
);
This page took 0.035781 seconds and 3 git commands to generate.