1 /* Bit_Row class implementation: inline functions.
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #ifndef PPL_Bit_Row_inlines_hh
25 #define PPL_Bit_Row_inlines_hh 1
26
27 #include "compiler.hh"
28 #include "globals_defs.hh"
29 #include "assertions.hh"
30
31 // For the declaration of ffs(3).
32 #if defined(PPL_HAVE_STRINGS_H)
33 # include <strings.h>
34 #elif defined(PPL_HAVE_STRING_H)
35 # include <string.h>
36 #endif
37
38 #define PPL_BITS_PER_GMP_LIMB sizeof_to_bits(PPL_SIZEOF_MP_LIMB_T)
39
40 namespace Parma_Polyhedra_Library {
41
42 inline
Bit_Row()43 Bit_Row::Bit_Row() {
44 mpz_init(vec);
45 }
46
47 inline
Bit_Row(const Bit_Row & y)48 Bit_Row::Bit_Row(const Bit_Row& y) {
49 mpz_init_set(vec, y.vec);
50 }
51
52 inline
Bit_Row(const Bit_Row & y,const Bit_Row & z)53 Bit_Row::Bit_Row(const Bit_Row& y, const Bit_Row& z) {
54 const mp_size_t y_size = y.vec->_mp_size;
55 PPL_ASSERT(y_size >= 0);
56 const mp_size_t z_size = z.vec->_mp_size;
57 PPL_ASSERT(z_size >= 0);
58 if (y_size < z_size) {
59 PPL_ASSERT(static_cast<unsigned long>(z_size)
60 <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
61 mpz_init2(vec, static_cast<unsigned long>(z_size) * PPL_BITS_PER_GMP_LIMB);
62 union_helper(y, z);
63 }
64 else {
65 PPL_ASSERT(static_cast<unsigned long>(y_size)
66 <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
67 mpz_init2(vec, static_cast<unsigned long>(y_size) * PPL_BITS_PER_GMP_LIMB);
68 union_helper(z, y);
69 }
70 }
71
72 inline
~Bit_Row()73 Bit_Row::~Bit_Row() {
74 mpz_clear(vec);
75 }
76
77 inline Bit_Row&
operator =(const Bit_Row & y)78 Bit_Row::operator=(const Bit_Row& y) {
79 mpz_set(vec, y.vec);
80 return *this;
81 }
82
83 inline void
set(const unsigned long k)84 Bit_Row::set(const unsigned long k) {
85 mpz_setbit(vec, k);
86 }
87
88 inline void
clear(const unsigned long k)89 Bit_Row::clear(const unsigned long k) {
90 mpz_clrbit(vec, k);
91 }
92
93 inline void
clear_from(const unsigned long k)94 Bit_Row::clear_from(const unsigned long k) {
95 mpz_tdiv_r_2exp(vec, vec, k);
96 }
97
98 inline unsigned long
count_ones() const99 Bit_Row::count_ones() const {
100 const mp_size_t x_size = vec->_mp_size;
101 PPL_ASSERT(x_size >= 0);
102 return (x_size == 0) ? 0 : mpn_popcount(vec->_mp_d, x_size);
103 }
104
105 inline bool
empty() const106 Bit_Row::empty() const {
107 return mpz_sgn(vec) == 0;
108 }
109
110 inline void
m_swap(Bit_Row & y)111 Bit_Row::m_swap(Bit_Row& y) {
112 mpz_swap(vec, y.vec);
113 }
114
115 inline void
clear()116 Bit_Row::clear() {
117 mpz_set_ui(vec, 0UL);
118 }
119
120 inline memory_size_type
external_memory_in_bytes() const121 Bit_Row::external_memory_in_bytes() const {
122 return static_cast<memory_size_type>(vec[0]._mp_alloc) * PPL_SIZEOF_MP_LIMB_T;
123 }
124
125 inline memory_size_type
total_memory_in_bytes() const126 Bit_Row::total_memory_in_bytes() const {
127 return sizeof(*this) + external_memory_in_bytes();
128 }
129
130 inline void
union_assign(const Bit_Row & x,const Bit_Row & y)131 Bit_Row::union_assign(const Bit_Row& x, const Bit_Row& y) {
132 const mp_size_t x_size = x.vec->_mp_size;
133 PPL_ASSERT(x_size >= 0);
134 const mp_size_t y_size = y.vec->_mp_size;
135 PPL_ASSERT(y_size >= 0);
136 if (x_size < y_size) {
137 PPL_ASSERT(static_cast<unsigned long>(y_size)
138 <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
139 mpz_realloc2(vec, static_cast<unsigned long>(y_size) * PPL_BITS_PER_GMP_LIMB);
140 union_helper(x, y);
141 }
142 else {
143 PPL_ASSERT(static_cast<unsigned long>(x_size)
144 <= C_Integer<unsigned long>::max / PPL_BITS_PER_GMP_LIMB);
145 mpz_realloc2(vec, static_cast<unsigned long>(x_size) * PPL_BITS_PER_GMP_LIMB);
146 union_helper(y, x);
147 }
148 }
149
150 inline void
intersection_assign(const Bit_Row & x,const Bit_Row & y)151 Bit_Row::intersection_assign(const Bit_Row& x, const Bit_Row& y) {
152 mpz_and(vec, x.vec, y.vec);
153 }
154
155 inline void
difference_assign(const Bit_Row & x,const Bit_Row & y)156 Bit_Row::difference_assign(const Bit_Row& x, const Bit_Row& y) {
157 PPL_DIRTY_TEMP(mpz_class, complement_y);
158 mpz_com(complement_y.get_mpz_t(), y.vec);
159 mpz_and(vec, x.vec, complement_y.get_mpz_t());
160 }
161
162 namespace Implementation {
163
164 /*! \brief
165 Assuming \p u is nonzero, returns the index of the first set bit in \p u.
166 */
167 inline unsigned int
first_one(unsigned int u)168 first_one(unsigned int u) {
169 return ctz(u);
170 }
171
172 /*! \brief
173 Assuming \p ul is nonzero, returns the index of the first set bit in
174 \p ul.
175 */
176 inline unsigned int
first_one(unsigned long ul)177 first_one(unsigned long ul) {
178 return ctz(ul);
179 }
180
181 /*! \brief
182 Assuming \p ull is nonzero, returns the index of the first set bit in
183 \p ull.
184 */
185 inline unsigned int
first_one(unsigned long long ull)186 first_one(unsigned long long ull) {
187 return ctz(ull);
188 }
189
190 /*! \brief
191 Assuming \p u is nonzero, returns the index of the last set bit in \p u.
192 */
193 inline unsigned int
last_one(unsigned int u)194 last_one(unsigned int u) {
195 return static_cast<unsigned int>(sizeof_to_bits(sizeof(u)))
196 - 1U - clz(u);
197 }
198
199 /*! \brief
200 Assuming \p ul is nonzero, returns the index of the last set bit in
201 \p ul.
202 */
203 inline unsigned int
last_one(unsigned long ul)204 last_one(unsigned long ul) {
205 return static_cast<unsigned int>(sizeof_to_bits(sizeof(ul)))
206 - 1U - clz(ul);
207 }
208
209 /*! \brief
210 Assuming \p ull is nonzero, returns the index of the last set bit in
211 \p ull.
212 */
213 inline unsigned int
last_one(unsigned long long ull)214 last_one(unsigned long long ull) {
215 return static_cast<unsigned int>(sizeof_to_bits(sizeof(ull)))
216 - 1U - clz(ull);
217 }
218
219 } // namespace Implementation
220
221 /*! \relates Bit_Row */
222 inline void
swap(Bit_Row & x,Bit_Row & y)223 swap(Bit_Row& x, Bit_Row& y) {
224 x.m_swap(y);
225 }
226
227 /*! \relates Bit_Row */
228 inline void
iter_swap(std::vector<Bit_Row>::iterator x,std::vector<Bit_Row>::iterator y)229 iter_swap(std::vector<Bit_Row>::iterator x,
230 std::vector<Bit_Row>::iterator y) {
231 swap(*x, *y);
232 }
233
234 } // namespace Parma_Polyhedra_Library
235
236 #endif // !defined(PPL_Bit_Row_inlines_hh)
237