annotate gcc/wide-int.h @ 128:fe568345ddd5

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