annotate gcc/wide-int.h @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Operations with very long integers. -*- C++ -*-
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
7 under the terms of the GNU General Public License as published by the
kono
parents:
diff changeset
8 Free Software Foundation; either version 3, or (at your option) any
kono
parents:
diff changeset
9 later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT
kono
parents:
diff changeset
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
14 for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #ifndef WIDE_INT_H
kono
parents:
diff changeset
21 #define WIDE_INT_H
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 /* wide-int.[cc|h] implements a class that efficiently performs
kono
parents:
diff changeset
24 mathematical operations on finite precision integers. wide_ints
kono
parents:
diff changeset
25 are designed to be transient - they are not for long term storage
kono
parents:
diff changeset
26 of values. There is tight integration between wide_ints and the
kono
parents:
diff changeset
27 other longer storage GCC representations (rtl and tree).
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 The actual precision of a wide_int depends on the flavor. There
kono
parents:
diff changeset
30 are three predefined flavors:
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 1) wide_int (the default). This flavor does the math in the
kono
parents:
diff changeset
33 precision of its input arguments. It is assumed (and checked)
kono
parents:
diff changeset
34 that the precisions of the operands and results are consistent.
kono
parents:
diff changeset
35 This is the most efficient flavor. It is not possible to examine
kono
parents:
diff changeset
36 bits above the precision that has been specified. Because of
kono
parents:
diff changeset
37 this, the default flavor has semantics that are simple to
kono
parents:
diff changeset
38 understand and in general model the underlying hardware that the
kono
parents:
diff changeset
39 compiler is targetted for.
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 This flavor must be used at the RTL level of gcc because there
kono
parents:
diff changeset
42 is, in general, not enough information in the RTL representation
kono
parents:
diff changeset
43 to extend a value beyond the precision specified in the mode.
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 This flavor should also be used at the TREE and GIMPLE levels of
kono
parents:
diff changeset
46 the compiler except for the circumstances described in the
kono
parents:
diff changeset
47 descriptions of the other two flavors.
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 The default wide_int representation does not contain any
kono
parents:
diff changeset
50 information inherent about signedness of the represented value,
kono
parents:
diff changeset
51 so it can be used to represent both signed and unsigned numbers.
kono
parents:
diff changeset
52 For operations where the results depend on signedness (full width
kono
parents:
diff changeset
53 multiply, division, shifts, comparisons, and operations that need
kono
parents:
diff changeset
54 overflow detected), the signedness must be specified separately.
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 2) offset_int. This is a fixed-precision integer that can hold
kono
parents:
diff changeset
57 any address offset, measured in either bits or bytes, with at
kono
parents:
diff changeset
58 least one extra sign bit. At the moment the maximum address
kono
parents:
diff changeset
59 size GCC supports is 64 bits. With 8-bit bytes and an extra
kono
parents:
diff changeset
60 sign bit, offset_int therefore needs to have at least 68 bits
kono
parents:
diff changeset
61 of precision. We round this up to 128 bits for efficiency.
kono
parents:
diff changeset
62 Values of type T are converted to this precision by sign- or
kono
parents:
diff changeset
63 zero-extending them based on the signedness of T.
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 The extra sign bit means that offset_int is effectively a signed
kono
parents:
diff changeset
66 128-bit integer, i.e. it behaves like int128_t.
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 Since the values are logically signed, there is no need to
kono
parents:
diff changeset
69 distinguish between signed and unsigned operations. Sign-sensitive
kono
parents:
diff changeset
70 comparison operators <, <=, > and >= are therefore supported.
kono
parents:
diff changeset
71 Shift operators << and >> are also supported, with >> being
kono
parents:
diff changeset
72 an _arithmetic_ right shift.
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 [ Note that, even though offset_int is effectively int128_t,
kono
parents:
diff changeset
75 it can still be useful to use unsigned comparisons like
kono
parents:
diff changeset
76 wi::leu_p (a, b) as a more efficient short-hand for
kono
parents:
diff changeset
77 "a >= 0 && a <= b". ]
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 3) widest_int. This representation is an approximation of
kono
parents:
diff changeset
80 infinite precision math. However, it is not really infinite
kono
parents:
diff changeset
81 precision math as in the GMP library. It is really finite
kono
parents:
diff changeset
82 precision math where the precision is 4 times the size of the
kono
parents:
diff changeset
83 largest integer that the target port can represent.
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 Like offset_int, widest_int is wider than all the values that
kono
parents:
diff changeset
86 it needs to represent, so the integers are logically signed.
kono
parents:
diff changeset
87 Sign-sensitive comparison operators <, <=, > and >= are supported,
kono
parents:
diff changeset
88 as are << and >>.
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 There are several places in the GCC where this should/must be used:
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 * Code that does induction variable optimizations. This code
kono
parents:
diff changeset
93 works with induction variables of many different types at the
kono
parents:
diff changeset
94 same time. Because of this, it ends up doing many different
kono
parents:
diff changeset
95 calculations where the operands are not compatible types. The
kono
parents:
diff changeset
96 widest_int makes this easy, because it provides a field where
kono
parents:
diff changeset
97 nothing is lost when converting from any variable,
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 * There are a small number of passes that currently use the
kono
parents:
diff changeset
100 widest_int that should use the default. These should be
kono
parents:
diff changeset
101 changed.
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 There are surprising features of offset_int and widest_int
kono
parents:
diff changeset
104 that the users should be careful about:
kono
parents:
diff changeset
105
kono
parents:
diff changeset
106 1) Shifts and rotations are just weird. You have to specify a
kono
parents:
diff changeset
107 precision in which the shift or rotate is to happen in. The bits
kono
parents:
diff changeset
108 above this precision are zeroed. While this is what you
kono
parents:
diff changeset
109 want, it is clearly non obvious.
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 2) Larger precision math sometimes does not produce the same
kono
parents:
diff changeset
112 answer as would be expected for doing the math at the proper
kono
parents:
diff changeset
113 precision. In particular, a multiply followed by a divide will
kono
parents:
diff changeset
114 produce a different answer if the first product is larger than
kono
parents:
diff changeset
115 what can be represented in the input precision.
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 The offset_int and the widest_int flavors are more expensive
kono
parents:
diff changeset
118 than the default wide int, so in addition to the caveats with these
kono
parents:
diff changeset
119 two, the default is the prefered representation.
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 All three flavors of wide_int are represented as a vector of
kono
parents:
diff changeset
122 HOST_WIDE_INTs. The default and widest_int vectors contain enough elements
kono
parents:
diff changeset
123 to hold a value of MAX_BITSIZE_MODE_ANY_INT bits. offset_int contains only
kono
parents:
diff changeset
124 enough elements to hold ADDR_MAX_PRECISION bits. The values are stored
kono
parents:
diff changeset
125 in the vector with the least significant HOST_BITS_PER_WIDE_INT bits
kono
parents:
diff changeset
126 in element 0.
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 The default wide_int contains three fields: the vector (VAL),
kono
parents:
diff changeset
129 the precision and a length (LEN). The length is the number of HWIs
kono
parents:
diff changeset
130 needed to represent the value. widest_int and offset_int have a
kono
parents:
diff changeset
131 constant precision that cannot be changed, so they only store the
kono
parents:
diff changeset
132 VAL and LEN fields.
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 Since most integers used in a compiler are small values, it is
kono
parents:
diff changeset
135 generally profitable to use a representation of the value that is
kono
parents:
diff changeset
136 as small as possible. LEN is used to indicate the number of
kono
parents:
diff changeset
137 elements of the vector that are in use. The numbers are stored as
kono
parents:
diff changeset
138 sign extended numbers as a means of compression. Leading
kono
parents:
diff changeset
139 HOST_WIDE_INTs that contain strings of either -1 or 0 are removed
kono
parents:
diff changeset
140 as long as they can be reconstructed from the top bit that is being
kono
parents:
diff changeset
141 represented.
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 The precision and length of a wide_int are always greater than 0.
kono
parents:
diff changeset
144 Any bits in a wide_int above the precision are sign-extended from the
kono
parents:
diff changeset
145 most significant bit. For example, a 4-bit value 0x8 is represented as
kono
parents:
diff changeset
146 VAL = { 0xf...fff8 }. However, as an optimization, we allow other integer
kono
parents:
diff changeset
147 constants to be represented with undefined bits above the precision.
kono
parents:
diff changeset
148 This allows INTEGER_CSTs to be pre-extended according to TYPE_SIGN,
kono
parents:
diff changeset
149 so that the INTEGER_CST representation can be used both in TYPE_PRECISION
kono
parents:
diff changeset
150 and in wider precisions.
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 There are constructors to create the various forms of wide_int from
kono
parents:
diff changeset
153 trees, rtl and constants. For trees the options are:
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 tree t = ...;
kono
parents:
diff changeset
156 wi::to_wide (t) // Treat T as a wide_int
kono
parents:
diff changeset
157 wi::to_offset (t) // Treat T as an offset_int
kono
parents:
diff changeset
158 wi::to_widest (t) // Treat T as a widest_int
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 All three are light-weight accessors that should have no overhead
kono
parents:
diff changeset
161 in release builds. If it is useful for readability reasons to
kono
parents:
diff changeset
162 store the result in a temporary variable, the preferred method is:
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 wi::tree_to_wide_ref twide = wi::to_wide (t);
kono
parents:
diff changeset
165 wi::tree_to_offset_ref toffset = wi::to_offset (t);
kono
parents:
diff changeset
166 wi::tree_to_widest_ref twidest = wi::to_widest (t);
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 To make an rtx into a wide_int, you have to pair it with a mode.
kono
parents:
diff changeset
169 The canonical way to do this is with rtx_mode_t as in:
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 rtx r = ...
kono
parents:
diff changeset
172 wide_int x = rtx_mode_t (r, mode);
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 Similarly, a wide_int can only be constructed from a host value if
kono
parents:
diff changeset
175 the target precision is given explicitly, such as in:
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 wide_int x = wi::shwi (c, prec); // sign-extend C if necessary
kono
parents:
diff changeset
178 wide_int y = wi::uhwi (c, prec); // zero-extend C if necessary
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 However, offset_int and widest_int have an inherent precision and so
kono
parents:
diff changeset
181 can be initialized directly from a host value:
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 offset_int x = (int) c; // sign-extend C
kono
parents:
diff changeset
184 widest_int x = (unsigned int) c; // zero-extend C
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 It is also possible to do arithmetic directly on rtx_mode_ts and
kono
parents:
diff changeset
187 constants. For example:
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 wi::add (r1, r2); // add equal-sized rtx_mode_ts r1 and r2
kono
parents:
diff changeset
190 wi::add (r1, 1); // add 1 to rtx_mode_t r1
kono
parents:
diff changeset
191 wi::lshift (1, 100); // 1 << 100 as a widest_int
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 Many binary operations place restrictions on the combinations of inputs,
kono
parents:
diff changeset
194 using the following rules:
kono
parents:
diff changeset
195
kono
parents:
diff changeset
196 - {rtx, wide_int} op {rtx, wide_int} -> wide_int
kono
parents:
diff changeset
197 The inputs must be the same precision. The result is a wide_int
kono
parents:
diff changeset
198 of the same precision
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 - {rtx, wide_int} op (un)signed HOST_WIDE_INT -> wide_int
kono
parents:
diff changeset
201 (un)signed HOST_WIDE_INT op {rtx, wide_int} -> wide_int
kono
parents:
diff changeset
202 The HOST_WIDE_INT is extended or truncated to the precision of
kono
parents:
diff changeset
203 the other input. The result is a wide_int of the same precision
kono
parents:
diff changeset
204 as that input.
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 - (un)signed HOST_WIDE_INT op (un)signed HOST_WIDE_INT -> widest_int
kono
parents:
diff changeset
207 The inputs are extended to widest_int precision and produce a
kono
parents:
diff changeset
208 widest_int result.
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 - offset_int op offset_int -> offset_int
kono
parents:
diff changeset
211 offset_int op (un)signed HOST_WIDE_INT -> offset_int
kono
parents:
diff changeset
212 (un)signed HOST_WIDE_INT op offset_int -> offset_int
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 - widest_int op widest_int -> widest_int
kono
parents:
diff changeset
215 widest_int op (un)signed HOST_WIDE_INT -> widest_int
kono
parents:
diff changeset
216 (un)signed HOST_WIDE_INT op widest_int -> widest_int
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 Other combinations like:
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 - widest_int op offset_int and
kono
parents:
diff changeset
221 - wide_int op offset_int
kono
parents:
diff changeset
222
kono
parents:
diff changeset
223 are not allowed. The inputs should instead be extended or truncated
kono
parents:
diff changeset
224 so that they match.
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 The inputs to comparison functions like wi::eq_p and wi::lts_p
kono
parents:
diff changeset
227 follow the same compatibility rules, although their return types
kono
parents:
diff changeset
228 are different. Unary functions on X produce the same result as
kono
parents:
diff changeset
229 a binary operation X + X. Shift functions X op Y also produce
kono
parents:
diff changeset
230 the same result as X + X; the precision of the shift amount Y
kono
parents:
diff changeset
231 can be arbitrarily different from X. */
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 /* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
kono
parents:
diff changeset
234 early examination of the target's mode file. The WIDE_INT_MAX_ELTS
kono
parents:
diff changeset
235 can accomodate at least 1 more bit so that unsigned numbers of that
kono
parents:
diff changeset
236 mode can be represented as a signed value. Note that it is still
kono
parents:
diff changeset
237 possible to create fixed_wide_ints that have precisions greater than
kono
parents:
diff changeset
238 MAX_BITSIZE_MODE_ANY_INT. This can be useful when representing a
kono
parents:
diff changeset
239 double-width multiplication result, for example. */
kono
parents:
diff changeset
240 #define WIDE_INT_MAX_ELTS \
kono
parents:
diff changeset
241 ((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT) / HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 #define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 /* This is the max size of any pointer on any machine. It does not
kono
parents:
diff changeset
246 seem to be as easy to sniff this out of the machine description as
kono
parents:
diff changeset
247 it is for MAX_BITSIZE_MODE_ANY_INT since targets may support
kono
parents:
diff changeset
248 multiple address sizes and may have different address sizes for
kono
parents:
diff changeset
249 different address spaces. However, currently the largest pointer
kono
parents:
diff changeset
250 on any platform is 64 bits. When that changes, then it is likely
kono
parents:
diff changeset
251 that a target hook should be defined so that targets can make this
kono
parents:
diff changeset
252 value larger for those targets. */
kono
parents:
diff changeset
253 #define ADDR_MAX_BITSIZE 64
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 /* This is the internal precision used when doing any address
kono
parents:
diff changeset
256 arithmetic. The '4' is really 3 + 1. Three of the bits are for
kono
parents:
diff changeset
257 the number of extra bits needed to do bit addresses and the other bit
kono
parents:
diff changeset
258 is to allow everything to be signed without loosing any precision.
kono
parents:
diff changeset
259 Then everything is rounded up to the next HWI for efficiency. */
kono
parents:
diff changeset
260 #define ADDR_MAX_PRECISION \
kono
parents:
diff changeset
261 ((ADDR_MAX_BITSIZE + 4 + HOST_BITS_PER_WIDE_INT - 1) \
kono
parents:
diff changeset
262 & ~(HOST_BITS_PER_WIDE_INT - 1))
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 /* The number of HWIs needed to store an offset_int. */
kono
parents:
diff changeset
265 #define OFFSET_INT_ELTS (ADDR_MAX_PRECISION / HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 /* The type of result produced by a binary operation on types T1 and T2.
kono
parents:
diff changeset
268 Defined purely for brevity. */
kono
parents:
diff changeset
269 #define WI_BINARY_RESULT(T1, T2) \
kono
parents:
diff changeset
270 typename wi::binary_traits <T1, T2>::result_type
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 /* Likewise for binary operators, which excludes the case in which neither
kono
parents:
diff changeset
273 T1 nor T2 is a wide-int-based type. */
kono
parents:
diff changeset
274 #define WI_BINARY_OPERATOR_RESULT(T1, T2) \
kono
parents:
diff changeset
275 typename wi::binary_traits <T1, T2>::operator_result
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 /* The type of result produced by T1 << T2. Leads to substitution failure
kono
parents:
diff changeset
278 if the operation isn't supported. Defined purely for brevity. */
kono
parents:
diff changeset
279 #define WI_SIGNED_SHIFT_RESULT(T1, T2) \
kono
parents:
diff changeset
280 typename wi::binary_traits <T1, T2>::signed_shift_result_type
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 /* The type of result produced by a sign-agnostic binary predicate on
kono
parents:
diff changeset
283 types T1 and T2. This is bool if wide-int operations make sense for
kono
parents:
diff changeset
284 T1 and T2 and leads to substitution failure otherwise. */
kono
parents:
diff changeset
285 #define WI_BINARY_PREDICATE_RESULT(T1, T2) \
kono
parents:
diff changeset
286 typename wi::binary_traits <T1, T2>::predicate_result
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 /* The type of result produced by a signed binary predicate on types T1 and T2.
kono
parents:
diff changeset
289 This is bool if signed comparisons make sense for T1 and T2 and leads to
kono
parents:
diff changeset
290 substitution failure otherwise. */
kono
parents:
diff changeset
291 #define WI_SIGNED_BINARY_PREDICATE_RESULT(T1, T2) \
kono
parents:
diff changeset
292 typename wi::binary_traits <T1, T2>::signed_predicate_result
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 /* The type of result produced by a unary operation on type T. */
kono
parents:
diff changeset
295 #define WI_UNARY_RESULT(T) \
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
296 typename wi::binary_traits <T, T>::result_type
111
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 /* Define a variable RESULT to hold the result of a binary operation on
kono
parents:
diff changeset
299 X and Y, which have types T1 and T2 respectively. Define VAL to
kono
parents:
diff changeset
300 point to the blocks of RESULT. Once the user of the macro has
kono
parents:
diff changeset
301 filled in VAL, it should call RESULT.set_len to set the number
kono
parents:
diff changeset
302 of initialized blocks. */
kono
parents:
diff changeset
303 #define WI_BINARY_RESULT_VAR(RESULT, VAL, T1, X, T2, Y) \
kono
parents:
diff changeset
304 WI_BINARY_RESULT (T1, T2) RESULT = \
kono
parents:
diff changeset
305 wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_result (X, Y); \
kono
parents:
diff changeset
306 HOST_WIDE_INT *VAL = RESULT.write_val ()
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 /* Similar for the result of a unary operation on X, which has type T. */
kono
parents:
diff changeset
309 #define WI_UNARY_RESULT_VAR(RESULT, VAL, T, X) \
kono
parents:
diff changeset
310 WI_UNARY_RESULT (T) RESULT = \
kono
parents:
diff changeset
311 wi::int_traits <WI_UNARY_RESULT (T)>::get_binary_result (X, X); \
kono
parents:
diff changeset
312 HOST_WIDE_INT *VAL = RESULT.write_val ()
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 template <typename T> class generic_wide_int;
kono
parents:
diff changeset
315 template <int N> class fixed_wide_int_storage;
kono
parents:
diff changeset
316 class wide_int_storage;
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 /* An N-bit integer. Until we can use typedef templates, use this instead. */
kono
parents:
diff changeset
319 #define FIXED_WIDE_INT(N) \
kono
parents:
diff changeset
320 generic_wide_int < fixed_wide_int_storage <N> >
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 typedef generic_wide_int <wide_int_storage> wide_int;
kono
parents:
diff changeset
323 typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
kono
parents:
diff changeset
324 typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
325 /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
326 so as not to confuse gengtype. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
327 typedef generic_wide_int < fixed_wide_int_storage <WIDE_INT_MAX_PRECISION * 2> > widest2_int;
111
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 /* wi::storage_ref can be a reference to a primitive type,
kono
parents:
diff changeset
330 so this is the conservatively-correct setting. */
kono
parents:
diff changeset
331 template <bool SE, bool HDP = true>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
332 class wide_int_ref_storage;
111
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 typedef generic_wide_int <wide_int_ref_storage <false> > wide_int_ref;
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 /* This can be used instead of wide_int_ref if the referenced value is
kono
parents:
diff changeset
337 known to have type T. It carries across properties of T's representation,
kono
parents:
diff changeset
338 such as whether excess upper bits in a HWI are defined, and can therefore
kono
parents:
diff changeset
339 help avoid redundant work.
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 The macro could be replaced with a template typedef, once we're able
kono
parents:
diff changeset
342 to use those. */
kono
parents:
diff changeset
343 #define WIDE_INT_REF_FOR(T) \
kono
parents:
diff changeset
344 generic_wide_int \
kono
parents:
diff changeset
345 <wide_int_ref_storage <wi::int_traits <T>::is_sign_extended, \
kono
parents:
diff changeset
346 wi::int_traits <T>::host_dependent_precision> >
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 namespace wi
kono
parents:
diff changeset
349 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
350 /* Operations that calculate overflow do so even for
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
351 TYPE_OVERFLOW_WRAPS types. For example, adding 1 to +MAX_INT in
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
352 an unsigned int is 0 and does not overflow in C/C++, but wi::add
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
353 will set the overflow argument in case it's needed for further
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
354 analysis.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
355
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
356 For operations that require overflow, these are the different
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
357 types of overflow. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
358 enum overflow_type {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
359 OVF_NONE = 0,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
360 OVF_UNDERFLOW = -1,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
361 OVF_OVERFLOW = 1,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
362 /* There was an overflow, but we are unsure whether it was an
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
363 overflow or an underflow. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
364 OVF_UNKNOWN = 2
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
365 };
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
366
111
kono
parents:
diff changeset
367 /* Classifies an integer based on its precision. */
kono
parents:
diff changeset
368 enum precision_type {
kono
parents:
diff changeset
369 /* The integer has both a precision and defined signedness. This allows
kono
parents:
diff changeset
370 the integer to be converted to any width, since we know whether to fill
kono
parents:
diff changeset
371 any extra bits with zeros or signs. */
kono
parents:
diff changeset
372 FLEXIBLE_PRECISION,
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 /* The integer has a variable precision but no defined signedness. */
kono
parents:
diff changeset
375 VAR_PRECISION,
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 /* The integer has a constant precision (known at GCC compile time)
kono
parents:
diff changeset
378 and is signed. */
kono
parents:
diff changeset
379 CONST_PRECISION
kono
parents:
diff changeset
380 };
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 /* This class, which has no default implementation, is expected to
kono
parents:
diff changeset
383 provide the following members:
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 static const enum precision_type precision_type;
kono
parents:
diff changeset
386 Classifies the type of T.
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 static const unsigned int precision;
kono
parents:
diff changeset
389 Only defined if precision_type == CONST_PRECISION. Specifies the
kono
parents:
diff changeset
390 precision of all integers of type T.
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 static const bool host_dependent_precision;
kono
parents:
diff changeset
393 True if the precision of T depends (or can depend) on the host.
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 static unsigned int get_precision (const T &x)
kono
parents:
diff changeset
396 Return the number of bits in X.
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 static wi::storage_ref *decompose (HOST_WIDE_INT *scratch,
kono
parents:
diff changeset
399 unsigned int precision, const T &x)
kono
parents:
diff changeset
400 Decompose X as a PRECISION-bit integer, returning the associated
kono
parents:
diff changeset
401 wi::storage_ref. SCRATCH is available as scratch space if needed.
kono
parents:
diff changeset
402 The routine should assert that PRECISION is acceptable. */
kono
parents:
diff changeset
403 template <typename T> struct int_traits;
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 /* This class provides a single type, result_type, which specifies the
kono
parents:
diff changeset
406 type of integer produced by a binary operation whose inputs have
kono
parents:
diff changeset
407 types T1 and T2. The definition should be symmetric. */
kono
parents:
diff changeset
408 template <typename T1, typename T2,
kono
parents:
diff changeset
409 enum precision_type P1 = int_traits <T1>::precision_type,
kono
parents:
diff changeset
410 enum precision_type P2 = int_traits <T2>::precision_type>
kono
parents:
diff changeset
411 struct binary_traits;
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 /* Specify the result type for each supported combination of binary
kono
parents:
diff changeset
414 inputs. Note that CONST_PRECISION and VAR_PRECISION cannot be
kono
parents:
diff changeset
415 mixed, in order to give stronger type checking. When both inputs
kono
parents:
diff changeset
416 are CONST_PRECISION, they must have the same precision. */
kono
parents:
diff changeset
417 template <typename T1, typename T2>
kono
parents:
diff changeset
418 struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION>
kono
parents:
diff changeset
419 {
kono
parents:
diff changeset
420 typedef widest_int result_type;
kono
parents:
diff changeset
421 /* Don't define operators for this combination. */
kono
parents:
diff changeset
422 };
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 template <typename T1, typename T2>
kono
parents:
diff changeset
425 struct binary_traits <T1, T2, FLEXIBLE_PRECISION, VAR_PRECISION>
kono
parents:
diff changeset
426 {
kono
parents:
diff changeset
427 typedef wide_int result_type;
kono
parents:
diff changeset
428 typedef result_type operator_result;
kono
parents:
diff changeset
429 typedef bool predicate_result;
kono
parents:
diff changeset
430 };
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 template <typename T1, typename T2>
kono
parents:
diff changeset
433 struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION>
kono
parents:
diff changeset
434 {
kono
parents:
diff changeset
435 /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
kono
parents:
diff changeset
436 so as not to confuse gengtype. */
kono
parents:
diff changeset
437 typedef generic_wide_int < fixed_wide_int_storage
kono
parents:
diff changeset
438 <int_traits <T2>::precision> > result_type;
kono
parents:
diff changeset
439 typedef result_type operator_result;
kono
parents:
diff changeset
440 typedef bool predicate_result;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
441 typedef result_type signed_shift_result_type;
111
kono
parents:
diff changeset
442 typedef bool signed_predicate_result;
kono
parents:
diff changeset
443 };
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 template <typename T1, typename T2>
kono
parents:
diff changeset
446 struct binary_traits <T1, T2, VAR_PRECISION, FLEXIBLE_PRECISION>
kono
parents:
diff changeset
447 {
kono
parents:
diff changeset
448 typedef wide_int result_type;
kono
parents:
diff changeset
449 typedef result_type operator_result;
kono
parents:
diff changeset
450 typedef bool predicate_result;
kono
parents:
diff changeset
451 };
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 template <typename T1, typename T2>
kono
parents:
diff changeset
454 struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION>
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
kono
parents:
diff changeset
457 so as not to confuse gengtype. */
kono
parents:
diff changeset
458 typedef generic_wide_int < fixed_wide_int_storage
kono
parents:
diff changeset
459 <int_traits <T1>::precision> > result_type;
kono
parents:
diff changeset
460 typedef result_type operator_result;
kono
parents:
diff changeset
461 typedef bool predicate_result;
kono
parents:
diff changeset
462 typedef result_type signed_shift_result_type;
kono
parents:
diff changeset
463 typedef bool signed_predicate_result;
kono
parents:
diff changeset
464 };
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 template <typename T1, typename T2>
kono
parents:
diff changeset
467 struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
kono
parents:
diff changeset
468 {
kono
parents:
diff changeset
469 STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
kono
parents:
diff changeset
470 /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
kono
parents:
diff changeset
471 so as not to confuse gengtype. */
kono
parents:
diff changeset
472 typedef generic_wide_int < fixed_wide_int_storage
kono
parents:
diff changeset
473 <int_traits <T1>::precision> > result_type;
kono
parents:
diff changeset
474 typedef result_type operator_result;
kono
parents:
diff changeset
475 typedef bool predicate_result;
kono
parents:
diff changeset
476 typedef result_type signed_shift_result_type;
kono
parents:
diff changeset
477 typedef bool signed_predicate_result;
kono
parents:
diff changeset
478 };
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 template <typename T1, typename T2>
kono
parents:
diff changeset
481 struct binary_traits <T1, T2, VAR_PRECISION, VAR_PRECISION>
kono
parents:
diff changeset
482 {
kono
parents:
diff changeset
483 typedef wide_int result_type;
kono
parents:
diff changeset
484 typedef result_type operator_result;
kono
parents:
diff changeset
485 typedef bool predicate_result;
kono
parents:
diff changeset
486 };
kono
parents:
diff changeset
487 }
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 /* Public functions for querying and operating on integers. */
kono
parents:
diff changeset
490 namespace wi
kono
parents:
diff changeset
491 {
kono
parents:
diff changeset
492 template <typename T>
kono
parents:
diff changeset
493 unsigned int get_precision (const T &);
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 template <typename T1, typename T2>
kono
parents:
diff changeset
496 unsigned int get_binary_precision (const T1 &, const T2 &);
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 template <typename T1, typename T2>
kono
parents:
diff changeset
499 void copy (T1 &, const T2 &);
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 #define UNARY_PREDICATE \
kono
parents:
diff changeset
502 template <typename T> bool
kono
parents:
diff changeset
503 #define UNARY_FUNCTION \
kono
parents:
diff changeset
504 template <typename T> WI_UNARY_RESULT (T)
kono
parents:
diff changeset
505 #define BINARY_PREDICATE \
kono
parents:
diff changeset
506 template <typename T1, typename T2> bool
kono
parents:
diff changeset
507 #define BINARY_FUNCTION \
kono
parents:
diff changeset
508 template <typename T1, typename T2> WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
509 #define SHIFT_FUNCTION \
kono
parents:
diff changeset
510 template <typename T1, typename T2> WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 UNARY_PREDICATE fits_shwi_p (const T &);
kono
parents:
diff changeset
513 UNARY_PREDICATE fits_uhwi_p (const T &);
kono
parents:
diff changeset
514 UNARY_PREDICATE neg_p (const T &, signop = SIGNED);
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 template <typename T>
kono
parents:
diff changeset
517 HOST_WIDE_INT sign_mask (const T &);
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 BINARY_PREDICATE eq_p (const T1 &, const T2 &);
kono
parents:
diff changeset
520 BINARY_PREDICATE ne_p (const T1 &, const T2 &);
kono
parents:
diff changeset
521 BINARY_PREDICATE lt_p (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
522 BINARY_PREDICATE lts_p (const T1 &, const T2 &);
kono
parents:
diff changeset
523 BINARY_PREDICATE ltu_p (const T1 &, const T2 &);
kono
parents:
diff changeset
524 BINARY_PREDICATE le_p (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
525 BINARY_PREDICATE les_p (const T1 &, const T2 &);
kono
parents:
diff changeset
526 BINARY_PREDICATE leu_p (const T1 &, const T2 &);
kono
parents:
diff changeset
527 BINARY_PREDICATE gt_p (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
528 BINARY_PREDICATE gts_p (const T1 &, const T2 &);
kono
parents:
diff changeset
529 BINARY_PREDICATE gtu_p (const T1 &, const T2 &);
kono
parents:
diff changeset
530 BINARY_PREDICATE ge_p (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
531 BINARY_PREDICATE ges_p (const T1 &, const T2 &);
kono
parents:
diff changeset
532 BINARY_PREDICATE geu_p (const T1 &, const T2 &);
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 template <typename T1, typename T2>
kono
parents:
diff changeset
535 int cmp (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 template <typename T1, typename T2>
kono
parents:
diff changeset
538 int cmps (const T1 &, const T2 &);
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 template <typename T1, typename T2>
kono
parents:
diff changeset
541 int cmpu (const T1 &, const T2 &);
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 UNARY_FUNCTION bit_not (const T &);
kono
parents:
diff changeset
544 UNARY_FUNCTION neg (const T &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
545 UNARY_FUNCTION neg (const T &, overflow_type *);
111
kono
parents:
diff changeset
546 UNARY_FUNCTION abs (const T &);
kono
parents:
diff changeset
547 UNARY_FUNCTION ext (const T &, unsigned int, signop);
kono
parents:
diff changeset
548 UNARY_FUNCTION sext (const T &, unsigned int);
kono
parents:
diff changeset
549 UNARY_FUNCTION zext (const T &, unsigned int);
kono
parents:
diff changeset
550 UNARY_FUNCTION set_bit (const T &, unsigned int);
kono
parents:
diff changeset
551
kono
parents:
diff changeset
552 BINARY_FUNCTION min (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
553 BINARY_FUNCTION smin (const T1 &, const T2 &);
kono
parents:
diff changeset
554 BINARY_FUNCTION umin (const T1 &, const T2 &);
kono
parents:
diff changeset
555 BINARY_FUNCTION max (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
556 BINARY_FUNCTION smax (const T1 &, const T2 &);
kono
parents:
diff changeset
557 BINARY_FUNCTION umax (const T1 &, const T2 &);
kono
parents:
diff changeset
558
kono
parents:
diff changeset
559 BINARY_FUNCTION bit_and (const T1 &, const T2 &);
kono
parents:
diff changeset
560 BINARY_FUNCTION bit_and_not (const T1 &, const T2 &);
kono
parents:
diff changeset
561 BINARY_FUNCTION bit_or (const T1 &, const T2 &);
kono
parents:
diff changeset
562 BINARY_FUNCTION bit_or_not (const T1 &, const T2 &);
kono
parents:
diff changeset
563 BINARY_FUNCTION bit_xor (const T1 &, const T2 &);
kono
parents:
diff changeset
564 BINARY_FUNCTION add (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
565 BINARY_FUNCTION add (const T1 &, const T2 &, signop, overflow_type *);
111
kono
parents:
diff changeset
566 BINARY_FUNCTION sub (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
567 BINARY_FUNCTION sub (const T1 &, const T2 &, signop, overflow_type *);
111
kono
parents:
diff changeset
568 BINARY_FUNCTION mul (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
569 BINARY_FUNCTION mul (const T1 &, const T2 &, signop, overflow_type *);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
570 BINARY_FUNCTION smul (const T1 &, const T2 &, overflow_type *);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
571 BINARY_FUNCTION umul (const T1 &, const T2 &, overflow_type *);
111
kono
parents:
diff changeset
572 BINARY_FUNCTION mul_high (const T1 &, const T2 &, signop);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
573 BINARY_FUNCTION div_trunc (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
574 overflow_type * = 0);
111
kono
parents:
diff changeset
575 BINARY_FUNCTION sdiv_trunc (const T1 &, const T2 &);
kono
parents:
diff changeset
576 BINARY_FUNCTION udiv_trunc (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
577 BINARY_FUNCTION div_floor (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
578 overflow_type * = 0);
111
kono
parents:
diff changeset
579 BINARY_FUNCTION udiv_floor (const T1 &, const T2 &);
kono
parents:
diff changeset
580 BINARY_FUNCTION sdiv_floor (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
581 BINARY_FUNCTION div_ceil (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
582 overflow_type * = 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
583 BINARY_FUNCTION udiv_ceil (const T1 &, const T2 &);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
584 BINARY_FUNCTION div_round (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
585 overflow_type * = 0);
111
kono
parents:
diff changeset
586 BINARY_FUNCTION divmod_trunc (const T1 &, const T2 &, signop,
kono
parents:
diff changeset
587 WI_BINARY_RESULT (T1, T2) *);
kono
parents:
diff changeset
588 BINARY_FUNCTION gcd (const T1 &, const T2 &, signop = UNSIGNED);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
589 BINARY_FUNCTION mod_trunc (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
590 overflow_type * = 0);
111
kono
parents:
diff changeset
591 BINARY_FUNCTION smod_trunc (const T1 &, const T2 &);
kono
parents:
diff changeset
592 BINARY_FUNCTION umod_trunc (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
593 BINARY_FUNCTION mod_floor (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
594 overflow_type * = 0);
111
kono
parents:
diff changeset
595 BINARY_FUNCTION umod_floor (const T1 &, const T2 &);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
596 BINARY_FUNCTION mod_ceil (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
597 overflow_type * = 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
598 BINARY_FUNCTION mod_round (const T1 &, const T2 &, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
599 overflow_type * = 0);
111
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 template <typename T1, typename T2>
kono
parents:
diff changeset
602 bool multiple_of_p (const T1 &, const T2 &, signop);
kono
parents:
diff changeset
603
kono
parents:
diff changeset
604 template <typename T1, typename T2>
kono
parents:
diff changeset
605 bool multiple_of_p (const T1 &, const T2 &, signop,
kono
parents:
diff changeset
606 WI_BINARY_RESULT (T1, T2) *);
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 SHIFT_FUNCTION lshift (const T1 &, const T2 &);
kono
parents:
diff changeset
609 SHIFT_FUNCTION lrshift (const T1 &, const T2 &);
kono
parents:
diff changeset
610 SHIFT_FUNCTION arshift (const T1 &, const T2 &);
kono
parents:
diff changeset
611 SHIFT_FUNCTION rshift (const T1 &, const T2 &, signop sgn);
kono
parents:
diff changeset
612 SHIFT_FUNCTION lrotate (const T1 &, const T2 &, unsigned int = 0);
kono
parents:
diff changeset
613 SHIFT_FUNCTION rrotate (const T1 &, const T2 &, unsigned int = 0);
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 #undef SHIFT_FUNCTION
kono
parents:
diff changeset
616 #undef BINARY_PREDICATE
kono
parents:
diff changeset
617 #undef BINARY_FUNCTION
kono
parents:
diff changeset
618 #undef UNARY_PREDICATE
kono
parents:
diff changeset
619 #undef UNARY_FUNCTION
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 bool only_sign_bit_p (const wide_int_ref &, unsigned int);
kono
parents:
diff changeset
622 bool only_sign_bit_p (const wide_int_ref &);
kono
parents:
diff changeset
623 int clz (const wide_int_ref &);
kono
parents:
diff changeset
624 int clrsb (const wide_int_ref &);
kono
parents:
diff changeset
625 int ctz (const wide_int_ref &);
kono
parents:
diff changeset
626 int exact_log2 (const wide_int_ref &);
kono
parents:
diff changeset
627 int floor_log2 (const wide_int_ref &);
kono
parents:
diff changeset
628 int ffs (const wide_int_ref &);
kono
parents:
diff changeset
629 int popcount (const wide_int_ref &);
kono
parents:
diff changeset
630 int parity (const wide_int_ref &);
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 template <typename T>
kono
parents:
diff changeset
633 unsigned HOST_WIDE_INT extract_uhwi (const T &, unsigned int, unsigned int);
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 template <typename T>
kono
parents:
diff changeset
636 unsigned int min_precision (const T &, signop);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
637
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638 static inline void accumulate_overflow (overflow_type &, overflow_type);
111
kono
parents:
diff changeset
639 }
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 namespace wi
kono
parents:
diff changeset
642 {
kono
parents:
diff changeset
643 /* Contains the components of a decomposed integer for easy, direct
kono
parents:
diff changeset
644 access. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
645 class storage_ref
111
kono
parents:
diff changeset
646 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
647 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
648 storage_ref () {}
111
kono
parents:
diff changeset
649 storage_ref (const HOST_WIDE_INT *, unsigned int, unsigned int);
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 const HOST_WIDE_INT *val;
kono
parents:
diff changeset
652 unsigned int len;
kono
parents:
diff changeset
653 unsigned int precision;
kono
parents:
diff changeset
654
kono
parents:
diff changeset
655 /* Provide enough trappings for this class to act as storage for
kono
parents:
diff changeset
656 generic_wide_int. */
kono
parents:
diff changeset
657 unsigned int get_len () const;
kono
parents:
diff changeset
658 unsigned int get_precision () const;
kono
parents:
diff changeset
659 const HOST_WIDE_INT *get_val () const;
kono
parents:
diff changeset
660 };
kono
parents:
diff changeset
661 }
kono
parents:
diff changeset
662
kono
parents:
diff changeset
663 inline::wi::storage_ref::storage_ref (const HOST_WIDE_INT *val_in,
kono
parents:
diff changeset
664 unsigned int len_in,
kono
parents:
diff changeset
665 unsigned int precision_in)
kono
parents:
diff changeset
666 : val (val_in), len (len_in), precision (precision_in)
kono
parents:
diff changeset
667 {
kono
parents:
diff changeset
668 }
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 inline unsigned int
kono
parents:
diff changeset
671 wi::storage_ref::get_len () const
kono
parents:
diff changeset
672 {
kono
parents:
diff changeset
673 return len;
kono
parents:
diff changeset
674 }
kono
parents:
diff changeset
675
kono
parents:
diff changeset
676 inline unsigned int
kono
parents:
diff changeset
677 wi::storage_ref::get_precision () const
kono
parents:
diff changeset
678 {
kono
parents:
diff changeset
679 return precision;
kono
parents:
diff changeset
680 }
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 inline const HOST_WIDE_INT *
kono
parents:
diff changeset
683 wi::storage_ref::get_val () const
kono
parents:
diff changeset
684 {
kono
parents:
diff changeset
685 return val;
kono
parents:
diff changeset
686 }
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 /* This class defines an integer type using the storage provided by the
kono
parents:
diff changeset
689 template argument. The storage class must provide the following
kono
parents:
diff changeset
690 functions:
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 unsigned int get_precision () const
kono
parents:
diff changeset
693 Return the number of bits in the integer.
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 HOST_WIDE_INT *get_val () const
kono
parents:
diff changeset
696 Return a pointer to the array of blocks that encodes the integer.
kono
parents:
diff changeset
697
kono
parents:
diff changeset
698 unsigned int get_len () const
kono
parents:
diff changeset
699 Return the number of blocks in get_val (). If this is smaller
kono
parents:
diff changeset
700 than the number of blocks implied by get_precision (), the
kono
parents:
diff changeset
701 remaining blocks are sign extensions of block get_len () - 1.
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 Although not required by generic_wide_int itself, writable storage
kono
parents:
diff changeset
704 classes can also provide the following functions:
kono
parents:
diff changeset
705
kono
parents:
diff changeset
706 HOST_WIDE_INT *write_val ()
kono
parents:
diff changeset
707 Get a modifiable version of get_val ()
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 unsigned int set_len (unsigned int len)
kono
parents:
diff changeset
710 Set the value returned by get_len () to LEN. */
kono
parents:
diff changeset
711 template <typename storage>
kono
parents:
diff changeset
712 class GTY(()) generic_wide_int : public storage
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 public:
kono
parents:
diff changeset
715 generic_wide_int ();
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 template <typename T>
kono
parents:
diff changeset
718 generic_wide_int (const T &);
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 template <typename T>
kono
parents:
diff changeset
721 generic_wide_int (const T &, unsigned int);
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 /* Conversions. */
kono
parents:
diff changeset
724 HOST_WIDE_INT to_shwi (unsigned int) const;
kono
parents:
diff changeset
725 HOST_WIDE_INT to_shwi () const;
kono
parents:
diff changeset
726 unsigned HOST_WIDE_INT to_uhwi (unsigned int) const;
kono
parents:
diff changeset
727 unsigned HOST_WIDE_INT to_uhwi () const;
kono
parents:
diff changeset
728 HOST_WIDE_INT to_short_addr () const;
kono
parents:
diff changeset
729
kono
parents:
diff changeset
730 /* Public accessors for the interior of a wide int. */
kono
parents:
diff changeset
731 HOST_WIDE_INT sign_mask () const;
kono
parents:
diff changeset
732 HOST_WIDE_INT elt (unsigned int) const;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
733 HOST_WIDE_INT sext_elt (unsigned int) const;
111
kono
parents:
diff changeset
734 unsigned HOST_WIDE_INT ulow () const;
kono
parents:
diff changeset
735 unsigned HOST_WIDE_INT uhigh () const;
kono
parents:
diff changeset
736 HOST_WIDE_INT slow () const;
kono
parents:
diff changeset
737 HOST_WIDE_INT shigh () const;
kono
parents:
diff changeset
738
kono
parents:
diff changeset
739 template <typename T>
kono
parents:
diff changeset
740 generic_wide_int &operator = (const T &);
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 #define ASSIGNMENT_OPERATOR(OP, F) \
kono
parents:
diff changeset
743 template <typename T> \
kono
parents:
diff changeset
744 generic_wide_int &OP (const T &c) { return (*this = wi::F (*this, c)); }
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 /* Restrict these to cases where the shift operator is defined. */
kono
parents:
diff changeset
747 #define SHIFT_ASSIGNMENT_OPERATOR(OP, OP2) \
kono
parents:
diff changeset
748 template <typename T> \
kono
parents:
diff changeset
749 generic_wide_int &OP (const T &c) { return (*this = *this OP2 c); }
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 #define INCDEC_OPERATOR(OP, DELTA) \
kono
parents:
diff changeset
752 generic_wide_int &OP () { *this += DELTA; return *this; }
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 ASSIGNMENT_OPERATOR (operator &=, bit_and)
kono
parents:
diff changeset
755 ASSIGNMENT_OPERATOR (operator |=, bit_or)
kono
parents:
diff changeset
756 ASSIGNMENT_OPERATOR (operator ^=, bit_xor)
kono
parents:
diff changeset
757 ASSIGNMENT_OPERATOR (operator +=, add)
kono
parents:
diff changeset
758 ASSIGNMENT_OPERATOR (operator -=, sub)
kono
parents:
diff changeset
759 ASSIGNMENT_OPERATOR (operator *=, mul)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
760 ASSIGNMENT_OPERATOR (operator <<=, lshift)
111
kono
parents:
diff changeset
761 SHIFT_ASSIGNMENT_OPERATOR (operator >>=, >>)
kono
parents:
diff changeset
762 INCDEC_OPERATOR (operator ++, 1)
kono
parents:
diff changeset
763 INCDEC_OPERATOR (operator --, -1)
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 #undef SHIFT_ASSIGNMENT_OPERATOR
kono
parents:
diff changeset
766 #undef ASSIGNMENT_OPERATOR
kono
parents:
diff changeset
767 #undef INCDEC_OPERATOR
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 /* Debugging functions. */
kono
parents:
diff changeset
770 void dump () const;
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 static const bool is_sign_extended
kono
parents:
diff changeset
773 = wi::int_traits <generic_wide_int <storage> >::is_sign_extended;
kono
parents:
diff changeset
774 };
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776 template <typename storage>
kono
parents:
diff changeset
777 inline generic_wide_int <storage>::generic_wide_int () {}
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 template <typename storage>
kono
parents:
diff changeset
780 template <typename T>
kono
parents:
diff changeset
781 inline generic_wide_int <storage>::generic_wide_int (const T &x)
kono
parents:
diff changeset
782 : storage (x)
kono
parents:
diff changeset
783 {
kono
parents:
diff changeset
784 }
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 template <typename storage>
kono
parents:
diff changeset
787 template <typename T>
kono
parents:
diff changeset
788 inline generic_wide_int <storage>::generic_wide_int (const T &x,
kono
parents:
diff changeset
789 unsigned int precision)
kono
parents:
diff changeset
790 : storage (x, precision)
kono
parents:
diff changeset
791 {
kono
parents:
diff changeset
792 }
kono
parents:
diff changeset
793
kono
parents:
diff changeset
794 /* Return THIS as a signed HOST_WIDE_INT, sign-extending from PRECISION.
kono
parents:
diff changeset
795 If THIS does not fit in PRECISION, the information is lost. */
kono
parents:
diff changeset
796 template <typename storage>
kono
parents:
diff changeset
797 inline HOST_WIDE_INT
kono
parents:
diff changeset
798 generic_wide_int <storage>::to_shwi (unsigned int precision) const
kono
parents:
diff changeset
799 {
kono
parents:
diff changeset
800 if (precision < HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
801 return sext_hwi (this->get_val ()[0], precision);
kono
parents:
diff changeset
802 else
kono
parents:
diff changeset
803 return this->get_val ()[0];
kono
parents:
diff changeset
804 }
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 /* Return THIS as a signed HOST_WIDE_INT, in its natural precision. */
kono
parents:
diff changeset
807 template <typename storage>
kono
parents:
diff changeset
808 inline HOST_WIDE_INT
kono
parents:
diff changeset
809 generic_wide_int <storage>::to_shwi () const
kono
parents:
diff changeset
810 {
kono
parents:
diff changeset
811 if (is_sign_extended)
kono
parents:
diff changeset
812 return this->get_val ()[0];
kono
parents:
diff changeset
813 else
kono
parents:
diff changeset
814 return to_shwi (this->get_precision ());
kono
parents:
diff changeset
815 }
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 /* Return THIS as an unsigned HOST_WIDE_INT, zero-extending from
kono
parents:
diff changeset
818 PRECISION. If THIS does not fit in PRECISION, the information
kono
parents:
diff changeset
819 is lost. */
kono
parents:
diff changeset
820 template <typename storage>
kono
parents:
diff changeset
821 inline unsigned HOST_WIDE_INT
kono
parents:
diff changeset
822 generic_wide_int <storage>::to_uhwi (unsigned int precision) const
kono
parents:
diff changeset
823 {
kono
parents:
diff changeset
824 if (precision < HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
825 return zext_hwi (this->get_val ()[0], precision);
kono
parents:
diff changeset
826 else
kono
parents:
diff changeset
827 return this->get_val ()[0];
kono
parents:
diff changeset
828 }
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 /* Return THIS as an signed HOST_WIDE_INT, in its natural precision. */
kono
parents:
diff changeset
831 template <typename storage>
kono
parents:
diff changeset
832 inline unsigned HOST_WIDE_INT
kono
parents:
diff changeset
833 generic_wide_int <storage>::to_uhwi () const
kono
parents:
diff changeset
834 {
kono
parents:
diff changeset
835 return to_uhwi (this->get_precision ());
kono
parents:
diff changeset
836 }
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 /* TODO: The compiler is half converted from using HOST_WIDE_INT to
kono
parents:
diff changeset
839 represent addresses to using offset_int to represent addresses.
kono
parents:
diff changeset
840 We use to_short_addr at the interface from new code to old,
kono
parents:
diff changeset
841 unconverted code. */
kono
parents:
diff changeset
842 template <typename storage>
kono
parents:
diff changeset
843 inline HOST_WIDE_INT
kono
parents:
diff changeset
844 generic_wide_int <storage>::to_short_addr () const
kono
parents:
diff changeset
845 {
kono
parents:
diff changeset
846 return this->get_val ()[0];
kono
parents:
diff changeset
847 }
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 /* Return the implicit value of blocks above get_len (). */
kono
parents:
diff changeset
850 template <typename storage>
kono
parents:
diff changeset
851 inline HOST_WIDE_INT
kono
parents:
diff changeset
852 generic_wide_int <storage>::sign_mask () const
kono
parents:
diff changeset
853 {
kono
parents:
diff changeset
854 unsigned int len = this->get_len ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
855 gcc_assert (len > 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
856
111
kono
parents:
diff changeset
857 unsigned HOST_WIDE_INT high = this->get_val ()[len - 1];
kono
parents:
diff changeset
858 if (!is_sign_extended)
kono
parents:
diff changeset
859 {
kono
parents:
diff changeset
860 unsigned int precision = this->get_precision ();
kono
parents:
diff changeset
861 int excess = len * HOST_BITS_PER_WIDE_INT - precision;
kono
parents:
diff changeset
862 if (excess > 0)
kono
parents:
diff changeset
863 high <<= excess;
kono
parents:
diff changeset
864 }
kono
parents:
diff changeset
865 return (HOST_WIDE_INT) (high) < 0 ? -1 : 0;
kono
parents:
diff changeset
866 }
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 /* Return the signed value of the least-significant explicitly-encoded
kono
parents:
diff changeset
869 block. */
kono
parents:
diff changeset
870 template <typename storage>
kono
parents:
diff changeset
871 inline HOST_WIDE_INT
kono
parents:
diff changeset
872 generic_wide_int <storage>::slow () const
kono
parents:
diff changeset
873 {
kono
parents:
diff changeset
874 return this->get_val ()[0];
kono
parents:
diff changeset
875 }
kono
parents:
diff changeset
876
kono
parents:
diff changeset
877 /* Return the signed value of the most-significant explicitly-encoded
kono
parents:
diff changeset
878 block. */
kono
parents:
diff changeset
879 template <typename storage>
kono
parents:
diff changeset
880 inline HOST_WIDE_INT
kono
parents:
diff changeset
881 generic_wide_int <storage>::shigh () const
kono
parents:
diff changeset
882 {
kono
parents:
diff changeset
883 return this->get_val ()[this->get_len () - 1];
kono
parents:
diff changeset
884 }
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 /* Return the unsigned value of the least-significant
kono
parents:
diff changeset
887 explicitly-encoded block. */
kono
parents:
diff changeset
888 template <typename storage>
kono
parents:
diff changeset
889 inline unsigned HOST_WIDE_INT
kono
parents:
diff changeset
890 generic_wide_int <storage>::ulow () const
kono
parents:
diff changeset
891 {
kono
parents:
diff changeset
892 return this->get_val ()[0];
kono
parents:
diff changeset
893 }
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 /* Return the unsigned value of the most-significant
kono
parents:
diff changeset
896 explicitly-encoded block. */
kono
parents:
diff changeset
897 template <typename storage>
kono
parents:
diff changeset
898 inline unsigned HOST_WIDE_INT
kono
parents:
diff changeset
899 generic_wide_int <storage>::uhigh () const
kono
parents:
diff changeset
900 {
kono
parents:
diff changeset
901 return this->get_val ()[this->get_len () - 1];
kono
parents:
diff changeset
902 }
kono
parents:
diff changeset
903
kono
parents:
diff changeset
904 /* Return block I, which might be implicitly or explicit encoded. */
kono
parents:
diff changeset
905 template <typename storage>
kono
parents:
diff changeset
906 inline HOST_WIDE_INT
kono
parents:
diff changeset
907 generic_wide_int <storage>::elt (unsigned int i) const
kono
parents:
diff changeset
908 {
kono
parents:
diff changeset
909 if (i >= this->get_len ())
kono
parents:
diff changeset
910 return sign_mask ();
kono
parents:
diff changeset
911 else
kono
parents:
diff changeset
912 return this->get_val ()[i];
kono
parents:
diff changeset
913 }
kono
parents:
diff changeset
914
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
915 /* Like elt, but sign-extend beyond the upper bit, instead of returning
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
916 the raw encoding. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
917 template <typename storage>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
918 inline HOST_WIDE_INT
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
919 generic_wide_int <storage>::sext_elt (unsigned int i) const
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
920 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
921 HOST_WIDE_INT elt_i = elt (i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
922 if (!is_sign_extended)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
923 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
924 unsigned int precision = this->get_precision ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
925 unsigned int lsb = i * HOST_BITS_PER_WIDE_INT;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
926 if (precision - lsb < HOST_BITS_PER_WIDE_INT)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
927 elt_i = sext_hwi (elt_i, precision - lsb);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
928 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
929 return elt_i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
930 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
931
111
kono
parents:
diff changeset
932 template <typename storage>
kono
parents:
diff changeset
933 template <typename T>
kono
parents:
diff changeset
934 inline generic_wide_int <storage> &
kono
parents:
diff changeset
935 generic_wide_int <storage>::operator = (const T &x)
kono
parents:
diff changeset
936 {
kono
parents:
diff changeset
937 storage::operator = (x);
kono
parents:
diff changeset
938 return *this;
kono
parents:
diff changeset
939 }
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 /* Dump the contents of the integer to stderr, for debugging. */
kono
parents:
diff changeset
942 template <typename storage>
kono
parents:
diff changeset
943 void
kono
parents:
diff changeset
944 generic_wide_int <storage>::dump () const
kono
parents:
diff changeset
945 {
kono
parents:
diff changeset
946 unsigned int len = this->get_len ();
kono
parents:
diff changeset
947 const HOST_WIDE_INT *val = this->get_val ();
kono
parents:
diff changeset
948 unsigned int precision = this->get_precision ();
kono
parents:
diff changeset
949 fprintf (stderr, "[");
kono
parents:
diff changeset
950 if (len * HOST_BITS_PER_WIDE_INT < precision)
kono
parents:
diff changeset
951 fprintf (stderr, "...,");
kono
parents:
diff changeset
952 for (unsigned int i = 0; i < len - 1; ++i)
kono
parents:
diff changeset
953 fprintf (stderr, HOST_WIDE_INT_PRINT_HEX ",", val[len - 1 - i]);
kono
parents:
diff changeset
954 fprintf (stderr, HOST_WIDE_INT_PRINT_HEX "], precision = %d\n",
kono
parents:
diff changeset
955 val[0], precision);
kono
parents:
diff changeset
956 }
kono
parents:
diff changeset
957
kono
parents:
diff changeset
958 namespace wi
kono
parents:
diff changeset
959 {
kono
parents:
diff changeset
960 template <typename storage>
kono
parents:
diff changeset
961 struct int_traits < generic_wide_int <storage> >
kono
parents:
diff changeset
962 : public wi::int_traits <storage>
kono
parents:
diff changeset
963 {
kono
parents:
diff changeset
964 static unsigned int get_precision (const generic_wide_int <storage> &);
kono
parents:
diff changeset
965 static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
966 const generic_wide_int <storage> &);
kono
parents:
diff changeset
967 };
kono
parents:
diff changeset
968 }
kono
parents:
diff changeset
969
kono
parents:
diff changeset
970 template <typename storage>
kono
parents:
diff changeset
971 inline unsigned int
kono
parents:
diff changeset
972 wi::int_traits < generic_wide_int <storage> >::
kono
parents:
diff changeset
973 get_precision (const generic_wide_int <storage> &x)
kono
parents:
diff changeset
974 {
kono
parents:
diff changeset
975 return x.get_precision ();
kono
parents:
diff changeset
976 }
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 template <typename storage>
kono
parents:
diff changeset
979 inline wi::storage_ref
kono
parents:
diff changeset
980 wi::int_traits < generic_wide_int <storage> >::
kono
parents:
diff changeset
981 decompose (HOST_WIDE_INT *, unsigned int precision,
kono
parents:
diff changeset
982 const generic_wide_int <storage> &x)
kono
parents:
diff changeset
983 {
kono
parents:
diff changeset
984 gcc_checking_assert (precision == x.get_precision ());
kono
parents:
diff changeset
985 return wi::storage_ref (x.get_val (), x.get_len (), precision);
kono
parents:
diff changeset
986 }
kono
parents:
diff changeset
987
kono
parents:
diff changeset
988 /* Provide the storage for a wide_int_ref. This acts like a read-only
kono
parents:
diff changeset
989 wide_int, with the optimization that VAL is normally a pointer to
kono
parents:
diff changeset
990 another integer's storage, so that no array copy is needed. */
kono
parents:
diff changeset
991 template <bool SE, bool HDP>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
992 class wide_int_ref_storage : public wi::storage_ref
111
kono
parents:
diff changeset
993 {
kono
parents:
diff changeset
994 private:
kono
parents:
diff changeset
995 /* Scratch space that can be used when decomposing the original integer.
kono
parents:
diff changeset
996 It must live as long as this object. */
kono
parents:
diff changeset
997 HOST_WIDE_INT scratch[2];
kono
parents:
diff changeset
998
kono
parents:
diff changeset
999 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1000 wide_int_ref_storage () {}
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1001
111
kono
parents:
diff changeset
1002 wide_int_ref_storage (const wi::storage_ref &);
kono
parents:
diff changeset
1003
kono
parents:
diff changeset
1004 template <typename T>
kono
parents:
diff changeset
1005 wide_int_ref_storage (const T &);
kono
parents:
diff changeset
1006
kono
parents:
diff changeset
1007 template <typename T>
kono
parents:
diff changeset
1008 wide_int_ref_storage (const T &, unsigned int);
kono
parents:
diff changeset
1009 };
kono
parents:
diff changeset
1010
kono
parents:
diff changeset
1011 /* Create a reference from an existing reference. */
kono
parents:
diff changeset
1012 template <bool SE, bool HDP>
kono
parents:
diff changeset
1013 inline wide_int_ref_storage <SE, HDP>::
kono
parents:
diff changeset
1014 wide_int_ref_storage (const wi::storage_ref &x)
kono
parents:
diff changeset
1015 : storage_ref (x)
kono
parents:
diff changeset
1016 {}
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 /* Create a reference to integer X in its natural precision. Note
kono
parents:
diff changeset
1019 that the natural precision is host-dependent for primitive
kono
parents:
diff changeset
1020 types. */
kono
parents:
diff changeset
1021 template <bool SE, bool HDP>
kono
parents:
diff changeset
1022 template <typename T>
kono
parents:
diff changeset
1023 inline wide_int_ref_storage <SE, HDP>::wide_int_ref_storage (const T &x)
kono
parents:
diff changeset
1024 : storage_ref (wi::int_traits <T>::decompose (scratch,
kono
parents:
diff changeset
1025 wi::get_precision (x), x))
kono
parents:
diff changeset
1026 {
kono
parents:
diff changeset
1027 }
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 /* Create a reference to integer X in precision PRECISION. */
kono
parents:
diff changeset
1030 template <bool SE, bool HDP>
kono
parents:
diff changeset
1031 template <typename T>
kono
parents:
diff changeset
1032 inline wide_int_ref_storage <SE, HDP>::
kono
parents:
diff changeset
1033 wide_int_ref_storage (const T &x, unsigned int precision)
kono
parents:
diff changeset
1034 : storage_ref (wi::int_traits <T>::decompose (scratch, precision, x))
kono
parents:
diff changeset
1035 {
kono
parents:
diff changeset
1036 }
kono
parents:
diff changeset
1037
kono
parents:
diff changeset
1038 namespace wi
kono
parents:
diff changeset
1039 {
kono
parents:
diff changeset
1040 template <bool SE, bool HDP>
kono
parents:
diff changeset
1041 struct int_traits <wide_int_ref_storage <SE, HDP> >
kono
parents:
diff changeset
1042 {
kono
parents:
diff changeset
1043 static const enum precision_type precision_type = VAR_PRECISION;
kono
parents:
diff changeset
1044 static const bool host_dependent_precision = HDP;
kono
parents:
diff changeset
1045 static const bool is_sign_extended = SE;
kono
parents:
diff changeset
1046 };
kono
parents:
diff changeset
1047 }
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 namespace wi
kono
parents:
diff changeset
1050 {
kono
parents:
diff changeset
1051 unsigned int force_to_size (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1052 unsigned int, unsigned int, unsigned int,
kono
parents:
diff changeset
1053 signop sgn);
kono
parents:
diff changeset
1054 unsigned int from_array (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1055 unsigned int, unsigned int, bool = true);
kono
parents:
diff changeset
1056 }
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 /* The storage used by wide_int. */
kono
parents:
diff changeset
1059 class GTY(()) wide_int_storage
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 private:
kono
parents:
diff changeset
1062 HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
kono
parents:
diff changeset
1063 unsigned int len;
kono
parents:
diff changeset
1064 unsigned int precision;
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 public:
kono
parents:
diff changeset
1067 wide_int_storage ();
kono
parents:
diff changeset
1068 template <typename T>
kono
parents:
diff changeset
1069 wide_int_storage (const T &);
kono
parents:
diff changeset
1070
kono
parents:
diff changeset
1071 /* The standard generic_wide_int storage methods. */
kono
parents:
diff changeset
1072 unsigned int get_precision () const;
kono
parents:
diff changeset
1073 const HOST_WIDE_INT *get_val () const;
kono
parents:
diff changeset
1074 unsigned int get_len () const;
kono
parents:
diff changeset
1075 HOST_WIDE_INT *write_val ();
kono
parents:
diff changeset
1076 void set_len (unsigned int, bool = false);
kono
parents:
diff changeset
1077
kono
parents:
diff changeset
1078 template <typename T>
kono
parents:
diff changeset
1079 wide_int_storage &operator = (const T &);
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 static wide_int from (const wide_int_ref &, unsigned int, signop);
kono
parents:
diff changeset
1082 static wide_int from_array (const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1083 unsigned int, bool = true);
kono
parents:
diff changeset
1084 static wide_int create (unsigned int);
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 /* FIXME: target-dependent, so should disappear. */
kono
parents:
diff changeset
1087 wide_int bswap () const;
kono
parents:
diff changeset
1088 };
kono
parents:
diff changeset
1089
kono
parents:
diff changeset
1090 namespace wi
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092 template <>
kono
parents:
diff changeset
1093 struct int_traits <wide_int_storage>
kono
parents:
diff changeset
1094 {
kono
parents:
diff changeset
1095 static const enum precision_type precision_type = VAR_PRECISION;
kono
parents:
diff changeset
1096 /* Guaranteed by a static assert in the wide_int_storage constructor. */
kono
parents:
diff changeset
1097 static const bool host_dependent_precision = false;
kono
parents:
diff changeset
1098 static const bool is_sign_extended = true;
kono
parents:
diff changeset
1099 template <typename T1, typename T2>
kono
parents:
diff changeset
1100 static wide_int get_binary_result (const T1 &, const T2 &);
kono
parents:
diff changeset
1101 };
kono
parents:
diff changeset
1102 }
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 inline wide_int_storage::wide_int_storage () {}
kono
parents:
diff changeset
1105
kono
parents:
diff changeset
1106 /* Initialize the storage from integer X, in its natural precision.
kono
parents:
diff changeset
1107 Note that we do not allow integers with host-dependent precision
kono
parents:
diff changeset
1108 to become wide_ints; wide_ints must always be logically independent
kono
parents:
diff changeset
1109 of the host. */
kono
parents:
diff changeset
1110 template <typename T>
kono
parents:
diff changeset
1111 inline wide_int_storage::wide_int_storage (const T &x)
kono
parents:
diff changeset
1112 {
kono
parents:
diff changeset
1113 { STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); }
kono
parents:
diff changeset
1114 { STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION); }
kono
parents:
diff changeset
1115 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1116 precision = xi.precision;
kono
parents:
diff changeset
1117 wi::copy (*this, xi);
kono
parents:
diff changeset
1118 }
kono
parents:
diff changeset
1119
kono
parents:
diff changeset
1120 template <typename T>
kono
parents:
diff changeset
1121 inline wide_int_storage&
kono
parents:
diff changeset
1122 wide_int_storage::operator = (const T &x)
kono
parents:
diff changeset
1123 {
kono
parents:
diff changeset
1124 { STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); }
kono
parents:
diff changeset
1125 { STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION); }
kono
parents:
diff changeset
1126 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1127 precision = xi.precision;
kono
parents:
diff changeset
1128 wi::copy (*this, xi);
kono
parents:
diff changeset
1129 return *this;
kono
parents:
diff changeset
1130 }
kono
parents:
diff changeset
1131
kono
parents:
diff changeset
1132 inline unsigned int
kono
parents:
diff changeset
1133 wide_int_storage::get_precision () const
kono
parents:
diff changeset
1134 {
kono
parents:
diff changeset
1135 return precision;
kono
parents:
diff changeset
1136 }
kono
parents:
diff changeset
1137
kono
parents:
diff changeset
1138 inline const HOST_WIDE_INT *
kono
parents:
diff changeset
1139 wide_int_storage::get_val () const
kono
parents:
diff changeset
1140 {
kono
parents:
diff changeset
1141 return val;
kono
parents:
diff changeset
1142 }
kono
parents:
diff changeset
1143
kono
parents:
diff changeset
1144 inline unsigned int
kono
parents:
diff changeset
1145 wide_int_storage::get_len () const
kono
parents:
diff changeset
1146 {
kono
parents:
diff changeset
1147 return len;
kono
parents:
diff changeset
1148 }
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 inline HOST_WIDE_INT *
kono
parents:
diff changeset
1151 wide_int_storage::write_val ()
kono
parents:
diff changeset
1152 {
kono
parents:
diff changeset
1153 return val;
kono
parents:
diff changeset
1154 }
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 inline void
kono
parents:
diff changeset
1157 wide_int_storage::set_len (unsigned int l, bool is_sign_extended)
kono
parents:
diff changeset
1158 {
kono
parents:
diff changeset
1159 len = l;
kono
parents:
diff changeset
1160 if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > precision)
kono
parents:
diff changeset
1161 val[len - 1] = sext_hwi (val[len - 1],
kono
parents:
diff changeset
1162 precision % HOST_BITS_PER_WIDE_INT);
kono
parents:
diff changeset
1163 }
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 /* Treat X as having signedness SGN and convert it to a PRECISION-bit
kono
parents:
diff changeset
1166 number. */
kono
parents:
diff changeset
1167 inline wide_int
kono
parents:
diff changeset
1168 wide_int_storage::from (const wide_int_ref &x, unsigned int precision,
kono
parents:
diff changeset
1169 signop sgn)
kono
parents:
diff changeset
1170 {
kono
parents:
diff changeset
1171 wide_int result = wide_int::create (precision);
kono
parents:
diff changeset
1172 result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
kono
parents:
diff changeset
1173 x.precision, precision, sgn));
kono
parents:
diff changeset
1174 return result;
kono
parents:
diff changeset
1175 }
kono
parents:
diff changeset
1176
kono
parents:
diff changeset
1177 /* Create a wide_int from the explicit block encoding given by VAL and
kono
parents:
diff changeset
1178 LEN. PRECISION is the precision of the integer. NEED_CANON_P is
kono
parents:
diff changeset
1179 true if the encoding may have redundant trailing blocks. */
kono
parents:
diff changeset
1180 inline wide_int
kono
parents:
diff changeset
1181 wide_int_storage::from_array (const HOST_WIDE_INT *val, unsigned int len,
kono
parents:
diff changeset
1182 unsigned int precision, bool need_canon_p)
kono
parents:
diff changeset
1183 {
kono
parents:
diff changeset
1184 wide_int result = wide_int::create (precision);
kono
parents:
diff changeset
1185 result.set_len (wi::from_array (result.write_val (), val, len, precision,
kono
parents:
diff changeset
1186 need_canon_p));
kono
parents:
diff changeset
1187 return result;
kono
parents:
diff changeset
1188 }
kono
parents:
diff changeset
1189
kono
parents:
diff changeset
1190 /* Return an uninitialized wide_int with precision PRECISION. */
kono
parents:
diff changeset
1191 inline wide_int
kono
parents:
diff changeset
1192 wide_int_storage::create (unsigned int precision)
kono
parents:
diff changeset
1193 {
kono
parents:
diff changeset
1194 wide_int x;
kono
parents:
diff changeset
1195 x.precision = precision;
kono
parents:
diff changeset
1196 return x;
kono
parents:
diff changeset
1197 }
kono
parents:
diff changeset
1198
kono
parents:
diff changeset
1199 template <typename T1, typename T2>
kono
parents:
diff changeset
1200 inline wide_int
kono
parents:
diff changeset
1201 wi::int_traits <wide_int_storage>::get_binary_result (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1202 {
kono
parents:
diff changeset
1203 /* This shouldn't be used for two flexible-precision inputs. */
kono
parents:
diff changeset
1204 STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
kono
parents:
diff changeset
1205 || wi::int_traits <T2>::precision_type != FLEXIBLE_PRECISION);
kono
parents:
diff changeset
1206 if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
kono
parents:
diff changeset
1207 return wide_int::create (wi::get_precision (y));
kono
parents:
diff changeset
1208 else
kono
parents:
diff changeset
1209 return wide_int::create (wi::get_precision (x));
kono
parents:
diff changeset
1210 }
kono
parents:
diff changeset
1211
kono
parents:
diff changeset
1212 /* The storage used by FIXED_WIDE_INT (N). */
kono
parents:
diff changeset
1213 template <int N>
kono
parents:
diff changeset
1214 class GTY(()) fixed_wide_int_storage
kono
parents:
diff changeset
1215 {
kono
parents:
diff changeset
1216 private:
kono
parents:
diff changeset
1217 HOST_WIDE_INT val[(N + HOST_BITS_PER_WIDE_INT + 1) / HOST_BITS_PER_WIDE_INT];
kono
parents:
diff changeset
1218 unsigned int len;
kono
parents:
diff changeset
1219
kono
parents:
diff changeset
1220 public:
kono
parents:
diff changeset
1221 fixed_wide_int_storage ();
kono
parents:
diff changeset
1222 template <typename T>
kono
parents:
diff changeset
1223 fixed_wide_int_storage (const T &);
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 /* The standard generic_wide_int storage methods. */
kono
parents:
diff changeset
1226 unsigned int get_precision () const;
kono
parents:
diff changeset
1227 const HOST_WIDE_INT *get_val () const;
kono
parents:
diff changeset
1228 unsigned int get_len () const;
kono
parents:
diff changeset
1229 HOST_WIDE_INT *write_val ();
kono
parents:
diff changeset
1230 void set_len (unsigned int, bool = false);
kono
parents:
diff changeset
1231
kono
parents:
diff changeset
1232 static FIXED_WIDE_INT (N) from (const wide_int_ref &, signop);
kono
parents:
diff changeset
1233 static FIXED_WIDE_INT (N) from_array (const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1234 bool = true);
kono
parents:
diff changeset
1235 };
kono
parents:
diff changeset
1236
kono
parents:
diff changeset
1237 namespace wi
kono
parents:
diff changeset
1238 {
kono
parents:
diff changeset
1239 template <int N>
kono
parents:
diff changeset
1240 struct int_traits < fixed_wide_int_storage <N> >
kono
parents:
diff changeset
1241 {
kono
parents:
diff changeset
1242 static const enum precision_type precision_type = CONST_PRECISION;
kono
parents:
diff changeset
1243 static const bool host_dependent_precision = false;
kono
parents:
diff changeset
1244 static const bool is_sign_extended = true;
kono
parents:
diff changeset
1245 static const unsigned int precision = N;
kono
parents:
diff changeset
1246 template <typename T1, typename T2>
kono
parents:
diff changeset
1247 static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &);
kono
parents:
diff changeset
1248 };
kono
parents:
diff changeset
1249 }
kono
parents:
diff changeset
1250
kono
parents:
diff changeset
1251 template <int N>
kono
parents:
diff changeset
1252 inline fixed_wide_int_storage <N>::fixed_wide_int_storage () {}
kono
parents:
diff changeset
1253
kono
parents:
diff changeset
1254 /* Initialize the storage from integer X, in precision N. */
kono
parents:
diff changeset
1255 template <int N>
kono
parents:
diff changeset
1256 template <typename T>
kono
parents:
diff changeset
1257 inline fixed_wide_int_storage <N>::fixed_wide_int_storage (const T &x)
kono
parents:
diff changeset
1258 {
kono
parents:
diff changeset
1259 /* Check for type compatibility. We don't want to initialize a
kono
parents:
diff changeset
1260 fixed-width integer from something like a wide_int. */
kono
parents:
diff changeset
1261 WI_BINARY_RESULT (T, FIXED_WIDE_INT (N)) *assertion ATTRIBUTE_UNUSED;
kono
parents:
diff changeset
1262 wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N));
kono
parents:
diff changeset
1263 }
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 template <int N>
kono
parents:
diff changeset
1266 inline unsigned int
kono
parents:
diff changeset
1267 fixed_wide_int_storage <N>::get_precision () const
kono
parents:
diff changeset
1268 {
kono
parents:
diff changeset
1269 return N;
kono
parents:
diff changeset
1270 }
kono
parents:
diff changeset
1271
kono
parents:
diff changeset
1272 template <int N>
kono
parents:
diff changeset
1273 inline const HOST_WIDE_INT *
kono
parents:
diff changeset
1274 fixed_wide_int_storage <N>::get_val () const
kono
parents:
diff changeset
1275 {
kono
parents:
diff changeset
1276 return val;
kono
parents:
diff changeset
1277 }
kono
parents:
diff changeset
1278
kono
parents:
diff changeset
1279 template <int N>
kono
parents:
diff changeset
1280 inline unsigned int
kono
parents:
diff changeset
1281 fixed_wide_int_storage <N>::get_len () const
kono
parents:
diff changeset
1282 {
kono
parents:
diff changeset
1283 return len;
kono
parents:
diff changeset
1284 }
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 template <int N>
kono
parents:
diff changeset
1287 inline HOST_WIDE_INT *
kono
parents:
diff changeset
1288 fixed_wide_int_storage <N>::write_val ()
kono
parents:
diff changeset
1289 {
kono
parents:
diff changeset
1290 return val;
kono
parents:
diff changeset
1291 }
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 template <int N>
kono
parents:
diff changeset
1294 inline void
kono
parents:
diff changeset
1295 fixed_wide_int_storage <N>::set_len (unsigned int l, bool)
kono
parents:
diff changeset
1296 {
kono
parents:
diff changeset
1297 len = l;
kono
parents:
diff changeset
1298 /* There are no excess bits in val[len - 1]. */
kono
parents:
diff changeset
1299 STATIC_ASSERT (N % HOST_BITS_PER_WIDE_INT == 0);
kono
parents:
diff changeset
1300 }
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 /* Treat X as having signedness SGN and convert it to an N-bit number. */
kono
parents:
diff changeset
1303 template <int N>
kono
parents:
diff changeset
1304 inline FIXED_WIDE_INT (N)
kono
parents:
diff changeset
1305 fixed_wide_int_storage <N>::from (const wide_int_ref &x, signop sgn)
kono
parents:
diff changeset
1306 {
kono
parents:
diff changeset
1307 FIXED_WIDE_INT (N) result;
kono
parents:
diff changeset
1308 result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
kono
parents:
diff changeset
1309 x.precision, N, sgn));
kono
parents:
diff changeset
1310 return result;
kono
parents:
diff changeset
1311 }
kono
parents:
diff changeset
1312
kono
parents:
diff changeset
1313 /* Create a FIXED_WIDE_INT (N) from the explicit block encoding given by
kono
parents:
diff changeset
1314 VAL and LEN. NEED_CANON_P is true if the encoding may have redundant
kono
parents:
diff changeset
1315 trailing blocks. */
kono
parents:
diff changeset
1316 template <int N>
kono
parents:
diff changeset
1317 inline FIXED_WIDE_INT (N)
kono
parents:
diff changeset
1318 fixed_wide_int_storage <N>::from_array (const HOST_WIDE_INT *val,
kono
parents:
diff changeset
1319 unsigned int len,
kono
parents:
diff changeset
1320 bool need_canon_p)
kono
parents:
diff changeset
1321 {
kono
parents:
diff changeset
1322 FIXED_WIDE_INT (N) result;
kono
parents:
diff changeset
1323 result.set_len (wi::from_array (result.write_val (), val, len,
kono
parents:
diff changeset
1324 N, need_canon_p));
kono
parents:
diff changeset
1325 return result;
kono
parents:
diff changeset
1326 }
kono
parents:
diff changeset
1327
kono
parents:
diff changeset
1328 template <int N>
kono
parents:
diff changeset
1329 template <typename T1, typename T2>
kono
parents:
diff changeset
1330 inline FIXED_WIDE_INT (N)
kono
parents:
diff changeset
1331 wi::int_traits < fixed_wide_int_storage <N> >::
kono
parents:
diff changeset
1332 get_binary_result (const T1 &, const T2 &)
kono
parents:
diff changeset
1333 {
kono
parents:
diff changeset
1334 return FIXED_WIDE_INT (N) ();
kono
parents:
diff changeset
1335 }
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 /* A reference to one element of a trailing_wide_ints structure. */
kono
parents:
diff changeset
1338 class trailing_wide_int_storage
kono
parents:
diff changeset
1339 {
kono
parents:
diff changeset
1340 private:
kono
parents:
diff changeset
1341 /* The precision of the integer, which is a fixed property of the
kono
parents:
diff changeset
1342 parent trailing_wide_ints. */
kono
parents:
diff changeset
1343 unsigned int m_precision;
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345 /* A pointer to the length field. */
kono
parents:
diff changeset
1346 unsigned char *m_len;
kono
parents:
diff changeset
1347
kono
parents:
diff changeset
1348 /* A pointer to the HWI array. There are enough elements to hold all
kono
parents:
diff changeset
1349 values of precision M_PRECISION. */
kono
parents:
diff changeset
1350 HOST_WIDE_INT *m_val;
kono
parents:
diff changeset
1351
kono
parents:
diff changeset
1352 public:
kono
parents:
diff changeset
1353 trailing_wide_int_storage (unsigned int, unsigned char *, HOST_WIDE_INT *);
kono
parents:
diff changeset
1354
kono
parents:
diff changeset
1355 /* The standard generic_wide_int storage methods. */
kono
parents:
diff changeset
1356 unsigned int get_len () const;
kono
parents:
diff changeset
1357 unsigned int get_precision () const;
kono
parents:
diff changeset
1358 const HOST_WIDE_INT *get_val () const;
kono
parents:
diff changeset
1359 HOST_WIDE_INT *write_val ();
kono
parents:
diff changeset
1360 void set_len (unsigned int, bool = false);
kono
parents:
diff changeset
1361
kono
parents:
diff changeset
1362 template <typename T>
kono
parents:
diff changeset
1363 trailing_wide_int_storage &operator = (const T &);
kono
parents:
diff changeset
1364 };
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 typedef generic_wide_int <trailing_wide_int_storage> trailing_wide_int;
kono
parents:
diff changeset
1367
kono
parents:
diff changeset
1368 /* trailing_wide_int behaves like a wide_int. */
kono
parents:
diff changeset
1369 namespace wi
kono
parents:
diff changeset
1370 {
kono
parents:
diff changeset
1371 template <>
kono
parents:
diff changeset
1372 struct int_traits <trailing_wide_int_storage>
kono
parents:
diff changeset
1373 : public int_traits <wide_int_storage> {};
kono
parents:
diff changeset
1374 }
kono
parents:
diff changeset
1375
kono
parents:
diff changeset
1376 /* An array of N wide_int-like objects that can be put at the end of
kono
parents:
diff changeset
1377 a variable-sized structure. Use extra_size to calculate how many
kono
parents:
diff changeset
1378 bytes beyond the sizeof need to be allocated. Use set_precision
kono
parents:
diff changeset
1379 to initialize the structure. */
kono
parents:
diff changeset
1380 template <int N>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1381 struct GTY((user)) trailing_wide_ints
111
kono
parents:
diff changeset
1382 {
kono
parents:
diff changeset
1383 private:
kono
parents:
diff changeset
1384 /* The shared precision of each number. */
kono
parents:
diff changeset
1385 unsigned short m_precision;
kono
parents:
diff changeset
1386
kono
parents:
diff changeset
1387 /* The shared maximum length of each number. */
kono
parents:
diff changeset
1388 unsigned char m_max_len;
kono
parents:
diff changeset
1389
kono
parents:
diff changeset
1390 /* The current length of each number. */
kono
parents:
diff changeset
1391 unsigned char m_len[N];
kono
parents:
diff changeset
1392
kono
parents:
diff changeset
1393 /* The variable-length part of the structure, which always contains
kono
parents:
diff changeset
1394 at least one HWI. Element I starts at index I * M_MAX_LEN. */
kono
parents:
diff changeset
1395 HOST_WIDE_INT m_val[1];
kono
parents:
diff changeset
1396
kono
parents:
diff changeset
1397 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1398 typedef WIDE_INT_REF_FOR (trailing_wide_int_storage) const_reference;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1399
111
kono
parents:
diff changeset
1400 void set_precision (unsigned int);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1401 unsigned int get_precision () const { return m_precision; }
111
kono
parents:
diff changeset
1402 trailing_wide_int operator [] (unsigned int);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1403 const_reference operator [] (unsigned int) const;
111
kono
parents:
diff changeset
1404 static size_t extra_size (unsigned int);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1405 size_t extra_size () const { return extra_size (m_precision); }
111
kono
parents:
diff changeset
1406 };
kono
parents:
diff changeset
1407
kono
parents:
diff changeset
1408 inline trailing_wide_int_storage::
kono
parents:
diff changeset
1409 trailing_wide_int_storage (unsigned int precision, unsigned char *len,
kono
parents:
diff changeset
1410 HOST_WIDE_INT *val)
kono
parents:
diff changeset
1411 : m_precision (precision), m_len (len), m_val (val)
kono
parents:
diff changeset
1412 {
kono
parents:
diff changeset
1413 }
kono
parents:
diff changeset
1414
kono
parents:
diff changeset
1415 inline unsigned int
kono
parents:
diff changeset
1416 trailing_wide_int_storage::get_len () const
kono
parents:
diff changeset
1417 {
kono
parents:
diff changeset
1418 return *m_len;
kono
parents:
diff changeset
1419 }
kono
parents:
diff changeset
1420
kono
parents:
diff changeset
1421 inline unsigned int
kono
parents:
diff changeset
1422 trailing_wide_int_storage::get_precision () const
kono
parents:
diff changeset
1423 {
kono
parents:
diff changeset
1424 return m_precision;
kono
parents:
diff changeset
1425 }
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 inline const HOST_WIDE_INT *
kono
parents:
diff changeset
1428 trailing_wide_int_storage::get_val () const
kono
parents:
diff changeset
1429 {
kono
parents:
diff changeset
1430 return m_val;
kono
parents:
diff changeset
1431 }
kono
parents:
diff changeset
1432
kono
parents:
diff changeset
1433 inline HOST_WIDE_INT *
kono
parents:
diff changeset
1434 trailing_wide_int_storage::write_val ()
kono
parents:
diff changeset
1435 {
kono
parents:
diff changeset
1436 return m_val;
kono
parents:
diff changeset
1437 }
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 inline void
kono
parents:
diff changeset
1440 trailing_wide_int_storage::set_len (unsigned int len, bool is_sign_extended)
kono
parents:
diff changeset
1441 {
kono
parents:
diff changeset
1442 *m_len = len;
kono
parents:
diff changeset
1443 if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > m_precision)
kono
parents:
diff changeset
1444 m_val[len - 1] = sext_hwi (m_val[len - 1],
kono
parents:
diff changeset
1445 m_precision % HOST_BITS_PER_WIDE_INT);
kono
parents:
diff changeset
1446 }
kono
parents:
diff changeset
1447
kono
parents:
diff changeset
1448 template <typename T>
kono
parents:
diff changeset
1449 inline trailing_wide_int_storage &
kono
parents:
diff changeset
1450 trailing_wide_int_storage::operator = (const T &x)
kono
parents:
diff changeset
1451 {
kono
parents:
diff changeset
1452 WIDE_INT_REF_FOR (T) xi (x, m_precision);
kono
parents:
diff changeset
1453 wi::copy (*this, xi);
kono
parents:
diff changeset
1454 return *this;
kono
parents:
diff changeset
1455 }
kono
parents:
diff changeset
1456
kono
parents:
diff changeset
1457 /* Initialize the structure and record that all elements have precision
kono
parents:
diff changeset
1458 PRECISION. */
kono
parents:
diff changeset
1459 template <int N>
kono
parents:
diff changeset
1460 inline void
kono
parents:
diff changeset
1461 trailing_wide_ints <N>::set_precision (unsigned int precision)
kono
parents:
diff changeset
1462 {
kono
parents:
diff changeset
1463 m_precision = precision;
kono
parents:
diff changeset
1464 m_max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
kono
parents:
diff changeset
1465 / HOST_BITS_PER_WIDE_INT);
kono
parents:
diff changeset
1466 }
kono
parents:
diff changeset
1467
kono
parents:
diff changeset
1468 /* Return a reference to element INDEX. */
kono
parents:
diff changeset
1469 template <int N>
kono
parents:
diff changeset
1470 inline trailing_wide_int
kono
parents:
diff changeset
1471 trailing_wide_ints <N>::operator [] (unsigned int index)
kono
parents:
diff changeset
1472 {
kono
parents:
diff changeset
1473 return trailing_wide_int_storage (m_precision, &m_len[index],
kono
parents:
diff changeset
1474 &m_val[index * m_max_len]);
kono
parents:
diff changeset
1475 }
kono
parents:
diff changeset
1476
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1477 template <int N>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1478 inline typename trailing_wide_ints <N>::const_reference
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1479 trailing_wide_ints <N>::operator [] (unsigned int index) const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1480 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1481 return wi::storage_ref (&m_val[index * m_max_len],
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1482 m_len[index], m_precision);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1483 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1484
111
kono
parents:
diff changeset
1485 /* Return how many extra bytes need to be added to the end of the structure
kono
parents:
diff changeset
1486 in order to handle N wide_ints of precision PRECISION. */
kono
parents:
diff changeset
1487 template <int N>
kono
parents:
diff changeset
1488 inline size_t
kono
parents:
diff changeset
1489 trailing_wide_ints <N>::extra_size (unsigned int precision)
kono
parents:
diff changeset
1490 {
kono
parents:
diff changeset
1491 unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
kono
parents:
diff changeset
1492 / HOST_BITS_PER_WIDE_INT);
kono
parents:
diff changeset
1493 return (N * max_len - 1) * sizeof (HOST_WIDE_INT);
kono
parents:
diff changeset
1494 }
kono
parents:
diff changeset
1495
kono
parents:
diff changeset
1496 /* This macro is used in structures that end with a trailing_wide_ints field
kono
parents:
diff changeset
1497 called FIELD. It declares get_NAME() and set_NAME() methods to access
kono
parents:
diff changeset
1498 element I of FIELD. */
kono
parents:
diff changeset
1499 #define TRAILING_WIDE_INT_ACCESSOR(NAME, FIELD, I) \
kono
parents:
diff changeset
1500 trailing_wide_int get_##NAME () { return FIELD[I]; } \
kono
parents:
diff changeset
1501 template <typename T> void set_##NAME (const T &x) { FIELD[I] = x; }
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 namespace wi
kono
parents:
diff changeset
1504 {
kono
parents:
diff changeset
1505 /* Implementation of int_traits for primitive integer types like "int". */
kono
parents:
diff changeset
1506 template <typename T, bool signed_p>
kono
parents:
diff changeset
1507 struct primitive_int_traits
kono
parents:
diff changeset
1508 {
kono
parents:
diff changeset
1509 static const enum precision_type precision_type = FLEXIBLE_PRECISION;
kono
parents:
diff changeset
1510 static const bool host_dependent_precision = true;
kono
parents:
diff changeset
1511 static const bool is_sign_extended = true;
kono
parents:
diff changeset
1512 static unsigned int get_precision (T);
kono
parents:
diff changeset
1513 static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, T);
kono
parents:
diff changeset
1514 };
kono
parents:
diff changeset
1515 }
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 template <typename T, bool signed_p>
kono
parents:
diff changeset
1518 inline unsigned int
kono
parents:
diff changeset
1519 wi::primitive_int_traits <T, signed_p>::get_precision (T)
kono
parents:
diff changeset
1520 {
kono
parents:
diff changeset
1521 return sizeof (T) * CHAR_BIT;
kono
parents:
diff changeset
1522 }
kono
parents:
diff changeset
1523
kono
parents:
diff changeset
1524 template <typename T, bool signed_p>
kono
parents:
diff changeset
1525 inline wi::storage_ref
kono
parents:
diff changeset
1526 wi::primitive_int_traits <T, signed_p>::decompose (HOST_WIDE_INT *scratch,
kono
parents:
diff changeset
1527 unsigned int precision, T x)
kono
parents:
diff changeset
1528 {
kono
parents:
diff changeset
1529 scratch[0] = x;
kono
parents:
diff changeset
1530 if (signed_p || scratch[0] >= 0 || precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
1531 return wi::storage_ref (scratch, 1, precision);
kono
parents:
diff changeset
1532 scratch[1] = 0;
kono
parents:
diff changeset
1533 return wi::storage_ref (scratch, 2, precision);
kono
parents:
diff changeset
1534 }
kono
parents:
diff changeset
1535
kono
parents:
diff changeset
1536 /* Allow primitive C types to be used in wi:: routines. */
kono
parents:
diff changeset
1537 namespace wi
kono
parents:
diff changeset
1538 {
kono
parents:
diff changeset
1539 template <>
kono
parents:
diff changeset
1540 struct int_traits <unsigned char>
kono
parents:
diff changeset
1541 : public primitive_int_traits <unsigned char, false> {};
kono
parents:
diff changeset
1542
kono
parents:
diff changeset
1543 template <>
kono
parents:
diff changeset
1544 struct int_traits <unsigned short>
kono
parents:
diff changeset
1545 : public primitive_int_traits <unsigned short, false> {};
kono
parents:
diff changeset
1546
kono
parents:
diff changeset
1547 template <>
kono
parents:
diff changeset
1548 struct int_traits <int>
kono
parents:
diff changeset
1549 : public primitive_int_traits <int, true> {};
kono
parents:
diff changeset
1550
kono
parents:
diff changeset
1551 template <>
kono
parents:
diff changeset
1552 struct int_traits <unsigned int>
kono
parents:
diff changeset
1553 : public primitive_int_traits <unsigned int, false> {};
kono
parents:
diff changeset
1554
kono
parents:
diff changeset
1555 template <>
kono
parents:
diff changeset
1556 struct int_traits <long>
kono
parents:
diff changeset
1557 : public primitive_int_traits <long, true> {};
kono
parents:
diff changeset
1558
kono
parents:
diff changeset
1559 template <>
kono
parents:
diff changeset
1560 struct int_traits <unsigned long>
kono
parents:
diff changeset
1561 : public primitive_int_traits <unsigned long, false> {};
kono
parents:
diff changeset
1562
kono
parents:
diff changeset
1563 #if defined HAVE_LONG_LONG
kono
parents:
diff changeset
1564 template <>
kono
parents:
diff changeset
1565 struct int_traits <long long>
kono
parents:
diff changeset
1566 : public primitive_int_traits <long long, true> {};
kono
parents:
diff changeset
1567
kono
parents:
diff changeset
1568 template <>
kono
parents:
diff changeset
1569 struct int_traits <unsigned long long>
kono
parents:
diff changeset
1570 : public primitive_int_traits <unsigned long long, false> {};
kono
parents:
diff changeset
1571 #endif
kono
parents:
diff changeset
1572 }
kono
parents:
diff changeset
1573
kono
parents:
diff changeset
1574 namespace wi
kono
parents:
diff changeset
1575 {
kono
parents:
diff changeset
1576 /* Stores HWI-sized integer VAL, treating it as having signedness SGN
kono
parents:
diff changeset
1577 and precision PRECISION. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1578 class hwi_with_prec
111
kono
parents:
diff changeset
1579 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1580 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1581 hwi_with_prec () {}
111
kono
parents:
diff changeset
1582 hwi_with_prec (HOST_WIDE_INT, unsigned int, signop);
kono
parents:
diff changeset
1583 HOST_WIDE_INT val;
kono
parents:
diff changeset
1584 unsigned int precision;
kono
parents:
diff changeset
1585 signop sgn;
kono
parents:
diff changeset
1586 };
kono
parents:
diff changeset
1587
kono
parents:
diff changeset
1588 hwi_with_prec shwi (HOST_WIDE_INT, unsigned int);
kono
parents:
diff changeset
1589 hwi_with_prec uhwi (unsigned HOST_WIDE_INT, unsigned int);
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 hwi_with_prec minus_one (unsigned int);
kono
parents:
diff changeset
1592 hwi_with_prec zero (unsigned int);
kono
parents:
diff changeset
1593 hwi_with_prec one (unsigned int);
kono
parents:
diff changeset
1594 hwi_with_prec two (unsigned int);
kono
parents:
diff changeset
1595 }
kono
parents:
diff changeset
1596
kono
parents:
diff changeset
1597 inline wi::hwi_with_prec::hwi_with_prec (HOST_WIDE_INT v, unsigned int p,
kono
parents:
diff changeset
1598 signop s)
kono
parents:
diff changeset
1599 : precision (p), sgn (s)
kono
parents:
diff changeset
1600 {
kono
parents:
diff changeset
1601 if (precision < HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
1602 val = sext_hwi (v, precision);
kono
parents:
diff changeset
1603 else
kono
parents:
diff changeset
1604 val = v;
kono
parents:
diff changeset
1605 }
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 /* Return a signed integer that has value VAL and precision PRECISION. */
kono
parents:
diff changeset
1608 inline wi::hwi_with_prec
kono
parents:
diff changeset
1609 wi::shwi (HOST_WIDE_INT val, unsigned int precision)
kono
parents:
diff changeset
1610 {
kono
parents:
diff changeset
1611 return hwi_with_prec (val, precision, SIGNED);
kono
parents:
diff changeset
1612 }
kono
parents:
diff changeset
1613
kono
parents:
diff changeset
1614 /* Return an unsigned integer that has value VAL and precision PRECISION. */
kono
parents:
diff changeset
1615 inline wi::hwi_with_prec
kono
parents:
diff changeset
1616 wi::uhwi (unsigned HOST_WIDE_INT val, unsigned int precision)
kono
parents:
diff changeset
1617 {
kono
parents:
diff changeset
1618 return hwi_with_prec (val, precision, UNSIGNED);
kono
parents:
diff changeset
1619 }
kono
parents:
diff changeset
1620
kono
parents:
diff changeset
1621 /* Return a wide int of -1 with precision PRECISION. */
kono
parents:
diff changeset
1622 inline wi::hwi_with_prec
kono
parents:
diff changeset
1623 wi::minus_one (unsigned int precision)
kono
parents:
diff changeset
1624 {
kono
parents:
diff changeset
1625 return wi::shwi (-1, precision);
kono
parents:
diff changeset
1626 }
kono
parents:
diff changeset
1627
kono
parents:
diff changeset
1628 /* Return a wide int of 0 with precision PRECISION. */
kono
parents:
diff changeset
1629 inline wi::hwi_with_prec
kono
parents:
diff changeset
1630 wi::zero (unsigned int precision)
kono
parents:
diff changeset
1631 {
kono
parents:
diff changeset
1632 return wi::shwi (0, precision);
kono
parents:
diff changeset
1633 }
kono
parents:
diff changeset
1634
kono
parents:
diff changeset
1635 /* Return a wide int of 1 with precision PRECISION. */
kono
parents:
diff changeset
1636 inline wi::hwi_with_prec
kono
parents:
diff changeset
1637 wi::one (unsigned int precision)
kono
parents:
diff changeset
1638 {
kono
parents:
diff changeset
1639 return wi::shwi (1, precision);
kono
parents:
diff changeset
1640 }
kono
parents:
diff changeset
1641
kono
parents:
diff changeset
1642 /* Return a wide int of 2 with precision PRECISION. */
kono
parents:
diff changeset
1643 inline wi::hwi_with_prec
kono
parents:
diff changeset
1644 wi::two (unsigned int precision)
kono
parents:
diff changeset
1645 {
kono
parents:
diff changeset
1646 return wi::shwi (2, precision);
kono
parents:
diff changeset
1647 }
kono
parents:
diff changeset
1648
kono
parents:
diff changeset
1649 namespace wi
kono
parents:
diff changeset
1650 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1651 /* ints_for<T>::zero (X) returns a zero that, when asssigned to a T,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1652 gives that T the same precision as X. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1653 template<typename T, precision_type = int_traits<T>::precision_type>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 struct ints_for
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1655 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1656 static int zero (const T &) { return 0; }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1657 };
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1658
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1659 template<typename T>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1660 struct ints_for<T, VAR_PRECISION>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1661 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1662 static hwi_with_prec zero (const T &);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1663 };
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1664 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1665
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1666 template<typename T>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1667 inline wi::hwi_with_prec
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1668 wi::ints_for<T, wi::VAR_PRECISION>::zero (const T &x)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1669 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1670 return wi::zero (wi::get_precision (x));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1671 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1672
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1673 namespace wi
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1674 {
111
kono
parents:
diff changeset
1675 template <>
kono
parents:
diff changeset
1676 struct int_traits <wi::hwi_with_prec>
kono
parents:
diff changeset
1677 {
kono
parents:
diff changeset
1678 static const enum precision_type precision_type = VAR_PRECISION;
kono
parents:
diff changeset
1679 /* hwi_with_prec has an explicitly-given precision, rather than the
kono
parents:
diff changeset
1680 precision of HOST_WIDE_INT. */
kono
parents:
diff changeset
1681 static const bool host_dependent_precision = false;
kono
parents:
diff changeset
1682 static const bool is_sign_extended = true;
kono
parents:
diff changeset
1683 static unsigned int get_precision (const wi::hwi_with_prec &);
kono
parents:
diff changeset
1684 static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1685 const wi::hwi_with_prec &);
kono
parents:
diff changeset
1686 };
kono
parents:
diff changeset
1687 }
kono
parents:
diff changeset
1688
kono
parents:
diff changeset
1689 inline unsigned int
kono
parents:
diff changeset
1690 wi::int_traits <wi::hwi_with_prec>::get_precision (const wi::hwi_with_prec &x)
kono
parents:
diff changeset
1691 {
kono
parents:
diff changeset
1692 return x.precision;
kono
parents:
diff changeset
1693 }
kono
parents:
diff changeset
1694
kono
parents:
diff changeset
1695 inline wi::storage_ref
kono
parents:
diff changeset
1696 wi::int_traits <wi::hwi_with_prec>::
kono
parents:
diff changeset
1697 decompose (HOST_WIDE_INT *scratch, unsigned int precision,
kono
parents:
diff changeset
1698 const wi::hwi_with_prec &x)
kono
parents:
diff changeset
1699 {
kono
parents:
diff changeset
1700 gcc_checking_assert (precision == x.precision);
kono
parents:
diff changeset
1701 scratch[0] = x.val;
kono
parents:
diff changeset
1702 if (x.sgn == SIGNED || x.val >= 0 || precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
1703 return wi::storage_ref (scratch, 1, precision);
kono
parents:
diff changeset
1704 scratch[1] = 0;
kono
parents:
diff changeset
1705 return wi::storage_ref (scratch, 2, precision);
kono
parents:
diff changeset
1706 }
kono
parents:
diff changeset
1707
kono
parents:
diff changeset
1708 /* Private functions for handling large cases out of line. They take
kono
parents:
diff changeset
1709 individual length and array parameters because that is cheaper for
kono
parents:
diff changeset
1710 the inline caller than constructing an object on the stack and
kono
parents:
diff changeset
1711 passing a reference to it. (Although many callers use wide_int_refs,
kono
parents:
diff changeset
1712 we generally want those to be removed by SRA.) */
kono
parents:
diff changeset
1713 namespace wi
kono
parents:
diff changeset
1714 {
kono
parents:
diff changeset
1715 bool eq_p_large (const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1716 const HOST_WIDE_INT *, unsigned int, unsigned int);
kono
parents:
diff changeset
1717 bool lts_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
kono
parents:
diff changeset
1718 const HOST_WIDE_INT *, unsigned int);
kono
parents:
diff changeset
1719 bool ltu_p_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
kono
parents:
diff changeset
1720 const HOST_WIDE_INT *, unsigned int);
kono
parents:
diff changeset
1721 int cmps_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
kono
parents:
diff changeset
1722 const HOST_WIDE_INT *, unsigned int);
kono
parents:
diff changeset
1723 int cmpu_large (const HOST_WIDE_INT *, unsigned int, unsigned int,
kono
parents:
diff changeset
1724 const HOST_WIDE_INT *, unsigned int);
kono
parents:
diff changeset
1725 unsigned int sext_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1726 unsigned int,
kono
parents:
diff changeset
1727 unsigned int, unsigned int);
kono
parents:
diff changeset
1728 unsigned int zext_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1729 unsigned int,
kono
parents:
diff changeset
1730 unsigned int, unsigned int);
kono
parents:
diff changeset
1731 unsigned int set_bit_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1732 unsigned int, unsigned int, unsigned int);
kono
parents:
diff changeset
1733 unsigned int lshift_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1734 unsigned int, unsigned int, unsigned int);
kono
parents:
diff changeset
1735 unsigned int lrshift_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1736 unsigned int, unsigned int, unsigned int,
kono
parents:
diff changeset
1737 unsigned int);
kono
parents:
diff changeset
1738 unsigned int arshift_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1739 unsigned int, unsigned int, unsigned int,
kono
parents:
diff changeset
1740 unsigned int);
kono
parents:
diff changeset
1741 unsigned int and_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1742 const HOST_WIDE_INT *, unsigned int, unsigned int);
kono
parents:
diff changeset
1743 unsigned int and_not_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1744 unsigned int, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1745 unsigned int, unsigned int);
kono
parents:
diff changeset
1746 unsigned int or_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1747 const HOST_WIDE_INT *, unsigned int, unsigned int);
kono
parents:
diff changeset
1748 unsigned int or_not_large (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1749 unsigned int, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1750 unsigned int, unsigned int);
kono
parents:
diff changeset
1751 unsigned int xor_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1752 const HOST_WIDE_INT *, unsigned int, unsigned int);
kono
parents:
diff changeset
1753 unsigned int add_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1754 const HOST_WIDE_INT *, unsigned int, unsigned int,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1755 signop, overflow_type *);
111
kono
parents:
diff changeset
1756 unsigned int sub_large (HOST_WIDE_INT *, const HOST_WIDE_INT *, unsigned int,
kono
parents:
diff changeset
1757 const HOST_WIDE_INT *, unsigned int, unsigned int,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1758 signop, overflow_type *);
111
kono
parents:
diff changeset
1759 unsigned int mul_internal (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1760 unsigned int, const HOST_WIDE_INT *,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1761 unsigned int, unsigned int, signop,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1762 overflow_type *, bool);
111
kono
parents:
diff changeset
1763 unsigned int divmod_internal (HOST_WIDE_INT *, unsigned int *,
kono
parents:
diff changeset
1764 HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
1765 unsigned int, unsigned int,
kono
parents:
diff changeset
1766 const HOST_WIDE_INT *,
kono
parents:
diff changeset
1767 unsigned int, unsigned int,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1768 signop, overflow_type *);
111
kono
parents:
diff changeset
1769 }
kono
parents:
diff changeset
1770
kono
parents:
diff changeset
1771 /* Return the number of bits that integer X can hold. */
kono
parents:
diff changeset
1772 template <typename T>
kono
parents:
diff changeset
1773 inline unsigned int
kono
parents:
diff changeset
1774 wi::get_precision (const T &x)
kono
parents:
diff changeset
1775 {
kono
parents:
diff changeset
1776 return wi::int_traits <T>::get_precision (x);
kono
parents:
diff changeset
1777 }
kono
parents:
diff changeset
1778
kono
parents:
diff changeset
1779 /* Return the number of bits that the result of a binary operation can
kono
parents:
diff changeset
1780 hold when the input operands are X and Y. */
kono
parents:
diff changeset
1781 template <typename T1, typename T2>
kono
parents:
diff changeset
1782 inline unsigned int
kono
parents:
diff changeset
1783 wi::get_binary_precision (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1784 {
kono
parents:
diff changeset
1785 return get_precision (wi::int_traits <WI_BINARY_RESULT (T1, T2)>::
kono
parents:
diff changeset
1786 get_binary_result (x, y));
kono
parents:
diff changeset
1787 }
kono
parents:
diff changeset
1788
kono
parents:
diff changeset
1789 /* Copy the contents of Y to X, but keeping X's current precision. */
kono
parents:
diff changeset
1790 template <typename T1, typename T2>
kono
parents:
diff changeset
1791 inline void
kono
parents:
diff changeset
1792 wi::copy (T1 &x, const T2 &y)
kono
parents:
diff changeset
1793 {
kono
parents:
diff changeset
1794 HOST_WIDE_INT *xval = x.write_val ();
kono
parents:
diff changeset
1795 const HOST_WIDE_INT *yval = y.get_val ();
kono
parents:
diff changeset
1796 unsigned int len = y.get_len ();
kono
parents:
diff changeset
1797 unsigned int i = 0;
kono
parents:
diff changeset
1798 do
kono
parents:
diff changeset
1799 xval[i] = yval[i];
kono
parents:
diff changeset
1800 while (++i < len);
kono
parents:
diff changeset
1801 x.set_len (len, y.is_sign_extended);
kono
parents:
diff changeset
1802 }
kono
parents:
diff changeset
1803
kono
parents:
diff changeset
1804 /* Return true if X fits in a HOST_WIDE_INT with no loss of precision. */
kono
parents:
diff changeset
1805 template <typename T>
kono
parents:
diff changeset
1806 inline bool
kono
parents:
diff changeset
1807 wi::fits_shwi_p (const T &x)
kono
parents:
diff changeset
1808 {
kono
parents:
diff changeset
1809 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1810 return xi.len == 1;
kono
parents:
diff changeset
1811 }
kono
parents:
diff changeset
1812
kono
parents:
diff changeset
1813 /* Return true if X fits in an unsigned HOST_WIDE_INT with no loss of
kono
parents:
diff changeset
1814 precision. */
kono
parents:
diff changeset
1815 template <typename T>
kono
parents:
diff changeset
1816 inline bool
kono
parents:
diff changeset
1817 wi::fits_uhwi_p (const T &x)
kono
parents:
diff changeset
1818 {
kono
parents:
diff changeset
1819 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1820 if (xi.precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
1821 return true;
kono
parents:
diff changeset
1822 if (xi.len == 1)
kono
parents:
diff changeset
1823 return xi.slow () >= 0;
kono
parents:
diff changeset
1824 return xi.len == 2 && xi.uhigh () == 0;
kono
parents:
diff changeset
1825 }
kono
parents:
diff changeset
1826
kono
parents:
diff changeset
1827 /* Return true if X is negative based on the interpretation of SGN.
kono
parents:
diff changeset
1828 For UNSIGNED, this is always false. */
kono
parents:
diff changeset
1829 template <typename T>
kono
parents:
diff changeset
1830 inline bool
kono
parents:
diff changeset
1831 wi::neg_p (const T &x, signop sgn)
kono
parents:
diff changeset
1832 {
kono
parents:
diff changeset
1833 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1834 if (sgn == UNSIGNED)
kono
parents:
diff changeset
1835 return false;
kono
parents:
diff changeset
1836 return xi.sign_mask () < 0;
kono
parents:
diff changeset
1837 }
kono
parents:
diff changeset
1838
kono
parents:
diff changeset
1839 /* Return -1 if the top bit of X is set and 0 if the top bit is clear. */
kono
parents:
diff changeset
1840 template <typename T>
kono
parents:
diff changeset
1841 inline HOST_WIDE_INT
kono
parents:
diff changeset
1842 wi::sign_mask (const T &x)
kono
parents:
diff changeset
1843 {
kono
parents:
diff changeset
1844 WIDE_INT_REF_FOR (T) xi (x);
kono
parents:
diff changeset
1845 return xi.sign_mask ();
kono
parents:
diff changeset
1846 }
kono
parents:
diff changeset
1847
kono
parents:
diff changeset
1848 /* Return true if X == Y. X and Y must be binary-compatible. */
kono
parents:
diff changeset
1849 template <typename T1, typename T2>
kono
parents:
diff changeset
1850 inline bool
kono
parents:
diff changeset
1851 wi::eq_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1852 {
kono
parents:
diff changeset
1853 unsigned int precision = get_binary_precision (x, y);
kono
parents:
diff changeset
1854 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
1855 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
1856 if (xi.is_sign_extended && yi.is_sign_extended)
kono
parents:
diff changeset
1857 {
kono
parents:
diff changeset
1858 /* This case reduces to array equality. */
kono
parents:
diff changeset
1859 if (xi.len != yi.len)
kono
parents:
diff changeset
1860 return false;
kono
parents:
diff changeset
1861 unsigned int i = 0;
kono
parents:
diff changeset
1862 do
kono
parents:
diff changeset
1863 if (xi.val[i] != yi.val[i])
kono
parents:
diff changeset
1864 return false;
kono
parents:
diff changeset
1865 while (++i != xi.len);
kono
parents:
diff changeset
1866 return true;
kono
parents:
diff changeset
1867 }
kono
parents:
diff changeset
1868 if (__builtin_expect (yi.len == 1, true))
kono
parents:
diff changeset
1869 {
kono
parents:
diff changeset
1870 /* XI is only equal to YI if it too has a single HWI. */
kono
parents:
diff changeset
1871 if (xi.len != 1)
kono
parents:
diff changeset
1872 return false;
kono
parents:
diff changeset
1873 /* Excess bits in xi.val[0] will be signs or zeros, so comparisons
kono
parents:
diff changeset
1874 with 0 are simple. */
kono
parents:
diff changeset
1875 if (STATIC_CONSTANT_P (yi.val[0] == 0))
kono
parents:
diff changeset
1876 return xi.val[0] == 0;
kono
parents:
diff changeset
1877 /* Otherwise flush out any excess bits first. */
kono
parents:
diff changeset
1878 unsigned HOST_WIDE_INT diff = xi.val[0] ^ yi.val[0];
kono
parents:
diff changeset
1879 int excess = HOST_BITS_PER_WIDE_INT - precision;
kono
parents:
diff changeset
1880 if (excess > 0)
kono
parents:
diff changeset
1881 diff <<= excess;
kono
parents:
diff changeset
1882 return diff == 0;
kono
parents:
diff changeset
1883 }
kono
parents:
diff changeset
1884 return eq_p_large (xi.val, xi.len, yi.val, yi.len, precision);
kono
parents:
diff changeset
1885 }
kono
parents:
diff changeset
1886
kono
parents:
diff changeset
1887 /* Return true if X != Y. X and Y must be binary-compatible. */
kono
parents:
diff changeset
1888 template <typename T1, typename T2>
kono
parents:
diff changeset
1889 inline bool
kono
parents:
diff changeset
1890 wi::ne_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1891 {
kono
parents:
diff changeset
1892 return !eq_p (x, y);
kono
parents:
diff changeset
1893 }
kono
parents:
diff changeset
1894
kono
parents:
diff changeset
1895 /* Return true if X < Y when both are treated as signed values. */
kono
parents:
diff changeset
1896 template <typename T1, typename T2>
kono
parents:
diff changeset
1897 inline bool
kono
parents:
diff changeset
1898 wi::lts_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1899 {
kono
parents:
diff changeset
1900 unsigned int precision = get_binary_precision (x, y);
kono
parents:
diff changeset
1901 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
1902 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
1903 /* We optimize x < y, where y is 64 or fewer bits. */
kono
parents:
diff changeset
1904 if (wi::fits_shwi_p (yi))
kono
parents:
diff changeset
1905 {
kono
parents:
diff changeset
1906 /* Make lts_p (x, 0) as efficient as wi::neg_p (x). */
kono
parents:
diff changeset
1907 if (STATIC_CONSTANT_P (yi.val[0] == 0))
kono
parents:
diff changeset
1908 return neg_p (xi);
kono
parents:
diff changeset
1909 /* If x fits directly into a shwi, we can compare directly. */
kono
parents:
diff changeset
1910 if (wi::fits_shwi_p (xi))
kono
parents:
diff changeset
1911 return xi.to_shwi () < yi.to_shwi ();
kono
parents:
diff changeset
1912 /* If x doesn't fit and is negative, then it must be more
kono
parents:
diff changeset
1913 negative than any value in y, and hence smaller than y. */
kono
parents:
diff changeset
1914 if (neg_p (xi))
kono
parents:
diff changeset
1915 return true;
kono
parents:
diff changeset
1916 /* If x is positive, then it must be larger than any value in y,
kono
parents:
diff changeset
1917 and hence greater than y. */
kono
parents:
diff changeset
1918 return false;
kono
parents:
diff changeset
1919 }
kono
parents:
diff changeset
1920 /* Optimize the opposite case, if it can be detected at compile time. */
kono
parents:
diff changeset
1921 if (STATIC_CONSTANT_P (xi.len == 1))
kono
parents:
diff changeset
1922 /* If YI is negative it is lower than the least HWI.
kono
parents:
diff changeset
1923 If YI is positive it is greater than the greatest HWI. */
kono
parents:
diff changeset
1924 return !neg_p (yi);
kono
parents:
diff changeset
1925 return lts_p_large (xi.val, xi.len, precision, yi.val, yi.len);
kono
parents:
diff changeset
1926 }
kono
parents:
diff changeset
1927
kono
parents:
diff changeset
1928 /* Return true if X < Y when both are treated as unsigned values. */
kono
parents:
diff changeset
1929 template <typename T1, typename T2>
kono
parents:
diff changeset
1930 inline bool
kono
parents:
diff changeset
1931 wi::ltu_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1932 {
kono
parents:
diff changeset
1933 unsigned int precision = get_binary_precision (x, y);
kono
parents:
diff changeset
1934 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
1935 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
1936 /* Optimize comparisons with constants. */
kono
parents:
diff changeset
1937 if (STATIC_CONSTANT_P (yi.len == 1 && yi.val[0] >= 0))
kono
parents:
diff changeset
1938 return xi.len == 1 && xi.to_uhwi () < (unsigned HOST_WIDE_INT) yi.val[0];
kono
parents:
diff changeset
1939 if (STATIC_CONSTANT_P (xi.len == 1 && xi.val[0] >= 0))
kono
parents:
diff changeset
1940 return yi.len != 1 || yi.to_uhwi () > (unsigned HOST_WIDE_INT) xi.val[0];
kono
parents:
diff changeset
1941 /* Optimize the case of two HWIs. The HWIs are implicitly sign-extended
kono
parents:
diff changeset
1942 for precisions greater than HOST_BITS_WIDE_INT, but sign-extending both
kono
parents:
diff changeset
1943 values does not change the result. */
kono
parents:
diff changeset
1944 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
1945 {
kono
parents:
diff changeset
1946 unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
kono
parents:
diff changeset
1947 unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
kono
parents:
diff changeset
1948 return xl < yl;
kono
parents:
diff changeset
1949 }
kono
parents:
diff changeset
1950 return ltu_p_large (xi.val, xi.len, precision, yi.val, yi.len);
kono
parents:
diff changeset
1951 }
kono
parents:
diff changeset
1952
kono
parents:
diff changeset
1953 /* Return true if X < Y. Signedness of X and Y is indicated by SGN. */
kono
parents:
diff changeset
1954 template <typename T1, typename T2>
kono
parents:
diff changeset
1955 inline bool
kono
parents:
diff changeset
1956 wi::lt_p (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
1957 {
kono
parents:
diff changeset
1958 if (sgn == SIGNED)
kono
parents:
diff changeset
1959 return lts_p (x, y);
kono
parents:
diff changeset
1960 else
kono
parents:
diff changeset
1961 return ltu_p (x, y);
kono
parents:
diff changeset
1962 }
kono
parents:
diff changeset
1963
kono
parents:
diff changeset
1964 /* Return true if X <= Y when both are treated as signed values. */
kono
parents:
diff changeset
1965 template <typename T1, typename T2>
kono
parents:
diff changeset
1966 inline bool
kono
parents:
diff changeset
1967 wi::les_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1968 {
kono
parents:
diff changeset
1969 return !lts_p (y, x);
kono
parents:
diff changeset
1970 }
kono
parents:
diff changeset
1971
kono
parents:
diff changeset
1972 /* Return true if X <= Y when both are treated as unsigned values. */
kono
parents:
diff changeset
1973 template <typename T1, typename T2>
kono
parents:
diff changeset
1974 inline bool
kono
parents:
diff changeset
1975 wi::leu_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1976 {
kono
parents:
diff changeset
1977 return !ltu_p (y, x);
kono
parents:
diff changeset
1978 }
kono
parents:
diff changeset
1979
kono
parents:
diff changeset
1980 /* Return true if X <= Y. Signedness of X and Y is indicated by SGN. */
kono
parents:
diff changeset
1981 template <typename T1, typename T2>
kono
parents:
diff changeset
1982 inline bool
kono
parents:
diff changeset
1983 wi::le_p (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
1984 {
kono
parents:
diff changeset
1985 if (sgn == SIGNED)
kono
parents:
diff changeset
1986 return les_p (x, y);
kono
parents:
diff changeset
1987 else
kono
parents:
diff changeset
1988 return leu_p (x, y);
kono
parents:
diff changeset
1989 }
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 /* Return true if X > Y when both are treated as signed values. */
kono
parents:
diff changeset
1992 template <typename T1, typename T2>
kono
parents:
diff changeset
1993 inline bool
kono
parents:
diff changeset
1994 wi::gts_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
1995 {
kono
parents:
diff changeset
1996 return lts_p (y, x);
kono
parents:
diff changeset
1997 }
kono
parents:
diff changeset
1998
kono
parents:
diff changeset
1999 /* Return true if X > Y when both are treated as unsigned values. */
kono
parents:
diff changeset
2000 template <typename T1, typename T2>
kono
parents:
diff changeset
2001 inline bool
kono
parents:
diff changeset
2002 wi::gtu_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2003 {
kono
parents:
diff changeset
2004 return ltu_p (y, x);
kono
parents:
diff changeset
2005 }
kono
parents:
diff changeset
2006
kono
parents:
diff changeset
2007 /* Return true if X > Y. Signedness of X and Y is indicated by SGN. */
kono
parents:
diff changeset
2008 template <typename T1, typename T2>
kono
parents:
diff changeset
2009 inline bool
kono
parents:
diff changeset
2010 wi::gt_p (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2011 {
kono
parents:
diff changeset
2012 if (sgn == SIGNED)
kono
parents:
diff changeset
2013 return gts_p (x, y);
kono
parents:
diff changeset
2014 else
kono
parents:
diff changeset
2015 return gtu_p (x, y);
kono
parents:
diff changeset
2016 }
kono
parents:
diff changeset
2017
kono
parents:
diff changeset
2018 /* Return true if X >= Y when both are treated as signed values. */
kono
parents:
diff changeset
2019 template <typename T1, typename T2>
kono
parents:
diff changeset
2020 inline bool
kono
parents:
diff changeset
2021 wi::ges_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2022 {
kono
parents:
diff changeset
2023 return !lts_p (x, y);
kono
parents:
diff changeset
2024 }
kono
parents:
diff changeset
2025
kono
parents:
diff changeset
2026 /* Return true if X >= Y when both are treated as unsigned values. */
kono
parents:
diff changeset
2027 template <typename T1, typename T2>
kono
parents:
diff changeset
2028 inline bool
kono
parents:
diff changeset
2029 wi::geu_p (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2030 {
kono
parents:
diff changeset
2031 return !ltu_p (x, y);
kono
parents:
diff changeset
2032 }
kono
parents:
diff changeset
2033
kono
parents:
diff changeset
2034 /* Return true if X >= Y. Signedness of X and Y is indicated by SGN. */
kono
parents:
diff changeset
2035 template <typename T1, typename T2>
kono
parents:
diff changeset
2036 inline bool
kono
parents:
diff changeset
2037 wi::ge_p (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2038 {
kono
parents:
diff changeset
2039 if (sgn == SIGNED)
kono
parents:
diff changeset
2040 return ges_p (x, y);
kono
parents:
diff changeset
2041 else
kono
parents:
diff changeset
2042 return geu_p (x, y);
kono
parents:
diff changeset
2043 }
kono
parents:
diff changeset
2044
kono
parents:
diff changeset
2045 /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Treat both X and Y
kono
parents:
diff changeset
2046 as signed values. */
kono
parents:
diff changeset
2047 template <typename T1, typename T2>
kono
parents:
diff changeset
2048 inline int
kono
parents:
diff changeset
2049 wi::cmps (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2050 {
kono
parents:
diff changeset
2051 unsigned int precision = get_binary_precision (x, y);
kono
parents:
diff changeset
2052 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2053 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2054 if (wi::fits_shwi_p (yi))
kono
parents:
diff changeset
2055 {
kono
parents:
diff changeset
2056 /* Special case for comparisons with 0. */
kono
parents:
diff changeset
2057 if (STATIC_CONSTANT_P (yi.val[0] == 0))
kono
parents:
diff changeset
2058 return neg_p (xi) ? -1 : !(xi.len == 1 && xi.val[0] == 0);
kono
parents:
diff changeset
2059 /* If x fits into a signed HWI, we can compare directly. */
kono
parents:
diff changeset
2060 if (wi::fits_shwi_p (xi))
kono
parents:
diff changeset
2061 {
kono
parents:
diff changeset
2062 HOST_WIDE_INT xl = xi.to_shwi ();
kono
parents:
diff changeset
2063 HOST_WIDE_INT yl = yi.to_shwi ();
kono
parents:
diff changeset
2064 return xl < yl ? -1 : xl > yl;
kono
parents:
diff changeset
2065 }
kono
parents:
diff changeset
2066 /* If x doesn't fit and is negative, then it must be more
kono
parents:
diff changeset
2067 negative than any signed HWI, and hence smaller than y. */
kono
parents:
diff changeset
2068 if (neg_p (xi))
kono
parents:
diff changeset
2069 return -1;
kono
parents:
diff changeset
2070 /* If x is positive, then it must be larger than any signed HWI,
kono
parents:
diff changeset
2071 and hence greater than y. */
kono
parents:
diff changeset
2072 return 1;
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074 /* Optimize the opposite case, if it can be detected at compile time. */
kono
parents:
diff changeset
2075 if (STATIC_CONSTANT_P (xi.len == 1))
kono
parents:
diff changeset
2076 /* If YI is negative it is lower than the least HWI.
kono
parents:
diff changeset
2077 If YI is positive it is greater than the greatest HWI. */
kono
parents:
diff changeset
2078 return neg_p (yi) ? 1 : -1;
kono
parents:
diff changeset
2079 return cmps_large (xi.val, xi.len, precision, yi.val, yi.len);
kono
parents:
diff changeset
2080 }
kono
parents:
diff changeset
2081
kono
parents:
diff changeset
2082 /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Treat both X and Y
kono
parents:
diff changeset
2083 as unsigned values. */
kono
parents:
diff changeset
2084 template <typename T1, typename T2>
kono
parents:
diff changeset
2085 inline int
kono
parents:
diff changeset
2086 wi::cmpu (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2087 {
kono
parents:
diff changeset
2088 unsigned int precision = get_binary_precision (x, y);
kono
parents:
diff changeset
2089 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2090 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2091 /* Optimize comparisons with constants. */
kono
parents:
diff changeset
2092 if (STATIC_CONSTANT_P (yi.len == 1 && yi.val[0] >= 0))
kono
parents:
diff changeset
2093 {
kono
parents:
diff changeset
2094 /* If XI doesn't fit in a HWI then it must be larger than YI. */
kono
parents:
diff changeset
2095 if (xi.len != 1)
kono
parents:
diff changeset
2096 return 1;
kono
parents:
diff changeset
2097 /* Otherwise compare directly. */
kono
parents:
diff changeset
2098 unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
kono
parents:
diff changeset
2099 unsigned HOST_WIDE_INT yl = yi.val[0];
kono
parents:
diff changeset
2100 return xl < yl ? -1 : xl > yl;
kono
parents:
diff changeset
2101 }
kono
parents:
diff changeset
2102 if (STATIC_CONSTANT_P (xi.len == 1 && xi.val[0] >= 0))
kono
parents:
diff changeset
2103 {
kono
parents:
diff changeset
2104 /* If YI doesn't fit in a HWI then it must be larger than XI. */
kono
parents:
diff changeset
2105 if (yi.len != 1)
kono
parents:
diff changeset
2106 return -1;
kono
parents:
diff changeset
2107 /* Otherwise compare directly. */
kono
parents:
diff changeset
2108 unsigned HOST_WIDE_INT xl = xi.val[0];
kono
parents:
diff changeset
2109 unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
kono
parents:
diff changeset
2110 return xl < yl ? -1 : xl > yl;
kono
parents:
diff changeset
2111 }
kono
parents:
diff changeset
2112 /* Optimize the case of two HWIs. The HWIs are implicitly sign-extended
kono
parents:
diff changeset
2113 for precisions greater than HOST_BITS_WIDE_INT, but sign-extending both
kono
parents:
diff changeset
2114 values does not change the result. */
kono
parents:
diff changeset
2115 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2116 {
kono
parents:
diff changeset
2117 unsigned HOST_WIDE_INT xl = xi.to_uhwi ();
kono
parents:
diff changeset
2118 unsigned HOST_WIDE_INT yl = yi.to_uhwi ();
kono
parents:
diff changeset
2119 return xl < yl ? -1 : xl > yl;
kono
parents:
diff changeset
2120 }
kono
parents:
diff changeset
2121 return cmpu_large (xi.val, xi.len, precision, yi.val, yi.len);
kono
parents:
diff changeset
2122 }
kono
parents:
diff changeset
2123
kono
parents:
diff changeset
2124 /* Return -1 if X < Y, 0 if X == Y and 1 if X > Y. Signedness of
kono
parents:
diff changeset
2125 X and Y indicated by SGN. */
kono
parents:
diff changeset
2126 template <typename T1, typename T2>
kono
parents:
diff changeset
2127 inline int
kono
parents:
diff changeset
2128 wi::cmp (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2129 {
kono
parents:
diff changeset
2130 if (sgn == SIGNED)
kono
parents:
diff changeset
2131 return cmps (x, y);
kono
parents:
diff changeset
2132 else
kono
parents:
diff changeset
2133 return cmpu (x, y);
kono
parents:
diff changeset
2134 }
kono
parents:
diff changeset
2135
kono
parents:
diff changeset
2136 /* Return ~x. */
kono
parents:
diff changeset
2137 template <typename T>
kono
parents:
diff changeset
2138 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2139 wi::bit_not (const T &x)
kono
parents:
diff changeset
2140 {
kono
parents:
diff changeset
2141 WI_UNARY_RESULT_VAR (result, val, T, x);
kono
parents:
diff changeset
2142 WIDE_INT_REF_FOR (T) xi (x, get_precision (result));
kono
parents:
diff changeset
2143 for (unsigned int i = 0; i < xi.len; ++i)
kono
parents:
diff changeset
2144 val[i] = ~xi.val[i];
kono
parents:
diff changeset
2145 result.set_len (xi.len);
kono
parents:
diff changeset
2146 return result;
kono
parents:
diff changeset
2147 }
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 /* Return -x. */
kono
parents:
diff changeset
2150 template <typename T>
kono
parents:
diff changeset
2151 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2152 wi::neg (const T &x)
kono
parents:
diff changeset
2153 {
kono
parents:
diff changeset
2154 return sub (0, x);
kono
parents:
diff changeset
2155 }
kono
parents:
diff changeset
2156
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2157 /* Return -x. Indicate in *OVERFLOW if performing the negation would
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2158 cause an overflow. */
111
kono
parents:
diff changeset
2159 template <typename T>
kono
parents:
diff changeset
2160 inline WI_UNARY_RESULT (T)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2161 wi::neg (const T &x, overflow_type *overflow)
111
kono
parents:
diff changeset
2162 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2163 *overflow = only_sign_bit_p (x) ? OVF_OVERFLOW : OVF_NONE;
111
kono
parents:
diff changeset
2164 return sub (0, x);
kono
parents:
diff changeset
2165 }
kono
parents:
diff changeset
2166
kono
parents:
diff changeset
2167 /* Return the absolute value of x. */
kono
parents:
diff changeset
2168 template <typename T>
kono
parents:
diff changeset
2169 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2170 wi::abs (const T &x)
kono
parents:
diff changeset
2171 {
kono
parents:
diff changeset
2172 return neg_p (x) ? neg (x) : WI_UNARY_RESULT (T) (x);
kono
parents:
diff changeset
2173 }
kono
parents:
diff changeset
2174
kono
parents:
diff changeset
2175 /* Return the result of sign-extending the low OFFSET bits of X. */
kono
parents:
diff changeset
2176 template <typename T>
kono
parents:
diff changeset
2177 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2178 wi::sext (const T &x, unsigned int offset)
kono
parents:
diff changeset
2179 {
kono
parents:
diff changeset
2180 WI_UNARY_RESULT_VAR (result, val, T, x);
kono
parents:
diff changeset
2181 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2182 WIDE_INT_REF_FOR (T) xi (x, precision);
kono
parents:
diff changeset
2183
kono
parents:
diff changeset
2184 if (offset <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2185 {
kono
parents:
diff changeset
2186 val[0] = sext_hwi (xi.ulow (), offset);
kono
parents:
diff changeset
2187 result.set_len (1, true);
kono
parents:
diff changeset
2188 }
kono
parents:
diff changeset
2189 else
kono
parents:
diff changeset
2190 result.set_len (sext_large (val, xi.val, xi.len, precision, offset));
kono
parents:
diff changeset
2191 return result;
kono
parents:
diff changeset
2192 }
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 /* Return the result of zero-extending the low OFFSET bits of X. */
kono
parents:
diff changeset
2195 template <typename T>
kono
parents:
diff changeset
2196 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2197 wi::zext (const T &x, unsigned int offset)
kono
parents:
diff changeset
2198 {
kono
parents:
diff changeset
2199 WI_UNARY_RESULT_VAR (result, val, T, x);
kono
parents:
diff changeset
2200 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2201 WIDE_INT_REF_FOR (T) xi (x, precision);
kono
parents:
diff changeset
2202
kono
parents:
diff changeset
2203 /* This is not just an optimization, it is actually required to
kono
parents:
diff changeset
2204 maintain canonization. */
kono
parents:
diff changeset
2205 if (offset >= precision)
kono
parents:
diff changeset
2206 {
kono
parents:
diff changeset
2207 wi::copy (result, xi);
kono
parents:
diff changeset
2208 return result;
kono
parents:
diff changeset
2209 }
kono
parents:
diff changeset
2210
kono
parents:
diff changeset
2211 /* In these cases we know that at least the top bit will be clear,
kono
parents:
diff changeset
2212 so no sign extension is necessary. */
kono
parents:
diff changeset
2213 if (offset < HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2214 {
kono
parents:
diff changeset
2215 val[0] = zext_hwi (xi.ulow (), offset);
kono
parents:
diff changeset
2216 result.set_len (1, true);
kono
parents:
diff changeset
2217 }
kono
parents:
diff changeset
2218 else
kono
parents:
diff changeset
2219 result.set_len (zext_large (val, xi.val, xi.len, precision, offset), true);
kono
parents:
diff changeset
2220 return result;
kono
parents:
diff changeset
2221 }
kono
parents:
diff changeset
2222
kono
parents:
diff changeset
2223 /* Return the result of extending the low OFFSET bits of X according to
kono
parents:
diff changeset
2224 signedness SGN. */
kono
parents:
diff changeset
2225 template <typename T>
kono
parents:
diff changeset
2226 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2227 wi::ext (const T &x, unsigned int offset, signop sgn)
kono
parents:
diff changeset
2228 {
kono
parents:
diff changeset
2229 return sgn == SIGNED ? sext (x, offset) : zext (x, offset);
kono
parents:
diff changeset
2230 }
kono
parents:
diff changeset
2231
kono
parents:
diff changeset
2232 /* Return an integer that represents X | (1 << bit). */
kono
parents:
diff changeset
2233 template <typename T>
kono
parents:
diff changeset
2234 inline WI_UNARY_RESULT (T)
kono
parents:
diff changeset
2235 wi::set_bit (const T &x, unsigned int bit)
kono
parents:
diff changeset
2236 {
kono
parents:
diff changeset
2237 WI_UNARY_RESULT_VAR (result, val, T, x);
kono
parents:
diff changeset
2238 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2239 WIDE_INT_REF_FOR (T) xi (x, precision);
kono
parents:
diff changeset
2240 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2241 {
kono
parents:
diff changeset
2242 val[0] = xi.ulow () | (HOST_WIDE_INT_1U << bit);
kono
parents:
diff changeset
2243 result.set_len (1);
kono
parents:
diff changeset
2244 }
kono
parents:
diff changeset
2245 else
kono
parents:
diff changeset
2246 result.set_len (set_bit_large (val, xi.val, xi.len, precision, bit));
kono
parents:
diff changeset
2247 return result;
kono
parents:
diff changeset
2248 }
kono
parents:
diff changeset
2249
kono
parents:
diff changeset
2250 /* Return the mininum of X and Y, treating them both as having
kono
parents:
diff changeset
2251 signedness SGN. */
kono
parents:
diff changeset
2252 template <typename T1, typename T2>
kono
parents:
diff changeset
2253 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2254 wi::min (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2255 {
kono
parents:
diff changeset
2256 WI_BINARY_RESULT_VAR (result, val ATTRIBUTE_UNUSED, T1, x, T2, y);
kono
parents:
diff changeset
2257 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2258 if (wi::le_p (x, y, sgn))
kono
parents:
diff changeset
2259 wi::copy (result, WIDE_INT_REF_FOR (T1) (x, precision));
kono
parents:
diff changeset
2260 else
kono
parents:
diff changeset
2261 wi::copy (result, WIDE_INT_REF_FOR (T2) (y, precision));
kono
parents:
diff changeset
2262 return result;
kono
parents:
diff changeset
2263 }
kono
parents:
diff changeset
2264
kono
parents:
diff changeset
2265 /* Return the minimum of X and Y, treating both as signed values. */
kono
parents:
diff changeset
2266 template <typename T1, typename T2>
kono
parents:
diff changeset
2267 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2268 wi::smin (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2269 {
kono
parents:
diff changeset
2270 return wi::min (x, y, SIGNED);
kono
parents:
diff changeset
2271 }
kono
parents:
diff changeset
2272
kono
parents:
diff changeset
2273 /* Return the minimum of X and Y, treating both as unsigned values. */
kono
parents:
diff changeset
2274 template <typename T1, typename T2>
kono
parents:
diff changeset
2275 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2276 wi::umin (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2277 {
kono
parents:
diff changeset
2278 return wi::min (x, y, UNSIGNED);
kono
parents:
diff changeset
2279 }
kono
parents:
diff changeset
2280
kono
parents:
diff changeset
2281 /* Return the maxinum of X and Y, treating them both as having
kono
parents:
diff changeset
2282 signedness SGN. */
kono
parents:
diff changeset
2283 template <typename T1, typename T2>
kono
parents:
diff changeset
2284 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2285 wi::max (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2286 {
kono
parents:
diff changeset
2287 WI_BINARY_RESULT_VAR (result, val ATTRIBUTE_UNUSED, T1, x, T2, y);
kono
parents:
diff changeset
2288 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2289 if (wi::ge_p (x, y, sgn))
kono
parents:
diff changeset
2290 wi::copy (result, WIDE_INT_REF_FOR (T1) (x, precision));
kono
parents:
diff changeset
2291 else
kono
parents:
diff changeset
2292 wi::copy (result, WIDE_INT_REF_FOR (T2) (y, precision));
kono
parents:
diff changeset
2293 return result;
kono
parents:
diff changeset
2294 }
kono
parents:
diff changeset
2295
kono
parents:
diff changeset
2296 /* Return the maximum of X and Y, treating both as signed values. */
kono
parents:
diff changeset
2297 template <typename T1, typename T2>
kono
parents:
diff changeset
2298 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2299 wi::smax (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2300 {
kono
parents:
diff changeset
2301 return wi::max (x, y, SIGNED);
kono
parents:
diff changeset
2302 }
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 /* Return the maximum of X and Y, treating both as unsigned values. */
kono
parents:
diff changeset
2305 template <typename T1, typename T2>
kono
parents:
diff changeset
2306 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2307 wi::umax (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2308 {
kono
parents:
diff changeset
2309 return wi::max (x, y, UNSIGNED);
kono
parents:
diff changeset
2310 }
kono
parents:
diff changeset
2311
kono
parents:
diff changeset
2312 /* Return X & Y. */
kono
parents:
diff changeset
2313 template <typename T1, typename T2>
kono
parents:
diff changeset
2314 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2315 wi::bit_and (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2316 {
kono
parents:
diff changeset
2317 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2318 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2319 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2320 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2321 bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
kono
parents:
diff changeset
2322 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2323 {
kono
parents:
diff changeset
2324 val[0] = xi.ulow () & yi.ulow ();
kono
parents:
diff changeset
2325 result.set_len (1, is_sign_extended);
kono
parents:
diff changeset
2326 }
kono
parents:
diff changeset
2327 else
kono
parents:
diff changeset
2328 result.set_len (and_large (val, xi.val, xi.len, yi.val, yi.len,
kono
parents:
diff changeset
2329 precision), is_sign_extended);
kono
parents:
diff changeset
2330 return result;
kono
parents:
diff changeset
2331 }
kono
parents:
diff changeset
2332
kono
parents:
diff changeset
2333 /* Return X & ~Y. */
kono
parents:
diff changeset
2334 template <typename T1, typename T2>
kono
parents:
diff changeset
2335 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2336 wi::bit_and_not (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2337 {
kono
parents:
diff changeset
2338 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2339 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2340 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2341 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2342 bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
kono
parents:
diff changeset
2343 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2344 {
kono
parents:
diff changeset
2345 val[0] = xi.ulow () & ~yi.ulow ();
kono
parents:
diff changeset
2346 result.set_len (1, is_sign_extended);
kono
parents:
diff changeset
2347 }
kono
parents:
diff changeset
2348 else
kono
parents:
diff changeset
2349 result.set_len (and_not_large (val, xi.val, xi.len, yi.val, yi.len,
kono
parents:
diff changeset
2350 precision), is_sign_extended);
kono
parents:
diff changeset
2351 return result;
kono
parents:
diff changeset
2352 }
kono
parents:
diff changeset
2353
kono
parents:
diff changeset
2354 /* Return X | Y. */
kono
parents:
diff changeset
2355 template <typename T1, typename T2>
kono
parents:
diff changeset
2356 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2357 wi::bit_or (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2358 {
kono
parents:
diff changeset
2359 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2360 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2361 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2362 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2363 bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
kono
parents:
diff changeset
2364 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2365 {
kono
parents:
diff changeset
2366 val[0] = xi.ulow () | yi.ulow ();
kono
parents:
diff changeset
2367 result.set_len (1, is_sign_extended);
kono
parents:
diff changeset
2368 }
kono
parents:
diff changeset
2369 else
kono
parents:
diff changeset
2370 result.set_len (or_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2371 yi.val, yi.len, precision), is_sign_extended);
kono
parents:
diff changeset
2372 return result;
kono
parents:
diff changeset
2373 }
kono
parents:
diff changeset
2374
kono
parents:
diff changeset
2375 /* Return X | ~Y. */
kono
parents:
diff changeset
2376 template <typename T1, typename T2>
kono
parents:
diff changeset
2377 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2378 wi::bit_or_not (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2379 {
kono
parents:
diff changeset
2380 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2381 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2382 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2383 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2384 bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
kono
parents:
diff changeset
2385 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2386 {
kono
parents:
diff changeset
2387 val[0] = xi.ulow () | ~yi.ulow ();
kono
parents:
diff changeset
2388 result.set_len (1, is_sign_extended);
kono
parents:
diff changeset
2389 }
kono
parents:
diff changeset
2390 else
kono
parents:
diff changeset
2391 result.set_len (or_not_large (val, xi.val, xi.len, yi.val, yi.len,
kono
parents:
diff changeset
2392 precision), is_sign_extended);
kono
parents:
diff changeset
2393 return result;
kono
parents:
diff changeset
2394 }
kono
parents:
diff changeset
2395
kono
parents:
diff changeset
2396 /* Return X ^ Y. */
kono
parents:
diff changeset
2397 template <typename T1, typename T2>
kono
parents:
diff changeset
2398 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2399 wi::bit_xor (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2400 {
kono
parents:
diff changeset
2401 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2402 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2403 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2404 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2405 bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended;
kono
parents:
diff changeset
2406 if (__builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2407 {
kono
parents:
diff changeset
2408 val[0] = xi.ulow () ^ yi.ulow ();
kono
parents:
diff changeset
2409 result.set_len (1, is_sign_extended);
kono
parents:
diff changeset
2410 }
kono
parents:
diff changeset
2411 else
kono
parents:
diff changeset
2412 result.set_len (xor_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2413 yi.val, yi.len, precision), is_sign_extended);
kono
parents:
diff changeset
2414 return result;
kono
parents:
diff changeset
2415 }
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 /* Return X + Y. */
kono
parents:
diff changeset
2418 template <typename T1, typename T2>
kono
parents:
diff changeset
2419 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2420 wi::add (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2421 {
kono
parents:
diff changeset
2422 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2423 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2424 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2425 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2426 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2427 {
kono
parents:
diff changeset
2428 val[0] = xi.ulow () + yi.ulow ();
kono
parents:
diff changeset
2429 result.set_len (1);
kono
parents:
diff changeset
2430 }
kono
parents:
diff changeset
2431 /* If the precision is known at compile time to be greater than
kono
parents:
diff changeset
2432 HOST_BITS_PER_WIDE_INT, we can optimize the single-HWI case
kono
parents:
diff changeset
2433 knowing that (a) all bits in those HWIs are significant and
kono
parents:
diff changeset
2434 (b) the result has room for at least two HWIs. This provides
kono
parents:
diff changeset
2435 a fast path for things like offset_int and widest_int.
kono
parents:
diff changeset
2436
kono
parents:
diff changeset
2437 The STATIC_CONSTANT_P test prevents this path from being
kono
parents:
diff changeset
2438 used for wide_ints. wide_ints with precisions greater than
kono
parents:
diff changeset
2439 HOST_BITS_PER_WIDE_INT are relatively rare and there's not much
kono
parents:
diff changeset
2440 point handling them inline. */
kono
parents:
diff changeset
2441 else if (STATIC_CONSTANT_P (precision > HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2442 && __builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2443 {
kono
parents:
diff changeset
2444 unsigned HOST_WIDE_INT xl = xi.ulow ();
kono
parents:
diff changeset
2445 unsigned HOST_WIDE_INT yl = yi.ulow ();
kono
parents:
diff changeset
2446 unsigned HOST_WIDE_INT resultl = xl + yl;
kono
parents:
diff changeset
2447 val[0] = resultl;
kono
parents:
diff changeset
2448 val[1] = (HOST_WIDE_INT) resultl < 0 ? 0 : -1;
kono
parents:
diff changeset
2449 result.set_len (1 + (((resultl ^ xl) & (resultl ^ yl))
kono
parents:
diff changeset
2450 >> (HOST_BITS_PER_WIDE_INT - 1)));
kono
parents:
diff changeset
2451 }
kono
parents:
diff changeset
2452 else
kono
parents:
diff changeset
2453 result.set_len (add_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2454 yi.val, yi.len, precision,
kono
parents:
diff changeset
2455 UNSIGNED, 0));
kono
parents:
diff changeset
2456 return result;
kono
parents:
diff changeset
2457 }
kono
parents:
diff changeset
2458
kono
parents:
diff changeset
2459 /* Return X + Y. Treat X and Y as having the signednes given by SGN
kono
parents:
diff changeset
2460 and indicate in *OVERFLOW whether the operation overflowed. */
kono
parents:
diff changeset
2461 template <typename T1, typename T2>
kono
parents:
diff changeset
2462 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2463 wi::add (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2464 {
kono
parents:
diff changeset
2465 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2466 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2467 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2468 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2469 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2470 {
kono
parents:
diff changeset
2471 unsigned HOST_WIDE_INT xl = xi.ulow ();
kono
parents:
diff changeset
2472 unsigned HOST_WIDE_INT yl = yi.ulow ();
kono
parents:
diff changeset
2473 unsigned HOST_WIDE_INT resultl = xl + yl;
kono
parents:
diff changeset
2474 if (sgn == SIGNED)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2475 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2476 if ((((resultl ^ xl) & (resultl ^ yl))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2477 >> (precision - 1)) & 1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2478 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2479 if (xl > resultl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2480 *overflow = OVF_UNDERFLOW;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2481 else if (xl < resultl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2482 *overflow = OVF_OVERFLOW;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2483 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2484 *overflow = OVF_NONE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2485 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2486 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2487 *overflow = OVF_NONE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2488 }
111
kono
parents:
diff changeset
2489 else
kono
parents:
diff changeset
2490 *overflow = ((resultl << (HOST_BITS_PER_WIDE_INT - precision))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2491 < (xl << (HOST_BITS_PER_WIDE_INT - precision)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2492 ? OVF_OVERFLOW : OVF_NONE;
111
kono
parents:
diff changeset
2493 val[0] = resultl;
kono
parents:
diff changeset
2494 result.set_len (1);
kono
parents:
diff changeset
2495 }
kono
parents:
diff changeset
2496 else
kono
parents:
diff changeset
2497 result.set_len (add_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2498 yi.val, yi.len, precision,
kono
parents:
diff changeset
2499 sgn, overflow));
kono
parents:
diff changeset
2500 return result;
kono
parents:
diff changeset
2501 }
kono
parents:
diff changeset
2502
kono
parents:
diff changeset
2503 /* Return X - Y. */
kono
parents:
diff changeset
2504 template <typename T1, typename T2>
kono
parents:
diff changeset
2505 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2506 wi::sub (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2507 {
kono
parents:
diff changeset
2508 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2509 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2510 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2511 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2512 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2513 {
kono
parents:
diff changeset
2514 val[0] = xi.ulow () - yi.ulow ();
kono
parents:
diff changeset
2515 result.set_len (1);
kono
parents:
diff changeset
2516 }
kono
parents:
diff changeset
2517 /* If the precision is known at compile time to be greater than
kono
parents:
diff changeset
2518 HOST_BITS_PER_WIDE_INT, we can optimize the single-HWI case
kono
parents:
diff changeset
2519 knowing that (a) all bits in those HWIs are significant and
kono
parents:
diff changeset
2520 (b) the result has room for at least two HWIs. This provides
kono
parents:
diff changeset
2521 a fast path for things like offset_int and widest_int.
kono
parents:
diff changeset
2522
kono
parents:
diff changeset
2523 The STATIC_CONSTANT_P test prevents this path from being
kono
parents:
diff changeset
2524 used for wide_ints. wide_ints with precisions greater than
kono
parents:
diff changeset
2525 HOST_BITS_PER_WIDE_INT are relatively rare and there's not much
kono
parents:
diff changeset
2526 point handling them inline. */
kono
parents:
diff changeset
2527 else if (STATIC_CONSTANT_P (precision > HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2528 && __builtin_expect (xi.len + yi.len == 2, true))
kono
parents:
diff changeset
2529 {
kono
parents:
diff changeset
2530 unsigned HOST_WIDE_INT xl = xi.ulow ();
kono
parents:
diff changeset
2531 unsigned HOST_WIDE_INT yl = yi.ulow ();
kono
parents:
diff changeset
2532 unsigned HOST_WIDE_INT resultl = xl - yl;
kono
parents:
diff changeset
2533 val[0] = resultl;
kono
parents:
diff changeset
2534 val[1] = (HOST_WIDE_INT) resultl < 0 ? 0 : -1;
kono
parents:
diff changeset
2535 result.set_len (1 + (((resultl ^ xl) & (xl ^ yl))
kono
parents:
diff changeset
2536 >> (HOST_BITS_PER_WIDE_INT - 1)));
kono
parents:
diff changeset
2537 }
kono
parents:
diff changeset
2538 else
kono
parents:
diff changeset
2539 result.set_len (sub_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2540 yi.val, yi.len, precision,
kono
parents:
diff changeset
2541 UNSIGNED, 0));
kono
parents:
diff changeset
2542 return result;
kono
parents:
diff changeset
2543 }
kono
parents:
diff changeset
2544
kono
parents:
diff changeset
2545 /* Return X - Y. Treat X and Y as having the signednes given by SGN
kono
parents:
diff changeset
2546 and indicate in *OVERFLOW whether the operation overflowed. */
kono
parents:
diff changeset
2547 template <typename T1, typename T2>
kono
parents:
diff changeset
2548 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2549 wi::sub (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2550 {
kono
parents:
diff changeset
2551 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2552 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2553 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2554 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2555 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2556 {
kono
parents:
diff changeset
2557 unsigned HOST_WIDE_INT xl = xi.ulow ();
kono
parents:
diff changeset
2558 unsigned HOST_WIDE_INT yl = yi.ulow ();
kono
parents:
diff changeset
2559 unsigned HOST_WIDE_INT resultl = xl - yl;
kono
parents:
diff changeset
2560 if (sgn == SIGNED)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2561 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2562 if ((((xl ^ yl) & (resultl ^ xl)) >> (precision - 1)) & 1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2563 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2564 if (xl > yl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2565 *overflow = OVF_UNDERFLOW;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2566 else if (xl < yl)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2567 *overflow = OVF_OVERFLOW;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2568 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2569 *overflow = OVF_NONE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2570 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2571 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2572 *overflow = OVF_NONE;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2573 }
111
kono
parents:
diff changeset
2574 else
kono
parents:
diff changeset
2575 *overflow = ((resultl << (HOST_BITS_PER_WIDE_INT - precision))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2576 > (xl << (HOST_BITS_PER_WIDE_INT - precision)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2577 ? OVF_UNDERFLOW : OVF_NONE;
111
kono
parents:
diff changeset
2578 val[0] = resultl;
kono
parents:
diff changeset
2579 result.set_len (1);
kono
parents:
diff changeset
2580 }
kono
parents:
diff changeset
2581 else
kono
parents:
diff changeset
2582 result.set_len (sub_large (val, xi.val, xi.len,
kono
parents:
diff changeset
2583 yi.val, yi.len, precision,
kono
parents:
diff changeset
2584 sgn, overflow));
kono
parents:
diff changeset
2585 return result;
kono
parents:
diff changeset
2586 }
kono
parents:
diff changeset
2587
kono
parents:
diff changeset
2588 /* Return X * Y. */
kono
parents:
diff changeset
2589 template <typename T1, typename T2>
kono
parents:
diff changeset
2590 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2591 wi::mul (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2592 {
kono
parents:
diff changeset
2593 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2594 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2595 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2596 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2597 if (precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
2598 {
kono
parents:
diff changeset
2599 val[0] = xi.ulow () * yi.ulow ();
kono
parents:
diff changeset
2600 result.set_len (1);
kono
parents:
diff changeset
2601 }
kono
parents:
diff changeset
2602 else
kono
parents:
diff changeset
2603 result.set_len (mul_internal (val, xi.val, xi.len, yi.val, yi.len,
kono
parents:
diff changeset
2604 precision, UNSIGNED, 0, false));
kono
parents:
diff changeset
2605 return result;
kono
parents:
diff changeset
2606 }
kono
parents:
diff changeset
2607
kono
parents:
diff changeset
2608 /* Return X * Y. Treat X and Y as having the signednes given by SGN
kono
parents:
diff changeset
2609 and indicate in *OVERFLOW whether the operation overflowed. */
kono
parents:
diff changeset
2610 template <typename T1, typename T2>
kono
parents:
diff changeset
2611 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2612 wi::mul (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2613 {
kono
parents:
diff changeset
2614 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2615 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2616 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2617 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2618 result.set_len (mul_internal (val, xi.val, xi.len,
kono
parents:
diff changeset
2619 yi.val, yi.len, precision,
kono
parents:
diff changeset
2620 sgn, overflow, false));
kono
parents:
diff changeset
2621 return result;
kono
parents:
diff changeset
2622 }
kono
parents:
diff changeset
2623
kono
parents:
diff changeset
2624 /* Return X * Y, treating both X and Y as signed values. Indicate in
kono
parents:
diff changeset
2625 *OVERFLOW whether the operation overflowed. */
kono
parents:
diff changeset
2626 template <typename T1, typename T2>
kono
parents:
diff changeset
2627 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2628 wi::smul (const T1 &x, const T2 &y, overflow_type *overflow)
111
kono
parents:
diff changeset
2629 {
kono
parents:
diff changeset
2630 return mul (x, y, SIGNED, overflow);
kono
parents:
diff changeset
2631 }
kono
parents:
diff changeset
2632
kono
parents:
diff changeset
2633 /* Return X * Y, treating both X and Y as unsigned values. Indicate in
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2634 *OVERFLOW if the result overflows. */
111
kono
parents:
diff changeset
2635 template <typename T1, typename T2>
kono
parents:
diff changeset
2636 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2637 wi::umul (const T1 &x, const T2 &y, overflow_type *overflow)
111
kono
parents:
diff changeset
2638 {
kono
parents:
diff changeset
2639 return mul (x, y, UNSIGNED, overflow);
kono
parents:
diff changeset
2640 }
kono
parents:
diff changeset
2641
kono
parents:
diff changeset
2642 /* Perform a widening multiplication of X and Y, extending the values
kono
parents:
diff changeset
2643 according to SGN, and return the high part of the result. */
kono
parents:
diff changeset
2644 template <typename T1, typename T2>
kono
parents:
diff changeset
2645 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2646 wi::mul_high (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
2647 {
kono
parents:
diff changeset
2648 WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
kono
parents:
diff changeset
2649 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
2650 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2651 WIDE_INT_REF_FOR (T2) yi (y, precision);
kono
parents:
diff changeset
2652 result.set_len (mul_internal (val, xi.val, xi.len,
kono
parents:
diff changeset
2653 yi.val, yi.len, precision,
kono
parents:
diff changeset
2654 sgn, 0, true));
kono
parents:
diff changeset
2655 return result;
kono
parents:
diff changeset
2656 }
kono
parents:
diff changeset
2657
kono
parents:
diff changeset
2658 /* Return X / Y, rouding towards 0. Treat X and Y as having the
kono
parents:
diff changeset
2659 signedness given by SGN. Indicate in *OVERFLOW if the result
kono
parents:
diff changeset
2660 overflows. */
kono
parents:
diff changeset
2661 template <typename T1, typename T2>
kono
parents:
diff changeset
2662 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2663 wi::div_trunc (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2664 {
kono
parents:
diff changeset
2665 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2666 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2667 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2668 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2669
kono
parents:
diff changeset
2670 quotient.set_len (divmod_internal (quotient_val, 0, 0, xi.val, xi.len,
kono
parents:
diff changeset
2671 precision,
kono
parents:
diff changeset
2672 yi.val, yi.len, yi.precision,
kono
parents:
diff changeset
2673 sgn, overflow));
kono
parents:
diff changeset
2674 return quotient;
kono
parents:
diff changeset
2675 }
kono
parents:
diff changeset
2676
kono
parents:
diff changeset
2677 /* Return X / Y, rouding towards 0. Treat X and Y as signed values. */
kono
parents:
diff changeset
2678 template <typename T1, typename T2>
kono
parents:
diff changeset
2679 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2680 wi::sdiv_trunc (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2681 {
kono
parents:
diff changeset
2682 return div_trunc (x, y, SIGNED);
kono
parents:
diff changeset
2683 }
kono
parents:
diff changeset
2684
kono
parents:
diff changeset
2685 /* Return X / Y, rouding towards 0. Treat X and Y as unsigned values. */
kono
parents:
diff changeset
2686 template <typename T1, typename T2>
kono
parents:
diff changeset
2687 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2688 wi::udiv_trunc (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2689 {
kono
parents:
diff changeset
2690 return div_trunc (x, y, UNSIGNED);
kono
parents:
diff changeset
2691 }
kono
parents:
diff changeset
2692
kono
parents:
diff changeset
2693 /* Return X / Y, rouding towards -inf. Treat X and Y as having the
kono
parents:
diff changeset
2694 signedness given by SGN. Indicate in *OVERFLOW if the result
kono
parents:
diff changeset
2695 overflows. */
kono
parents:
diff changeset
2696 template <typename T1, typename T2>
kono
parents:
diff changeset
2697 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2698 wi::div_floor (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2699 {
kono
parents:
diff changeset
2700 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2701 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2702 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2703 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2704 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2705
kono
parents:
diff changeset
2706 unsigned int remainder_len;
kono
parents:
diff changeset
2707 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2708 &remainder_len, remainder_val,
kono
parents:
diff changeset
2709 xi.val, xi.len, precision,
kono
parents:
diff changeset
2710 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2711 overflow));
kono
parents:
diff changeset
2712 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2713 if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn) && remainder != 0)
kono
parents:
diff changeset
2714 return quotient - 1;
kono
parents:
diff changeset
2715 return quotient;
kono
parents:
diff changeset
2716 }
kono
parents:
diff changeset
2717
kono
parents:
diff changeset
2718 /* Return X / Y, rouding towards -inf. Treat X and Y as signed values. */
kono
parents:
diff changeset
2719 template <typename T1, typename T2>
kono
parents:
diff changeset
2720 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2721 wi::sdiv_floor (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2722 {
kono
parents:
diff changeset
2723 return div_floor (x, y, SIGNED);
kono
parents:
diff changeset
2724 }
kono
parents:
diff changeset
2725
kono
parents:
diff changeset
2726 /* Return X / Y, rouding towards -inf. Treat X and Y as unsigned values. */
kono
parents:
diff changeset
2727 /* ??? Why do we have both this and udiv_trunc. Aren't they the same? */
kono
parents:
diff changeset
2728 template <typename T1, typename T2>
kono
parents:
diff changeset
2729 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2730 wi::udiv_floor (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2731 {
kono
parents:
diff changeset
2732 return div_floor (x, y, UNSIGNED);
kono
parents:
diff changeset
2733 }
kono
parents:
diff changeset
2734
kono
parents:
diff changeset
2735 /* Return X / Y, rouding towards +inf. Treat X and Y as having the
kono
parents:
diff changeset
2736 signedness given by SGN. Indicate in *OVERFLOW if the result
kono
parents:
diff changeset
2737 overflows. */
kono
parents:
diff changeset
2738 template <typename T1, typename T2>
kono
parents:
diff changeset
2739 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2740 wi::div_ceil (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2741 {
kono
parents:
diff changeset
2742 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2743 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2744 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2745 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2746 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2747
kono
parents:
diff changeset
2748 unsigned int remainder_len;
kono
parents:
diff changeset
2749 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2750 &remainder_len, remainder_val,
kono
parents:
diff changeset
2751 xi.val, xi.len, precision,
kono
parents:
diff changeset
2752 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2753 overflow));
kono
parents:
diff changeset
2754 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2755 if (wi::neg_p (x, sgn) == wi::neg_p (y, sgn) && remainder != 0)
kono
parents:
diff changeset
2756 return quotient + 1;
kono
parents:
diff changeset
2757 return quotient;
kono
parents:
diff changeset
2758 }
kono
parents:
diff changeset
2759
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2760 /* Return X / Y, rouding towards +inf. Treat X and Y as unsigned values. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2761 template <typename T1, typename T2>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2762 inline WI_BINARY_RESULT (T1, T2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2763 wi::udiv_ceil (const T1 &x, const T2 &y)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2764 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2765 return div_ceil (x, y, UNSIGNED);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2766 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2767
111
kono
parents:
diff changeset
2768 /* Return X / Y, rouding towards nearest with ties away from zero.
kono
parents:
diff changeset
2769 Treat X and Y as having the signedness given by SGN. Indicate
kono
parents:
diff changeset
2770 in *OVERFLOW if the result overflows. */
kono
parents:
diff changeset
2771 template <typename T1, typename T2>
kono
parents:
diff changeset
2772 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2773 wi::div_round (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2774 {
kono
parents:
diff changeset
2775 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2776 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2777 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2778 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2779 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2780
kono
parents:
diff changeset
2781 unsigned int remainder_len;
kono
parents:
diff changeset
2782 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2783 &remainder_len, remainder_val,
kono
parents:
diff changeset
2784 xi.val, xi.len, precision,
kono
parents:
diff changeset
2785 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2786 overflow));
kono
parents:
diff changeset
2787 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 if (remainder != 0)
kono
parents:
diff changeset
2790 {
kono
parents:
diff changeset
2791 if (sgn == SIGNED)
kono
parents:
diff changeset
2792 {
kono
parents:
diff changeset
2793 WI_BINARY_RESULT (T1, T2) abs_remainder = wi::abs (remainder);
kono
parents:
diff changeset
2794 if (wi::geu_p (abs_remainder, wi::sub (wi::abs (y), abs_remainder)))
kono
parents:
diff changeset
2795 {
kono
parents:
diff changeset
2796 if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn))
kono
parents:
diff changeset
2797 return quotient - 1;
kono
parents:
diff changeset
2798 else
kono
parents:
diff changeset
2799 return quotient + 1;
kono
parents:
diff changeset
2800 }
kono
parents:
diff changeset
2801 }
kono
parents:
diff changeset
2802 else
kono
parents:
diff changeset
2803 {
kono
parents:
diff changeset
2804 if (wi::geu_p (remainder, wi::sub (y, remainder)))
kono
parents:
diff changeset
2805 return quotient + 1;
kono
parents:
diff changeset
2806 }
kono
parents:
diff changeset
2807 }
kono
parents:
diff changeset
2808 return quotient;
kono
parents:
diff changeset
2809 }
kono
parents:
diff changeset
2810
kono
parents:
diff changeset
2811 /* Return X / Y, rouding towards 0. Treat X and Y as having the
kono
parents:
diff changeset
2812 signedness given by SGN. Store the remainder in *REMAINDER_PTR. */
kono
parents:
diff changeset
2813 template <typename T1, typename T2>
kono
parents:
diff changeset
2814 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2815 wi::divmod_trunc (const T1 &x, const T2 &y, signop sgn,
kono
parents:
diff changeset
2816 WI_BINARY_RESULT (T1, T2) *remainder_ptr)
kono
parents:
diff changeset
2817 {
kono
parents:
diff changeset
2818 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2819 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2820 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2821 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2822 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2823
kono
parents:
diff changeset
2824 unsigned int remainder_len;
kono
parents:
diff changeset
2825 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2826 &remainder_len, remainder_val,
kono
parents:
diff changeset
2827 xi.val, xi.len, precision,
kono
parents:
diff changeset
2828 yi.val, yi.len, yi.precision, sgn, 0));
kono
parents:
diff changeset
2829 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2830
kono
parents:
diff changeset
2831 *remainder_ptr = remainder;
kono
parents:
diff changeset
2832 return quotient;
kono
parents:
diff changeset
2833 }
kono
parents:
diff changeset
2834
kono
parents:
diff changeset
2835 /* Compute the greatest common divisor of two numbers A and B using
kono
parents:
diff changeset
2836 Euclid's algorithm. */
kono
parents:
diff changeset
2837 template <typename T1, typename T2>
kono
parents:
diff changeset
2838 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2839 wi::gcd (const T1 &a, const T2 &b, signop sgn)
kono
parents:
diff changeset
2840 {
kono
parents:
diff changeset
2841 T1 x, y, z;
kono
parents:
diff changeset
2842
kono
parents:
diff changeset
2843 x = wi::abs (a);
kono
parents:
diff changeset
2844 y = wi::abs (b);
kono
parents:
diff changeset
2845
kono
parents:
diff changeset
2846 while (gt_p (x, 0, sgn))
kono
parents:
diff changeset
2847 {
kono
parents:
diff changeset
2848 z = mod_trunc (y, x, sgn);
kono
parents:
diff changeset
2849 y = x;
kono
parents:
diff changeset
2850 x = z;
kono
parents:
diff changeset
2851 }
kono
parents:
diff changeset
2852
kono
parents:
diff changeset
2853 return y;
kono
parents:
diff changeset
2854 }
kono
parents:
diff changeset
2855
kono
parents:
diff changeset
2856 /* Compute X / Y, rouding towards 0, and return the remainder.
kono
parents:
diff changeset
2857 Treat X and Y as having the signedness given by SGN. Indicate
kono
parents:
diff changeset
2858 in *OVERFLOW if the division overflows. */
kono
parents:
diff changeset
2859 template <typename T1, typename T2>
kono
parents:
diff changeset
2860 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2861 wi::mod_trunc (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2862 {
kono
parents:
diff changeset
2863 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2864 unsigned int precision = get_precision (remainder);
kono
parents:
diff changeset
2865 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2866 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2867
kono
parents:
diff changeset
2868 unsigned int remainder_len;
kono
parents:
diff changeset
2869 divmod_internal (0, &remainder_len, remainder_val,
kono
parents:
diff changeset
2870 xi.val, xi.len, precision,
kono
parents:
diff changeset
2871 yi.val, yi.len, yi.precision, sgn, overflow);
kono
parents:
diff changeset
2872 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2873
kono
parents:
diff changeset
2874 return remainder;
kono
parents:
diff changeset
2875 }
kono
parents:
diff changeset
2876
kono
parents:
diff changeset
2877 /* Compute X / Y, rouding towards 0, and return the remainder.
kono
parents:
diff changeset
2878 Treat X and Y as signed values. */
kono
parents:
diff changeset
2879 template <typename T1, typename T2>
kono
parents:
diff changeset
2880 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2881 wi::smod_trunc (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2882 {
kono
parents:
diff changeset
2883 return mod_trunc (x, y, SIGNED);
kono
parents:
diff changeset
2884 }
kono
parents:
diff changeset
2885
kono
parents:
diff changeset
2886 /* Compute X / Y, rouding towards 0, and return the remainder.
kono
parents:
diff changeset
2887 Treat X and Y as unsigned values. */
kono
parents:
diff changeset
2888 template <typename T1, typename T2>
kono
parents:
diff changeset
2889 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2890 wi::umod_trunc (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2891 {
kono
parents:
diff changeset
2892 return mod_trunc (x, y, UNSIGNED);
kono
parents:
diff changeset
2893 }
kono
parents:
diff changeset
2894
kono
parents:
diff changeset
2895 /* Compute X / Y, rouding towards -inf, and return the remainder.
kono
parents:
diff changeset
2896 Treat X and Y as having the signedness given by SGN. Indicate
kono
parents:
diff changeset
2897 in *OVERFLOW if the division overflows. */
kono
parents:
diff changeset
2898 template <typename T1, typename T2>
kono
parents:
diff changeset
2899 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2900 wi::mod_floor (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2901 {
kono
parents:
diff changeset
2902 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2903 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2904 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2905 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2906 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2907
kono
parents:
diff changeset
2908 unsigned int remainder_len;
kono
parents:
diff changeset
2909 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2910 &remainder_len, remainder_val,
kono
parents:
diff changeset
2911 xi.val, xi.len, precision,
kono
parents:
diff changeset
2912 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2913 overflow));
kono
parents:
diff changeset
2914 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2915
kono
parents:
diff changeset
2916 if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn) && remainder != 0)
kono
parents:
diff changeset
2917 return remainder + y;
kono
parents:
diff changeset
2918 return remainder;
kono
parents:
diff changeset
2919 }
kono
parents:
diff changeset
2920
kono
parents:
diff changeset
2921 /* Compute X / Y, rouding towards -inf, and return the remainder.
kono
parents:
diff changeset
2922 Treat X and Y as unsigned values. */
kono
parents:
diff changeset
2923 /* ??? Why do we have both this and umod_trunc. Aren't they the same? */
kono
parents:
diff changeset
2924 template <typename T1, typename T2>
kono
parents:
diff changeset
2925 inline WI_BINARY_RESULT (T1, T2)
kono
parents:
diff changeset
2926 wi::umod_floor (const T1 &x, const T2 &y)
kono
parents:
diff changeset
2927 {
kono
parents:
diff changeset
2928 return mod_floor (x, y, UNSIGNED);
kono
parents:
diff changeset
2929 }
kono
parents:
diff changeset
2930
kono
parents:
diff changeset
2931 /* Compute X / Y, rouding towards +inf, and return the remainder.
kono
parents:
diff changeset
2932 Treat X and Y as having the signedness given by SGN. Indicate
kono
parents:
diff changeset
2933 in *OVERFLOW if the division overflows. */
kono
parents:
diff changeset
2934 template <typename T1, typename T2>
kono
parents:
diff changeset
2935 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2936 wi::mod_ceil (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2937 {
kono
parents:
diff changeset
2938 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2939 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2940 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2941 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2942 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2943
kono
parents:
diff changeset
2944 unsigned int remainder_len;
kono
parents:
diff changeset
2945 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2946 &remainder_len, remainder_val,
kono
parents:
diff changeset
2947 xi.val, xi.len, precision,
kono
parents:
diff changeset
2948 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2949 overflow));
kono
parents:
diff changeset
2950 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2951
kono
parents:
diff changeset
2952 if (wi::neg_p (x, sgn) == wi::neg_p (y, sgn) && remainder != 0)
kono
parents:
diff changeset
2953 return remainder - y;
kono
parents:
diff changeset
2954 return remainder;
kono
parents:
diff changeset
2955 }
kono
parents:
diff changeset
2956
kono
parents:
diff changeset
2957 /* Compute X / Y, rouding towards nearest with ties away from zero,
kono
parents:
diff changeset
2958 and return the remainder. Treat X and Y as having the signedness
kono
parents:
diff changeset
2959 given by SGN. Indicate in *OVERFLOW if the division overflows. */
kono
parents:
diff changeset
2960 template <typename T1, typename T2>
kono
parents:
diff changeset
2961 inline WI_BINARY_RESULT (T1, T2)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2962 wi::mod_round (const T1 &x, const T2 &y, signop sgn, overflow_type *overflow)
111
kono
parents:
diff changeset
2963 {
kono
parents:
diff changeset
2964 WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y);
kono
parents:
diff changeset
2965 WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y);
kono
parents:
diff changeset
2966 unsigned int precision = get_precision (quotient);
kono
parents:
diff changeset
2967 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
2968 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
2969
kono
parents:
diff changeset
2970 unsigned int remainder_len;
kono
parents:
diff changeset
2971 quotient.set_len (divmod_internal (quotient_val,
kono
parents:
diff changeset
2972 &remainder_len, remainder_val,
kono
parents:
diff changeset
2973 xi.val, xi.len, precision,
kono
parents:
diff changeset
2974 yi.val, yi.len, yi.precision, sgn,
kono
parents:
diff changeset
2975 overflow));
kono
parents:
diff changeset
2976 remainder.set_len (remainder_len);
kono
parents:
diff changeset
2977
kono
parents:
diff changeset
2978 if (remainder != 0)
kono
parents:
diff changeset
2979 {
kono
parents:
diff changeset
2980 if (sgn == SIGNED)
kono
parents:
diff changeset
2981 {
kono
parents:
diff changeset
2982 WI_BINARY_RESULT (T1, T2) abs_remainder = wi::abs (remainder);
kono
parents:
diff changeset
2983 if (wi::geu_p (abs_remainder, wi::sub (wi::abs (y), abs_remainder)))
kono
parents:
diff changeset
2984 {
kono
parents:
diff changeset
2985 if (wi::neg_p (x, sgn) != wi::neg_p (y, sgn))
kono
parents:
diff changeset
2986 return remainder + y;
kono
parents:
diff changeset
2987 else
kono
parents:
diff changeset
2988 return remainder - y;
kono
parents:
diff changeset
2989 }
kono
parents:
diff changeset
2990 }
kono
parents:
diff changeset
2991 else
kono
parents:
diff changeset
2992 {
kono
parents:
diff changeset
2993 if (wi::geu_p (remainder, wi::sub (y, remainder)))
kono
parents:
diff changeset
2994 return remainder - y;
kono
parents:
diff changeset
2995 }
kono
parents:
diff changeset
2996 }
kono
parents:
diff changeset
2997 return remainder;
kono
parents:
diff changeset
2998 }
kono
parents:
diff changeset
2999
kono
parents:
diff changeset
3000 /* Return true if X is a multiple of Y. Treat X and Y as having the
kono
parents:
diff changeset
3001 signedness given by SGN. */
kono
parents:
diff changeset
3002 template <typename T1, typename T2>
kono
parents:
diff changeset
3003 inline bool
kono
parents:
diff changeset
3004 wi::multiple_of_p (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
3005 {
kono
parents:
diff changeset
3006 return wi::mod_trunc (x, y, sgn) == 0;
kono
parents:
diff changeset
3007 }
kono
parents:
diff changeset
3008
kono
parents:
diff changeset
3009 /* Return true if X is a multiple of Y, storing X / Y in *RES if so.
kono
parents:
diff changeset
3010 Treat X and Y as having the signedness given by SGN. */
kono
parents:
diff changeset
3011 template <typename T1, typename T2>
kono
parents:
diff changeset
3012 inline bool
kono
parents:
diff changeset
3013 wi::multiple_of_p (const T1 &x, const T2 &y, signop sgn,
kono
parents:
diff changeset
3014 WI_BINARY_RESULT (T1, T2) *res)
kono
parents:
diff changeset
3015 {
kono
parents:
diff changeset
3016 WI_BINARY_RESULT (T1, T2) remainder;
kono
parents:
diff changeset
3017 WI_BINARY_RESULT (T1, T2) quotient
kono
parents:
diff changeset
3018 = divmod_trunc (x, y, sgn, &remainder);
kono
parents:
diff changeset
3019 if (remainder == 0)
kono
parents:
diff changeset
3020 {
kono
parents:
diff changeset
3021 *res = quotient;
kono
parents:
diff changeset
3022 return true;
kono
parents:
diff changeset
3023 }
kono
parents:
diff changeset
3024 return false;
kono
parents:
diff changeset
3025 }
kono
parents:
diff changeset
3026
kono
parents:
diff changeset
3027 /* Return X << Y. Return 0 if Y is greater than or equal to
kono
parents:
diff changeset
3028 the precision of X. */
kono
parents:
diff changeset
3029 template <typename T1, typename T2>
kono
parents:
diff changeset
3030 inline WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3031 wi::lshift (const T1 &x, const T2 &y)
kono
parents:
diff changeset
3032 {
kono
parents:
diff changeset
3033 WI_UNARY_RESULT_VAR (result, val, T1, x);
kono
parents:
diff changeset
3034 unsigned int precision = get_precision (result);
kono
parents:
diff changeset
3035 WIDE_INT_REF_FOR (T1) xi (x, precision);
kono
parents:
diff changeset
3036 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
3037 /* Handle the simple cases quickly. */
kono
parents:
diff changeset
3038 if (geu_p (yi, precision))
kono
parents:
diff changeset
3039 {
kono
parents:
diff changeset
3040 val[0] = 0;
kono
parents:
diff changeset
3041 result.set_len (1);
kono
parents:
diff changeset
3042 }
kono
parents:
diff changeset
3043 else
kono
parents:
diff changeset
3044 {
kono
parents:
diff changeset
3045 unsigned int shift = yi.to_uhwi ();
kono
parents:
diff changeset
3046 /* For fixed-precision integers like offset_int and widest_int,
kono
parents:
diff changeset
3047 handle the case where the shift value is constant and the
kono
parents:
diff changeset
3048 result is a single nonnegative HWI (meaning that we don't
kono
parents:
diff changeset
3049 need to worry about val[1]). This is particularly common
kono
parents:
diff changeset
3050 for converting a byte count to a bit count.
kono
parents:
diff changeset
3051
kono
parents:
diff changeset
3052 For variable-precision integers like wide_int, handle HWI
kono
parents:
diff changeset
3053 and sub-HWI integers inline. */
kono
parents:
diff changeset
3054 if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3055 ? (STATIC_CONSTANT_P (shift < HOST_BITS_PER_WIDE_INT - 1)
kono
parents:
diff changeset
3056 && xi.len == 1
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3057 && IN_RANGE (xi.val[0], 0, HOST_WIDE_INT_MAX >> shift))
111
kono
parents:
diff changeset
3058 : precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3059 {
kono
parents:
diff changeset
3060 val[0] = xi.ulow () << shift;
kono
parents:
diff changeset
3061 result.set_len (1);
kono
parents:
diff changeset
3062 }
kono
parents:
diff changeset
3063 else
kono
parents:
diff changeset
3064 result.set_len (lshift_large (val, xi.val, xi.len,
kono
parents:
diff changeset
3065 precision, shift));
kono
parents:
diff changeset
3066 }
kono
parents:
diff changeset
3067 return result;
kono
parents:
diff changeset
3068 }
kono
parents:
diff changeset
3069
kono
parents:
diff changeset
3070 /* Return X >> Y, using a logical shift. Return 0 if Y is greater than
kono
parents:
diff changeset
3071 or equal to the precision of X. */
kono
parents:
diff changeset
3072 template <typename T1, typename T2>
kono
parents:
diff changeset
3073 inline WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3074 wi::lrshift (const T1 &x, const T2 &y)
kono
parents:
diff changeset
3075 {
kono
parents:
diff changeset
3076 WI_UNARY_RESULT_VAR (result, val, T1, x);
kono
parents:
diff changeset
3077 /* Do things in the precision of the input rather than the output,
kono
parents:
diff changeset
3078 since the result can be no larger than that. */
kono
parents:
diff changeset
3079 WIDE_INT_REF_FOR (T1) xi (x);
kono
parents:
diff changeset
3080 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
3081 /* Handle the simple cases quickly. */
kono
parents:
diff changeset
3082 if (geu_p (yi, xi.precision))
kono
parents:
diff changeset
3083 {
kono
parents:
diff changeset
3084 val[0] = 0;
kono
parents:
diff changeset
3085 result.set_len (1);
kono
parents:
diff changeset
3086 }
kono
parents:
diff changeset
3087 else
kono
parents:
diff changeset
3088 {
kono
parents:
diff changeset
3089 unsigned int shift = yi.to_uhwi ();
kono
parents:
diff changeset
3090 /* For fixed-precision integers like offset_int and widest_int,
kono
parents:
diff changeset
3091 handle the case where the shift value is constant and the
kono
parents:
diff changeset
3092 shifted value is a single nonnegative HWI (meaning that all
kono
parents:
diff changeset
3093 bits above the HWI are zero). This is particularly common
kono
parents:
diff changeset
3094 for converting a bit count to a byte count.
kono
parents:
diff changeset
3095
kono
parents:
diff changeset
3096 For variable-precision integers like wide_int, handle HWI
kono
parents:
diff changeset
3097 and sub-HWI integers inline. */
kono
parents:
diff changeset
3098 if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3099 ? (shift < HOST_BITS_PER_WIDE_INT
kono
parents:
diff changeset
3100 && xi.len == 1
kono
parents:
diff changeset
3101 && xi.val[0] >= 0)
kono
parents:
diff changeset
3102 : xi.precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3103 {
kono
parents:
diff changeset
3104 val[0] = xi.to_uhwi () >> shift;
kono
parents:
diff changeset
3105 result.set_len (1);
kono
parents:
diff changeset
3106 }
kono
parents:
diff changeset
3107 else
kono
parents:
diff changeset
3108 result.set_len (lrshift_large (val, xi.val, xi.len, xi.precision,
kono
parents:
diff changeset
3109 get_precision (result), shift));
kono
parents:
diff changeset
3110 }
kono
parents:
diff changeset
3111 return result;
kono
parents:
diff changeset
3112 }
kono
parents:
diff changeset
3113
kono
parents:
diff changeset
3114 /* Return X >> Y, using an arithmetic shift. Return a sign mask if
kono
parents:
diff changeset
3115 Y is greater than or equal to the precision of X. */
kono
parents:
diff changeset
3116 template <typename T1, typename T2>
kono
parents:
diff changeset
3117 inline WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3118 wi::arshift (const T1 &x, const T2 &y)
kono
parents:
diff changeset
3119 {
kono
parents:
diff changeset
3120 WI_UNARY_RESULT_VAR (result, val, T1, x);
kono
parents:
diff changeset
3121 /* Do things in the precision of the input rather than the output,
kono
parents:
diff changeset
3122 since the result can be no larger than that. */
kono
parents:
diff changeset
3123 WIDE_INT_REF_FOR (T1) xi (x);
kono
parents:
diff changeset
3124 WIDE_INT_REF_FOR (T2) yi (y);
kono
parents:
diff changeset
3125 /* Handle the simple cases quickly. */
kono
parents:
diff changeset
3126 if (geu_p (yi, xi.precision))
kono
parents:
diff changeset
3127 {
kono
parents:
diff changeset
3128 val[0] = sign_mask (x);
kono
parents:
diff changeset
3129 result.set_len (1);
kono
parents:
diff changeset
3130 }
kono
parents:
diff changeset
3131 else
kono
parents:
diff changeset
3132 {
kono
parents:
diff changeset
3133 unsigned int shift = yi.to_uhwi ();
kono
parents:
diff changeset
3134 if (xi.precision <= HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3135 {
kono
parents:
diff changeset
3136 val[0] = sext_hwi (xi.ulow () >> shift, xi.precision - shift);
kono
parents:
diff changeset
3137 result.set_len (1, true);
kono
parents:
diff changeset
3138 }
kono
parents:
diff changeset
3139 else
kono
parents:
diff changeset
3140 result.set_len (arshift_large (val, xi.val, xi.len, xi.precision,
kono
parents:
diff changeset
3141 get_precision (result), shift));
kono
parents:
diff changeset
3142 }
kono
parents:
diff changeset
3143 return result;
kono
parents:
diff changeset
3144 }
kono
parents:
diff changeset
3145
kono
parents:
diff changeset
3146 /* Return X >> Y, using an arithmetic shift if SGN is SIGNED and a
kono
parents:
diff changeset
3147 logical shift otherwise. */
kono
parents:
diff changeset
3148 template <typename T1, typename T2>
kono
parents:
diff changeset
3149 inline WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3150 wi::rshift (const T1 &x, const T2 &y, signop sgn)
kono
parents:
diff changeset
3151 {
kono
parents:
diff changeset
3152 if (sgn == UNSIGNED)
kono
parents:
diff changeset
3153 return lrshift (x, y);
kono
parents:
diff changeset
3154 else
kono
parents:
diff changeset
3155 return arshift (x, y);
kono
parents:
diff changeset
3156 }
kono
parents:
diff changeset
3157
kono
parents:
diff changeset
3158 /* Return the result of rotating the low WIDTH bits of X left by Y
kono
parents:
diff changeset
3159 bits and zero-extending the result. Use a full-width rotate if
kono
parents:
diff changeset
3160 WIDTH is zero. */
kono
parents:
diff changeset
3161 template <typename T1, typename T2>
kono
parents:
diff changeset
3162 WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3163 wi::lrotate (const T1 &x, const T2 &y, unsigned int width)
kono
parents:
diff changeset
3164 {
kono
parents:
diff changeset
3165 unsigned int precision = get_binary_precision (x, x);
kono
parents:
diff changeset
3166 if (width == 0)
kono
parents:
diff changeset
3167 width = precision;
kono
parents:
diff changeset
3168 WI_UNARY_RESULT (T2) ymod = umod_trunc (y, width);
kono
parents:
diff changeset
3169 WI_UNARY_RESULT (T1) left = wi::lshift (x, ymod);
kono
parents:
diff changeset
3170 WI_UNARY_RESULT (T1) right = wi::lrshift (x, wi::sub (width, ymod));
kono
parents:
diff changeset
3171 if (width != precision)
kono
parents:
diff changeset
3172 return wi::zext (left, width) | wi::zext (right, width);
kono
parents:
diff changeset
3173 return left | right;
kono
parents:
diff changeset
3174 }
kono
parents:
diff changeset
3175
kono
parents:
diff changeset
3176 /* Return the result of rotating the low WIDTH bits of X right by Y
kono
parents:
diff changeset
3177 bits and zero-extending the result. Use a full-width rotate if
kono
parents:
diff changeset
3178 WIDTH is zero. */
kono
parents:
diff changeset
3179 template <typename T1, typename T2>
kono
parents:
diff changeset
3180 WI_UNARY_RESULT (T1)
kono
parents:
diff changeset
3181 wi::rrotate (const T1 &x, const T2 &y, unsigned int width)
kono
parents:
diff changeset
3182 {
kono
parents:
diff changeset
3183 unsigned int precision = get_binary_precision (x, x);
kono
parents:
diff changeset
3184 if (width == 0)
kono
parents:
diff changeset
3185 width = precision;
kono
parents:
diff changeset
3186 WI_UNARY_RESULT (T2) ymod = umod_trunc (y, width);
kono
parents:
diff changeset
3187 WI_UNARY_RESULT (T1) right = wi::lrshift (x, ymod);
kono
parents:
diff changeset
3188 WI_UNARY_RESULT (T1) left = wi::lshift (x, wi::sub (width, ymod));
kono
parents:
diff changeset
3189 if (width != precision)
kono
parents:
diff changeset
3190 return wi::zext (left, width) | wi::zext (right, width);
kono
parents:
diff changeset
3191 return left | right;
kono
parents:
diff changeset
3192 }
kono
parents:
diff changeset
3193
kono
parents:
diff changeset
3194 /* Return 0 if the number of 1s in X is even and 1 if the number of 1s
kono
parents:
diff changeset
3195 is odd. */
kono
parents:
diff changeset
3196 inline int
kono
parents:
diff changeset
3197 wi::parity (const wide_int_ref &x)
kono
parents:
diff changeset
3198 {
kono
parents:
diff changeset
3199 return popcount (x) & 1;
kono
parents:
diff changeset
3200 }
kono
parents:
diff changeset
3201
kono
parents:
diff changeset
3202 /* Extract WIDTH bits from X, starting at BITPOS. */
kono
parents:
diff changeset
3203 template <typename T>
kono
parents:
diff changeset
3204 inline unsigned HOST_WIDE_INT
kono
parents:
diff changeset
3205 wi::extract_uhwi (const T &x, unsigned int bitpos, unsigned int width)
kono
parents:
diff changeset
3206 {
kono
parents:
diff changeset
3207 unsigned precision = get_precision (x);
kono
parents:
diff changeset
3208 if (precision < bitpos + width)
kono
parents:
diff changeset
3209 precision = bitpos + width;
kono
parents:
diff changeset
3210 WIDE_INT_REF_FOR (T) xi (x, precision);
kono
parents:
diff changeset
3211
kono
parents:
diff changeset
3212 /* Handle this rare case after the above, so that we assert about
kono
parents:
diff changeset
3213 bogus BITPOS values. */
kono
parents:
diff changeset
3214 if (width == 0)
kono
parents:
diff changeset
3215 return 0;
kono
parents:
diff changeset
3216
kono
parents:
diff changeset
3217 unsigned int start = bitpos / HOST_BITS_PER_WIDE_INT;
kono
parents:
diff changeset
3218 unsigned int shift = bitpos % HOST_BITS_PER_WIDE_INT;
kono
parents:
diff changeset
3219 unsigned HOST_WIDE_INT res = xi.elt (start);
kono
parents:
diff changeset
3220 res >>= shift;
kono
parents:
diff changeset
3221 if (shift + width > HOST_BITS_PER_WIDE_INT)
kono
parents:
diff changeset
3222 {
kono
parents:
diff changeset
3223 unsigned HOST_WIDE_INT upper = xi.elt (start + 1);
kono
parents:
diff changeset
3224 res |= upper << (-shift % HOST_BITS_PER_WIDE_INT);
kono
parents:
diff changeset
3225 }
kono
parents:
diff changeset
3226 return zext_hwi (res, width);
kono
parents:
diff changeset
3227 }
kono
parents:
diff changeset
3228
kono
parents:
diff changeset
3229 /* Return the minimum precision needed to store X with sign SGN. */
kono
parents:
diff changeset
3230 template <typename T>
kono
parents:
diff changeset
3231 inline unsigned int
kono
parents:
diff changeset
3232 wi::min_precision (const T &x, signop sgn)
kono
parents:
diff changeset
3233 {
kono
parents:
diff changeset
3234 if (sgn == SIGNED)
kono
parents:
diff changeset
3235 return get_precision (x) - clrsb (x);
kono
parents:
diff changeset
3236 else
kono
parents:
diff changeset
3237 return get_precision (x) - clz (x);
kono
parents:
diff changeset
3238 }
kono
parents:
diff changeset
3239
kono
parents:
diff changeset
3240 #define SIGNED_BINARY_PREDICATE(OP, F) \
kono
parents:
diff changeset
3241 template <typename T1, typename T2> \
kono
parents:
diff changeset
3242 inline WI_SIGNED_BINARY_PREDICATE_RESULT (T1, T2) \
kono
parents:
diff changeset
3243 OP (const T1 &x, const T2 &y) \
kono
parents:
diff changeset
3244 { \
kono
parents:
diff changeset
3245 return wi::F (x, y); \
kono
parents:
diff changeset
3246 }
kono
parents:
diff changeset
3247
kono
parents:
diff changeset
3248 SIGNED_BINARY_PREDICATE (operator <, lts_p)
kono
parents:
diff changeset
3249 SIGNED_BINARY_PREDICATE (operator <=, les_p)
kono
parents:
diff changeset
3250 SIGNED_BINARY_PREDICATE (operator >, gts_p)
kono
parents:
diff changeset
3251 SIGNED_BINARY_PREDICATE (operator >=, ges_p)
kono
parents:
diff changeset
3252
kono
parents:
diff changeset
3253 #undef SIGNED_BINARY_PREDICATE
kono
parents:
diff changeset
3254
kono
parents:
diff changeset
3255 #define UNARY_OPERATOR(OP, F) \
kono
parents:
diff changeset
3256 template<typename T> \
kono
parents:
diff changeset
3257 WI_UNARY_RESULT (generic_wide_int<T>) \
kono
parents:
diff changeset
3258 OP (const generic_wide_int<T> &x) \
kono
parents:
diff changeset
3259 { \
kono
parents:
diff changeset
3260 return wi::F (x); \
kono
parents:
diff changeset
3261 }
kono
parents:
diff changeset
3262
kono
parents:
diff changeset
3263 #define BINARY_PREDICATE(OP, F) \
kono
parents:
diff changeset
3264 template<typename T1, typename T2> \
kono
parents:
diff changeset
3265 WI_BINARY_PREDICATE_RESULT (T1, T2) \
kono
parents:
diff changeset
3266 OP (const T1 &x, const T2 &y) \
kono
parents:
diff changeset
3267 { \
kono
parents:
diff changeset
3268 return wi::F (x, y); \
kono
parents:
diff changeset
3269 }
kono
parents:
diff changeset
3270
kono
parents:
diff changeset
3271 #define BINARY_OPERATOR(OP, F) \
kono
parents:
diff changeset
3272 template<typename T1, typename T2> \
kono
parents:
diff changeset
3273 WI_BINARY_OPERATOR_RESULT (T1, T2) \
kono
parents:
diff changeset
3274 OP (const T1 &x, const T2 &y) \
kono
parents:
diff changeset
3275 { \
kono
parents:
diff changeset
3276 return wi::F (x, y); \
kono
parents:
diff changeset
3277 }
kono
parents:
diff changeset
3278
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3279 #define SHIFT_OPERATOR(OP, F) \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3280 template<typename T1, typename T2> \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3281 WI_BINARY_OPERATOR_RESULT (T1, T1) \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3282 OP (const T1 &x, const T2 &y) \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3283 { \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3284 return wi::F (x, y); \
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3285 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3286
111
kono
parents:
diff changeset
3287 UNARY_OPERATOR (operator ~, bit_not)
kono
parents:
diff changeset
3288 UNARY_OPERATOR (operator -, neg)
kono
parents:
diff changeset
3289 BINARY_PREDICATE (operator ==, eq_p)
kono
parents:
diff changeset
3290 BINARY_PREDICATE (operator !=, ne_p)
kono
parents:
diff changeset
3291 BINARY_OPERATOR (operator &, bit_and)
kono
parents:
diff changeset
3292 BINARY_OPERATOR (operator |, bit_or)
kono
parents:
diff changeset
3293 BINARY_OPERATOR (operator ^, bit_xor)
kono
parents:
diff changeset
3294 BINARY_OPERATOR (operator +, add)
kono
parents:
diff changeset
3295 BINARY_OPERATOR (operator -, sub)
kono
parents:
diff changeset
3296 BINARY_OPERATOR (operator *, mul)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3297 SHIFT_OPERATOR (operator <<, lshift)
111
kono
parents:
diff changeset
3298
kono
parents:
diff changeset
3299 #undef UNARY_OPERATOR
kono
parents:
diff changeset
3300 #undef BINARY_PREDICATE
kono
parents:
diff changeset
3301 #undef BINARY_OPERATOR
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3302 #undef SHIFT_OPERATOR
111
kono
parents:
diff changeset
3303
kono
parents:
diff changeset
3304 template <typename T1, typename T2>
kono
parents:
diff changeset
3305 inline WI_SIGNED_SHIFT_RESULT (T1, T2)
kono
parents:
diff changeset
3306 operator >> (const T1 &x, const T2 &y)
kono
parents:
diff changeset
3307 {
kono
parents:
diff changeset
3308 return wi::arshift (x, y);
kono
parents:
diff changeset
3309 }
kono
parents:
diff changeset
3310
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3311 template <typename T1, typename T2>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3312 inline WI_SIGNED_SHIFT_RESULT (T1, T2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3313 operator / (const T1 &x, const T2 &y)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3314 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3315 return wi::sdiv_trunc (x, y);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3316 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3317
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3318 template <typename T1, typename T2>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3319 inline WI_SIGNED_SHIFT_RESULT (T1, T2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3320 operator % (const T1 &x, const T2 &y)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3321 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3322 return wi::smod_trunc (x, y);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3323 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3324
111
kono
parents:
diff changeset
3325 template<typename T>
kono
parents:
diff changeset
3326 void
kono
parents:
diff changeset
3327 gt_ggc_mx (generic_wide_int <T> *)
kono
parents:
diff changeset
3328 {
kono
parents:
diff changeset
3329 }
kono
parents:
diff changeset
3330
kono
parents:
diff changeset
3331 template<typename T>
kono
parents:
diff changeset
3332 void
kono
parents:
diff changeset
3333 gt_pch_nx (generic_wide_int <T> *)
kono
parents:
diff changeset
3334 {
kono
parents:
diff changeset
3335 }
kono
parents:
diff changeset
3336
kono
parents:
diff changeset
3337 template<typename T>
kono
parents:
diff changeset
3338 void
kono
parents:
diff changeset
3339 gt_pch_nx (generic_wide_int <T> *, void (*) (void *, void *), void *)
kono
parents:
diff changeset
3340 {
kono
parents:
diff changeset
3341 }
kono
parents:
diff changeset
3342
kono
parents:
diff changeset
3343 template<int N>
kono
parents:
diff changeset
3344 void
kono
parents:
diff changeset
3345 gt_ggc_mx (trailing_wide_ints <N> *)
kono
parents:
diff changeset
3346 {
kono
parents:
diff changeset
3347 }
kono
parents:
diff changeset
3348
kono
parents:
diff changeset
3349 template<int N>
kono
parents:
diff changeset
3350 void
kono
parents:
diff changeset
3351 gt_pch_nx (trailing_wide_ints <N> *)
kono
parents:
diff changeset
3352 {
kono
parents:
diff changeset
3353 }
kono
parents:
diff changeset
3354
kono
parents:
diff changeset
3355 template<int N>
kono
parents:
diff changeset
3356 void
kono
parents:
diff changeset
3357 gt_pch_nx (trailing_wide_ints <N> *, void (*) (void *, void *), void *)
kono
parents:
diff changeset
3358 {
kono
parents:
diff changeset
3359 }
kono
parents:
diff changeset
3360
kono
parents:
diff changeset
3361 namespace wi
kono
parents:
diff changeset
3362 {
kono
parents:
diff changeset
3363 /* Used for overloaded functions in which the only other acceptable
kono
parents:
diff changeset
3364 scalar type is a pointer. It stops a plain 0 from being treated
kono
parents:
diff changeset
3365 as a null pointer. */
kono
parents:
diff changeset
3366 struct never_used1 {};
kono
parents:
diff changeset
3367 struct never_used2 {};
kono
parents:
diff changeset
3368
kono
parents:
diff changeset
3369 wide_int min_value (unsigned int, signop);
kono
parents:
diff changeset
3370 wide_int min_value (never_used1 *);
kono
parents:
diff changeset
3371 wide_int min_value (never_used2 *);
kono
parents:
diff changeset
3372 wide_int max_value (unsigned int, signop);
kono
parents:
diff changeset
3373 wide_int max_value (never_used1 *);
kono
parents:
diff changeset
3374 wide_int max_value (never_used2 *);
kono
parents:
diff changeset
3375
kono
parents:
diff changeset
3376 /* FIXME: this is target dependent, so should be elsewhere.
kono
parents:
diff changeset
3377 It also seems to assume that CHAR_BIT == BITS_PER_UNIT. */
kono
parents:
diff changeset
3378 wide_int from_buffer (const unsigned char *, unsigned int);
kono
parents:
diff changeset
3379
kono
parents:
diff changeset
3380 #ifndef GENERATOR_FILE
kono
parents:
diff changeset
3381 void to_mpz (const wide_int_ref &, mpz_t, signop);
kono
parents:
diff changeset
3382 #endif
kono
parents:
diff changeset
3383
kono
parents:
diff changeset
3384 wide_int mask (unsigned int, bool, unsigned int);
kono
parents:
diff changeset
3385 wide_int shifted_mask (unsigned int, unsigned int, bool, unsigned int);
kono
parents:
diff changeset
3386 wide_int set_bit_in_zero (unsigned int, unsigned int);
kono
parents:
diff changeset
3387 wide_int insert (const wide_int &x, const wide_int &y, unsigned int,
kono
parents:
diff changeset
3388 unsigned int);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3389 wide_int round_down_for_mask (const wide_int &, const wide_int &);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3390 wide_int round_up_for_mask (const wide_int &, const wide_int &);
111
kono
parents:
diff changeset
3391
kono
parents:
diff changeset
3392 template <typename T>
kono
parents:
diff changeset
3393 T mask (unsigned int, bool);
kono
parents:
diff changeset
3394
kono
parents:
diff changeset
3395 template <typename T>
kono
parents:
diff changeset
3396 T shifted_mask (unsigned int, unsigned int, bool);
kono
parents:
diff changeset
3397
kono
parents:
diff changeset
3398 template <typename T>
kono
parents:
diff changeset
3399 T set_bit_in_zero (unsigned int);
kono
parents:
diff changeset
3400
kono
parents:
diff changeset
3401 unsigned int mask (HOST_WIDE_INT *, unsigned int, bool, unsigned int);
kono
parents:
diff changeset
3402 unsigned int shifted_mask (HOST_WIDE_INT *, unsigned int, unsigned int,
kono
parents:
diff changeset
3403 bool, unsigned int);
kono
parents:
diff changeset
3404 unsigned int from_array (HOST_WIDE_INT *, const HOST_WIDE_INT *,
kono
parents:
diff changeset
3405 unsigned int, unsigned int, bool);
kono
parents:
diff changeset
3406 }
kono
parents:
diff changeset
3407
kono
parents:
diff changeset
3408 /* Return a PRECISION-bit integer in which the low WIDTH bits are set
kono
parents:
diff changeset
3409 and the other bits are clear, or the inverse if NEGATE_P. */
kono
parents:
diff changeset
3410 inline wide_int
kono
parents:
diff changeset
3411 wi::mask (unsigned int width, bool negate_p, unsigned int precision)
kono
parents:
diff changeset
3412 {
kono
parents:
diff changeset
3413 wide_int result = wide_int::create (precision);
kono
parents:
diff changeset
3414 result.set_len (mask (result.write_val (), width, negate_p, precision));
kono
parents:
diff changeset
3415 return result;
kono
parents:
diff changeset
3416 }
kono
parents:
diff changeset
3417
kono
parents:
diff changeset
3418 /* Return a PRECISION-bit integer in which the low START bits are clear,
kono
parents:
diff changeset
3419 the next WIDTH bits are set, and the other bits are clear,
kono
parents:
diff changeset
3420 or the inverse if NEGATE_P. */
kono
parents:
diff changeset
3421 inline wide_int
kono
parents:
diff changeset
3422 wi::shifted_mask (unsigned int start, unsigned int width, bool negate_p,
kono
parents:
diff changeset
3423 unsigned int precision)
kono
parents:
diff changeset
3424 {
kono
parents:
diff changeset
3425 wide_int result = wide_int::create (precision);
kono
parents:
diff changeset
3426 result.set_len (shifted_mask (result.write_val (), start, width, negate_p,
kono
parents:
diff changeset
3427 precision));
kono
parents:
diff changeset
3428 return result;
kono
parents:
diff changeset
3429 }
kono
parents:
diff changeset
3430
kono
parents:
diff changeset
3431 /* Return a PRECISION-bit integer in which bit BIT is set and all the
kono
parents:
diff changeset
3432 others are clear. */
kono
parents:
diff changeset
3433 inline wide_int
kono
parents:
diff changeset
3434 wi::set_bit_in_zero (unsigned int bit, unsigned int precision)
kono
parents:
diff changeset
3435 {
kono
parents:
diff changeset
3436 return shifted_mask (bit, 1, false, precision);
kono
parents:
diff changeset
3437 }
kono
parents:
diff changeset
3438
kono
parents:
diff changeset
3439 /* Return an integer of type T in which the low WIDTH bits are set
kono
parents:
diff changeset
3440 and the other bits are clear, or the inverse if NEGATE_P. */
kono
parents:
diff changeset
3441 template <typename T>
kono
parents:
diff changeset
3442 inline T
kono
parents:
diff changeset
3443 wi::mask (unsigned int width, bool negate_p)
kono
parents:
diff changeset
3444 {
kono
parents:
diff changeset
3445 STATIC_ASSERT (wi::int_traits<T>::precision);
kono
parents:
diff changeset
3446 T result;
kono
parents:
diff changeset
3447 result.set_len (mask (result.write_val (), width, negate_p,
kono
parents:
diff changeset
3448 wi::int_traits <T>::precision));
kono
parents:
diff changeset
3449 return result;
kono
parents:
diff changeset
3450 }
kono
parents:
diff changeset
3451
kono
parents:
diff changeset
3452 /* Return an integer of type T in which the low START bits are clear,
kono
parents:
diff changeset
3453 the next WIDTH bits are set, and the other bits are clear, or the
kono
parents:
diff changeset
3454 inverse if NEGATE_P. */
kono
parents:
diff changeset
3455 template <typename T>
kono
parents:
diff changeset
3456 inline T
kono
parents:
diff changeset
3457 wi::shifted_mask (unsigned int start, unsigned int width, bool negate_p)
kono
parents:
diff changeset
3458 {
kono
parents:
diff changeset
3459 STATIC_ASSERT (wi::int_traits<T>::precision);
kono
parents:
diff changeset
3460 T result;
kono
parents:
diff changeset
3461 result.set_len (shifted_mask (result.write_val (), start, width,
kono
parents:
diff changeset
3462 negate_p,
kono
parents:
diff changeset
3463 wi::int_traits <T>::precision));
kono
parents:
diff changeset
3464 return result;
kono
parents:
diff changeset
3465 }
kono
parents:
diff changeset
3466
kono
parents:
diff changeset
3467 /* Return an integer of type T in which bit BIT is set and all the
kono
parents:
diff changeset
3468 others are clear. */
kono
parents:
diff changeset
3469 template <typename T>
kono
parents:
diff changeset
3470 inline T
kono
parents:
diff changeset
3471 wi::set_bit_in_zero (unsigned int bit)
kono
parents:
diff changeset
3472 {
kono
parents:
diff changeset
3473 return shifted_mask <T> (bit, 1, false);
kono
parents:
diff changeset
3474 }
kono
parents:
diff changeset
3475
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3476 /* Accumulate a set of overflows into OVERFLOW. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3477
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3478 static inline void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3479 wi::accumulate_overflow (wi::overflow_type &overflow,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3480 wi::overflow_type suboverflow)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3481 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3482 if (!suboverflow)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3483 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3484 if (!overflow)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3485 overflow = suboverflow;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3486 else if (overflow != suboverflow)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3487 overflow = wi::OVF_UNKNOWN;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3488 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3489
111
kono
parents:
diff changeset
3490 #endif /* WIDE_INT_H */