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