|
PPL
0.12.1
|
00001 /* Bit_Row class implementation (non-inline functions). 00002 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00003 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00004 00005 This file is part of the Parma Polyhedra Library (PPL). 00006 00007 The PPL is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 The PPL is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software Foundation, 00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00020 00021 For the most up-to-date information see the Parma Polyhedra Library 00022 site: http://bugseng.com/products/ppl/ . */ 00023 00024 #include "ppl-config.h" 00025 #include "Bit_Row.defs.hh" 00026 #include "assert.hh" 00027 #include "C_Integer.hh" 00028 00029 namespace PPL = Parma_Polyhedra_Library; 00030 00031 unsigned long 00032 PPL::Bit_Row::first() const { 00033 const mp_size_t vec_size = vec->_mp_size; 00034 PPL_ASSERT(vec_size >= 0); 00035 mp_srcptr p = vec->_mp_d; 00036 for (mp_size_t li = 0; li < vec_size; ++li, ++p) { 00037 const mp_limb_t limb = *p; 00038 if (limb != 0) 00039 return static_cast<unsigned long>(li) * PPL_BITS_PER_GMP_LIMB 00040 + Implementation::first_one(limb); 00041 } 00042 return C_Integer<unsigned long>::max; 00043 } 00044 00045 unsigned long 00046 PPL::Bit_Row::next(unsigned long position) const { 00047 ++position; 00048 00049 // The alternative implementation using the mpz_scan1() function 00050 // of GMP was measured to be slower that ours. Here it is, in 00051 // case mpz_scan1() is improved. 00052 // 00053 // <CODE> 00054 // unsigned long r = mpz_scan1(vec, position); 00055 // return (r == C_Integer<unsigned long>::max) ? -1 : r; 00056 // </CODE> 00057 00058 const unsigned long uli = position / PPL_BITS_PER_GMP_LIMB; 00059 mp_size_t li = static_cast<mp_size_t>(uli); 00060 const mp_size_t vec_size = vec->_mp_size; 00061 PPL_ASSERT(vec_size >= 0); 00062 if (li >= vec_size) 00063 return C_Integer<unsigned long>::max; 00064 00065 // Get the first limb. 00066 mp_srcptr p = vec->_mp_d + li; 00067 00068 // Mask off any bits before `position' in the first limb. 00069 mp_limb_t limb 00070 = *p & ((~static_cast<mp_limb_t>(0)) << (position % PPL_BITS_PER_GMP_LIMB)); 00071 00072 while (true) { 00073 if (limb != 0) 00074 return static_cast<unsigned long>(li) * PPL_BITS_PER_GMP_LIMB 00075 + Implementation::first_one(limb); 00076 ++li; 00077 if (li == vec_size) 00078 break; 00079 ++p; 00080 limb = *p; 00081 } 00082 return C_Integer<unsigned long>::max; 00083 } 00084 00085 unsigned long 00086 PPL::Bit_Row::last() const { 00087 mp_size_t li = vec->_mp_size; 00088 PPL_ASSERT(li >= 0); 00089 if (li == 0) 00090 return C_Integer<unsigned long>::max; 00091 --li; 00092 const mp_srcptr p = vec->_mp_d + li; 00093 const mp_limb_t limb = *p; 00094 PPL_ASSERT(limb != 0); 00095 return static_cast<unsigned long>(li) * PPL_BITS_PER_GMP_LIMB 00096 + Implementation::last_one(limb); 00097 } 00098 00099 unsigned long 00100 PPL::Bit_Row::prev(unsigned long position) const { 00101 if (position == 0) 00102 return C_Integer<unsigned long>::max; 00103 00104 --position; 00105 00106 const mp_size_t vec_size = vec->_mp_size; 00107 PPL_ASSERT(vec_size > 0); 00108 const unsigned long uli = position / PPL_BITS_PER_GMP_LIMB; 00109 mp_size_t li = static_cast<mp_size_t>(uli); 00110 00111 mp_limb_t limb; 00112 mp_srcptr p = vec->_mp_d; 00113 00114 // Get the first limb. 00115 if (li >= vec_size) { 00116 li = vec_size - 1; 00117 p += li; 00118 limb = *p; 00119 } 00120 else { 00121 const mp_limb_t mask 00122 = (~static_cast<mp_limb_t>(0)) 00123 >> (PPL_BITS_PER_GMP_LIMB - 1U - position % PPL_BITS_PER_GMP_LIMB); 00124 p += li; 00125 limb = *p & mask; 00126 } 00127 00128 while (true) { 00129 if (limb != 0) 00130 return static_cast<unsigned long>(li) * PPL_BITS_PER_GMP_LIMB 00131 + Implementation::last_one(limb); 00132 if (li == 0) 00133 break; 00134 --li; 00135 --p; 00136 limb = *p; 00137 } 00138 return C_Integer<unsigned long>::max; 00139 } 00140 00141 bool 00142 PPL::Bit_Row::operator[](const unsigned long k) const { 00143 const mp_size_t vec_size = vec->_mp_size; 00144 PPL_ASSERT(vec_size >= 0); 00145 00146 unsigned long i = k / static_cast<unsigned long>(GMP_NUMB_BITS); 00147 if (i >= static_cast<unsigned long>(vec_size)) 00148 return false; 00149 00150 mp_limb_t limb = *(vec->_mp_d + i); 00151 return ((limb >> (k % static_cast<unsigned long>(GMP_NUMB_BITS))) & 1U) != 0; 00152 } 00153 00154 void 00155 PPL::Bit_Row::set_until(unsigned long k) { 00156 // FIXME, TODO: this is an inefficient implementation. 00157 while (k-- > 0) 00158 mpz_setbit(vec, k); 00159 } 00160 00162 int 00163 PPL::compare(const Bit_Row& x, const Bit_Row& y) { 00164 const mp_size_t x_size = x.vec->_mp_size; 00165 PPL_ASSERT(x_size >= 0); 00166 const mp_size_t y_size = y.vec->_mp_size; 00167 PPL_ASSERT(y_size >= 0); 00168 mp_size_t size = ((x_size > y_size) ? y_size : x_size); 00169 mp_srcptr xp = x.vec->_mp_d; 00170 mp_srcptr yp = y.vec->_mp_d; 00171 while (size > 0) { 00172 const mp_limb_t xl = *xp; 00173 const mp_limb_t yl = *yp; 00174 if (xl != yl) { 00175 // Get the ones where they are different. 00176 const mp_limb_t diff = xl ^ yl; 00177 // First bit that is different. 00178 const mp_limb_t mask = diff & ~(diff-1); 00179 return ((xl & mask) != 0) ? 1 : -1; 00180 } 00181 ++xp; 00182 ++yp; 00183 --size; 00184 } 00185 return (x_size == y_size) ? 0 : ((x_size > y_size) ? 1 : -1); 00186 } 00187 00189 bool 00190 PPL::subset_or_equal(const Bit_Row& x, const Bit_Row& y) { 00191 mp_size_t x_size = x.vec->_mp_size; 00192 PPL_ASSERT(x_size >= 0); 00193 mp_size_t y_size = y.vec->_mp_size; 00194 PPL_ASSERT(y_size >= 0); 00195 if (x_size > y_size) 00196 return false; 00197 mp_srcptr xp = x.vec->_mp_d; 00198 mp_srcptr yp = y.vec->_mp_d; 00199 while (x_size > 0) { 00200 if ((*xp & ~*yp) != 0) 00201 return false; 00202 ++xp; 00203 ++yp; 00204 --x_size; 00205 } 00206 return true; 00207 } 00208 00210 bool 00211 PPL::subset_or_equal(const Bit_Row& x, const Bit_Row& y, 00212 bool& strict_subset) { 00213 mp_size_t x_size = x.vec->_mp_size; 00214 PPL_ASSERT(x_size >= 0); 00215 mp_size_t y_size = y.vec->_mp_size; 00216 PPL_ASSERT(y_size >= 0); 00217 if (x_size > y_size) 00218 return false; 00219 mp_srcptr xp = x.vec->_mp_d; 00220 mp_srcptr yp = y.vec->_mp_d; 00221 strict_subset = (x_size < y_size); 00222 mp_limb_t xl; 00223 mp_limb_t yl; 00224 if (strict_subset) { 00225 while (x_size > 0) { 00226 xl = *xp; 00227 yl = *yp; 00228 if ((xl & ~yl) != 0) 00229 return false; 00230 strict_subset_next: 00231 ++xp; 00232 ++yp; 00233 --x_size; 00234 } 00235 } 00236 else { 00237 while (x_size > 0) { 00238 xl = *xp; 00239 yl = *yp; 00240 if (xl != yl) { 00241 if ((xl & ~yl) != 0) 00242 return false; 00243 strict_subset = true; 00244 goto strict_subset_next; 00245 } 00246 ++xp; 00247 ++yp; 00248 --x_size; 00249 } 00250 } 00251 return true; 00252 } 00253 00255 bool 00256 PPL::strict_subset(const Bit_Row& x, const Bit_Row& y) { 00257 mp_size_t x_size = x.vec->_mp_size; 00258 PPL_ASSERT(x_size >= 0); 00259 mp_size_t y_size = y.vec->_mp_size; 00260 PPL_ASSERT(y_size >= 0); 00261 if (x_size > y_size) 00262 return false; 00263 bool different = (x_size < y_size); 00264 mp_srcptr xp = x.vec->_mp_d; 00265 mp_srcptr yp = y.vec->_mp_d; 00266 while (x_size > 0) { 00267 const mp_limb_t xl = *xp; 00268 const mp_limb_t yl = *yp; 00269 if ((xl & ~yl) != 0) 00270 return false; 00271 if (!different && xl != yl) 00272 different = true; 00273 ++xp; 00274 ++yp; 00275 --x_size; 00276 } 00277 return different; 00278 } 00279 00281 bool 00282 PPL::operator==(const Bit_Row& x, const Bit_Row& y) { 00283 const mp_size_t x_vec_size = x.vec->_mp_size; 00284 PPL_ASSERT(x_vec_size >= 0); 00285 const mp_size_t y_vec_size = y.vec->_mp_size; 00286 PPL_ASSERT(y_vec_size >= 0); 00287 00288 if (x_vec_size != y_vec_size) 00289 return false; 00290 00291 return mpn_cmp(x.vec->_mp_d, y.vec->_mp_d, x_vec_size) == 0; 00292 } 00293 00295 bool 00296 PPL::operator!=(const Bit_Row& x, const Bit_Row& y) { 00297 const mp_size_t x_vec_size = x.vec->_mp_size; 00298 PPL_ASSERT(x_vec_size >= 0); 00299 const mp_size_t y_vec_size = y.vec->_mp_size; 00300 PPL_ASSERT(y_vec_size >= 0); 00301 00302 if (x_vec_size != y_vec_size) 00303 return true; 00304 00305 return mpn_cmp(x.vec->_mp_d, y.vec->_mp_d, x_vec_size) != 0; 00306 } 00307 00308 bool 00309 PPL::Bit_Row::OK() const { 00310 const mp_size_t vec_size = vec->_mp_size; 00311 const mp_size_t vec_alloc = vec->_mp_alloc; 00312 return vec_size >= 0 00313 && vec_alloc >= vec_size 00314 && (vec_size == 0 || mpz_getlimbn(vec, vec_size-1) != 0); 00315 } 00316 00317 void 00318 PPL::Bit_Row::union_helper(const Bit_Row& y, const Bit_Row& z) { 00319 mp_size_t y_size = y.vec->_mp_size; 00320 mp_size_t z_size = z.vec->_mp_size; 00321 PPL_ASSERT(y_size <= z_size); 00322 PPL_ASSERT(vec->_mp_alloc >= z_size); 00323 vec->_mp_size = z.vec->_mp_size; 00324 mp_srcptr yp = y.vec->_mp_d; 00325 mp_srcptr zp = z.vec->_mp_d; 00326 mp_ptr p = vec->_mp_d; 00327 z_size -= y_size; 00328 while (y_size > 0) { 00329 *p = *yp | * zp; 00330 ++yp; 00331 ++zp; 00332 ++p; 00333 --y_size; 00334 } 00335 while (z_size > 0) { 00336 *p = *zp; 00337 ++zp; 00338 ++p; 00339 --z_size; 00340 } 00341 }