1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/* Operations on HOST_WIDE_INT.
Copyright (C) 1987-2018 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#if GCC_VERSION < 3004
/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
and exact_log2 are defined as inline functions in hwint.h
if GCC_VERSION >= 3004.
The definitions here are used for older versions of GCC and
non-GCC bootstrap compilers. */
/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
If X is 0, return -1. */
int
floor_log2 (unsigned HOST_WIDE_INT x)
{
int t = 0;
if (x == 0)
return -1;
if (HOST_BITS_PER_WIDE_INT > 64)
if (x >= HOST_WIDE_INT_1U << (t + 64))
t += 64;
if (HOST_BITS_PER_WIDE_INT > 32)
if (x >= HOST_WIDE_INT_1U << (t + 32))
t += 32;
if (x >= HOST_WIDE_INT_1U << (t + 16))
t += 16;
if (x >= HOST_WIDE_INT_1U << (t + 8))
t += 8;
if (x >= HOST_WIDE_INT_1U << (t + 4))
t += 4;
if (x >= HOST_WIDE_INT_1U << (t + 2))
t += 2;
if (x >= HOST_WIDE_INT_1U << (t + 1))
t += 1;
return t;
}
/* Given X, an unsigned number, return the largest Y such that 2**Y >= X. */
int
ceil_log2 (unsigned HOST_WIDE_INT x)
{
return floor_log2 (x - 1) + 1;
}
/* Return the logarithm of X, base 2, considering X unsigned,
if X is a power of 2. Otherwise, returns -1. */
int
exact_log2 (unsigned HOST_WIDE_INT x)
{
if (!pow2p_hwi (x))
return -1;
return floor_log2 (x);
}
/* Given X, an unsigned number, return the number of least significant bits
that are zero. When X == 0, the result is the word size. */
int
ctz_hwi (unsigned HOST_WIDE_INT x)
{
return x ? floor_log2 (least_bit_hwi (x)) : HOST_BITS_PER_WIDE_INT;
}
/* Similarly for most significant bits. */
int
clz_hwi (unsigned HOST_WIDE_INT x)
{
return HOST_BITS_PER_WIDE_INT - 1 - floor_log2 (x);
}
/* Similar to ctz_hwi, except that the least significant bit is numbered
starting from 1, and X == 0 yields 0. */
int
ffs_hwi (unsigned HOST_WIDE_INT x)
{
return 1 + floor_log2 (least_bit_hwi (x));
}
/* Return the number of set bits in X. */
int
popcount_hwi (unsigned HOST_WIDE_INT x)
{
int i, ret = 0;
size_t bits = sizeof (x) * CHAR_BIT;
for (i = 0; i < bits; i += 1)
{
ret += x & 1;
x >>= 1;
}
return ret;
}
#endif /* GCC_VERSION < 3004 */
/* Compute the greatest common divisor of two numbers A and B using
Euclid's algorithm. */
HOST_WIDE_INT
gcd (HOST_WIDE_INT a, HOST_WIDE_INT b)
{
HOST_WIDE_INT x, y, z;
x = abs_hwi (a);
y = abs_hwi (b);
while (x > 0)
{
z = y % x;
y = x;
x = z;
}
return y;
}
/* For X and Y positive integers, return X multiplied by Y and check
that the result does not overflow. */
HOST_WIDE_INT
pos_mul_hwi (HOST_WIDE_INT x, HOST_WIDE_INT y)
{
if (x != 0)
gcc_checking_assert ((HOST_WIDE_INT_MAX) / x >= y);
return x * y;
}
/* Return X multiplied by Y and check that the result does not
overflow. */
HOST_WIDE_INT
mul_hwi (HOST_WIDE_INT x, HOST_WIDE_INT y)
{
gcc_checking_assert (x != HOST_WIDE_INT_MIN
&& y != HOST_WIDE_INT_MIN);
if (x >= 0)
{
if (y >= 0)
return pos_mul_hwi (x, y);
return -pos_mul_hwi (x, -y);
}
if (y >= 0)
return -pos_mul_hwi (-x, y);
return pos_mul_hwi (-x, -y);
}
/* Compute the least common multiple of two numbers A and B . */
HOST_WIDE_INT
least_common_multiple (HOST_WIDE_INT a, HOST_WIDE_INT b)
{
return mul_hwi (abs_hwi (a) / gcd (a, b), abs_hwi (b));
}
|