dynamic_bitset.ipp 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238
  1. // -----------------------------------------------------------
  2. //
  3. // Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
  4. // Copyright (c) 2003-2006, 2008, 2025 Gennaro Prota
  5. // Copyright (c) 2014 Ahmed Charles
  6. //
  7. // Copyright (c) 2014 Glen Joseph Fernandes
  8. // (glenjofe@gmail.com)
  9. //
  10. // Copyright (c) 2014 Riccardo Marcangelo
  11. // Copyright (c) 2018 Evgeny Shulgin
  12. //
  13. // Distributed under the Boost Software License, Version 1.0.
  14. // (See accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. //
  17. // -----------------------------------------------------------
  18. #include "boost/assert.hpp"
  19. #include "boost/core/bit.hpp"
  20. #include "boost/core/no_exceptions_support.hpp"
  21. #include "boost/dynamic_bitset/detail/lowest_bit.hpp"
  22. #include "boost/functional/hash/hash.hpp"
  23. #include "boost/throw_exception.hpp"
  24. #include <algorithm>
  25. #include <climits>
  26. #include <istream>
  27. #include <locale>
  28. #include <ostream>
  29. #include <stdexcept>
  30. #include <utility>
  31. namespace boost {
  32. template< typename Block, typename AllocatorOrContainer >
  33. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  34. dynamic_bitset< Block, AllocatorOrContainer >::reference::reference( block_type & b, int pos )
  35. : m_block( b ), m_mask( ( BOOST_ASSERT( pos < bits_per_block ), block_type( 1 ) << pos ) )
  36. {
  37. }
  38. template< typename Block, typename AllocatorOrContainer >
  39. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >::reference::reference( const reference & other ) = default;
  40. template< typename Block, typename AllocatorOrContainer >
  41. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >::reference::
  42. operator bool() const
  43. {
  44. return ( m_block & m_mask ) != 0;
  45. }
  46. template< typename Block, typename AllocatorOrContainer >
  47. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  48. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator~() const
  49. {
  50. return ( m_block & m_mask ) == 0;
  51. }
  52. template< typename Block, typename AllocatorOrContainer >
  53. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  54. dynamic_bitset< Block, AllocatorOrContainer >::reference::flip()
  55. {
  56. do_flip();
  57. return *this;
  58. }
  59. template< typename Block, typename AllocatorOrContainer >
  60. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  61. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator=( bool x )
  62. {
  63. do_assign( x );
  64. return *this;
  65. }
  66. template< typename Block, typename AllocatorOrContainer >
  67. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  68. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator=( const reference & rhs )
  69. {
  70. do_assign( rhs );
  71. return *this;
  72. }
  73. template< typename Block, typename AllocatorOrContainer >
  74. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  75. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator|=( bool x )
  76. {
  77. if ( x ) {
  78. do_set();
  79. }
  80. return *this;
  81. }
  82. template< typename Block, typename AllocatorOrContainer >
  83. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  84. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator&=( bool x )
  85. {
  86. if ( ! x ) {
  87. do_reset();
  88. }
  89. return *this;
  90. }
  91. template< typename Block, typename AllocatorOrContainer >
  92. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  93. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator^=( bool x )
  94. {
  95. if ( x ) {
  96. do_flip();
  97. }
  98. return *this;
  99. }
  100. template< typename Block, typename AllocatorOrContainer >
  101. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference &
  102. dynamic_bitset< Block, AllocatorOrContainer >::reference::operator-=( bool x )
  103. {
  104. if ( x ) {
  105. do_reset();
  106. }
  107. return *this;
  108. }
  109. template< typename Block, typename AllocatorOrContainer >
  110. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  111. dynamic_bitset< Block, AllocatorOrContainer >::reference::do_set()
  112. {
  113. m_block |= m_mask;
  114. }
  115. template< typename Block, typename AllocatorOrContainer >
  116. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  117. dynamic_bitset< Block, AllocatorOrContainer >::reference::do_reset()
  118. {
  119. m_block &= ~m_mask;
  120. }
  121. template< typename Block, typename AllocatorOrContainer >
  122. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  123. dynamic_bitset< Block, AllocatorOrContainer >::reference::do_flip()
  124. {
  125. m_block ^= m_mask;
  126. }
  127. template< typename Block, typename AllocatorOrContainer >
  128. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  129. dynamic_bitset< Block, AllocatorOrContainer >::reference::do_assign( bool x )
  130. {
  131. if ( x ) {
  132. do_set();
  133. } else {
  134. do_reset();
  135. }
  136. }
  137. template< typename Iterator >
  138. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  139. bit_iterator_base< Iterator >::bit_iterator_base( Iterator block_iterator, int bit_index )
  140. : m_block_iterator( block_iterator )
  141. , m_bit_index( bit_index )
  142. {
  143. BOOST_ASSERT( 0 <= bit_index && bit_index < bits_per_block );
  144. }
  145. template< typename Iterator >
  146. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  147. bit_iterator_base< Iterator >::increment()
  148. {
  149. ++m_bit_index;
  150. if ( m_bit_index == bits_per_block ) {
  151. m_bit_index = 0;
  152. ++m_block_iterator;
  153. }
  154. }
  155. template< typename Iterator >
  156. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  157. bit_iterator_base< Iterator >::decrement()
  158. {
  159. --m_bit_index;
  160. if ( m_bit_index < 0 ) {
  161. m_bit_index = bits_per_block - 1;
  162. --m_block_iterator;
  163. }
  164. }
  165. template< typename Iterator >
  166. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  167. bit_iterator_base< Iterator >::add( typename Iterator::difference_type n )
  168. {
  169. typename Iterator::difference_type d = m_bit_index + n;
  170. m_block_iterator += d / bits_per_block;
  171. d %= bits_per_block;
  172. if ( d < 0 ) {
  173. d += bits_per_block;
  174. --m_block_iterator;
  175. }
  176. m_bit_index = static_cast< int >( d );
  177. }
  178. template< typename Iterator >
  179. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  180. operator==( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  181. {
  182. return lhs.m_block_iterator == rhs.m_block_iterator && lhs.m_bit_index == rhs.m_bit_index;
  183. }
  184. template< typename Iterator >
  185. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  186. operator!=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  187. {
  188. return ! ( lhs == rhs );
  189. }
  190. template< typename Iterator >
  191. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  192. operator<( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  193. {
  194. return lhs.m_block_iterator < rhs.m_block_iterator
  195. || ( lhs.m_block_iterator == rhs.m_block_iterator && lhs.m_bit_index < rhs.m_bit_index );
  196. }
  197. template< typename Iterator >
  198. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  199. operator<=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  200. {
  201. return ! ( rhs < lhs );
  202. }
  203. template< typename Iterator >
  204. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  205. operator>( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  206. {
  207. return rhs < lhs;
  208. }
  209. template< typename Iterator >
  210. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  211. operator>=( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  212. {
  213. return ! ( lhs < rhs );
  214. }
  215. template< typename Iterator >
  216. BOOST_DYNAMIC_BITSET_CONSTEXPR20 std::ptrdiff_t
  217. operator-( const bit_iterator_base< Iterator > & lhs, const bit_iterator_base< Iterator > & rhs )
  218. {
  219. return ( lhs.m_block_iterator - rhs.m_block_iterator ) * bit_iterator_base< Iterator >::bits_per_block
  220. + lhs.m_bit_index - rhs.m_bit_index;
  221. }
  222. template< typename DynamicBitset >
  223. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  224. bit_iterator< DynamicBitset >::bit_iterator()
  225. : bit_iterator_base< typename DynamicBitset::buffer_type::iterator >()
  226. {
  227. }
  228. template< typename DynamicBitset >
  229. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  230. bit_iterator< DynamicBitset >::bit_iterator( typename DynamicBitset::buffer_type::iterator block_iterator, int bit_index )
  231. : bit_iterator_base< typename DynamicBitset::buffer_type::iterator >( block_iterator, bit_index )
  232. {
  233. }
  234. template< typename DynamicBitset >
  235. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename DynamicBitset::reference
  236. bit_iterator< DynamicBitset >::operator*() const
  237. {
  238. return reference( *( this->m_block_iterator ), this->m_bit_index );
  239. }
  240. template< typename DynamicBitset >
  241. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset > &
  242. bit_iterator< DynamicBitset >::operator++()
  243. {
  244. this->increment();
  245. return *this;
  246. }
  247. template< typename DynamicBitset >
  248. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset >
  249. bit_iterator< DynamicBitset >::operator++( int )
  250. {
  251. bit_iterator temp = *this;
  252. this->increment();
  253. return temp;
  254. }
  255. template< typename DynamicBitset >
  256. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset > &
  257. bit_iterator< DynamicBitset >::operator--()
  258. {
  259. this->decrement();
  260. return *this;
  261. }
  262. template< typename DynamicBitset >
  263. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset >
  264. bit_iterator< DynamicBitset >::operator--( int )
  265. {
  266. bit_iterator temp = *this;
  267. this->decrement();
  268. return temp;
  269. }
  270. template< typename DynamicBitset >
  271. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset > &
  272. bit_iterator< DynamicBitset >::operator+=( difference_type n )
  273. {
  274. this->add( n );
  275. return *this;
  276. }
  277. template< typename DynamicBitset >
  278. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset > &
  279. bit_iterator< DynamicBitset >::operator-=( difference_type n )
  280. {
  281. this->add( -n );
  282. return *this;
  283. }
  284. template< typename DynamicBitset >
  285. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset >
  286. operator+( const bit_iterator< DynamicBitset > & it, typename bit_iterator< DynamicBitset >::difference_type n )
  287. {
  288. bit_iterator< DynamicBitset > temp = it;
  289. temp += n;
  290. return temp;
  291. }
  292. template< typename DynamicBitset >
  293. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset >
  294. operator+( typename bit_iterator< DynamicBitset >::difference_type n, const bit_iterator< DynamicBitset > & it )
  295. {
  296. return it + n;
  297. }
  298. template< typename DynamicBitset >
  299. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bit_iterator< DynamicBitset >
  300. operator-( const bit_iterator< DynamicBitset > & it, typename bit_iterator< DynamicBitset >::difference_type n )
  301. {
  302. bit_iterator< DynamicBitset > temp = it;
  303. temp -= n;
  304. return temp;
  305. }
  306. template< typename DynamicBitset >
  307. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename DynamicBitset::reference
  308. bit_iterator< DynamicBitset >::operator[]( difference_type n ) const
  309. {
  310. return *( *this + n );
  311. }
  312. template< typename DynamicBitset >
  313. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  314. const_bit_iterator< DynamicBitset >::const_bit_iterator( typename DynamicBitset::buffer_type::const_iterator block_iterator, int bit_index )
  315. : bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >( block_iterator, bit_index )
  316. {
  317. }
  318. template< typename DynamicBitset >
  319. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  320. const_bit_iterator< DynamicBitset >::const_bit_iterator( const bit_iterator< DynamicBitset > & it )
  321. : bit_iterator_base< typename DynamicBitset::buffer_type::const_iterator >( it.m_block_iterator, it.m_bit_index )
  322. {
  323. }
  324. template< typename DynamicBitset >
  325. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename const_bit_iterator< DynamicBitset >::const_reference
  326. const_bit_iterator< DynamicBitset >::operator*() const
  327. {
  328. return ( *( this->m_block_iterator ) & ( typename DynamicBitset::block_type( 1 ) << this->m_bit_index ) ) != 0;
  329. }
  330. template< typename DynamicBitset >
  331. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset > &
  332. const_bit_iterator< DynamicBitset >::const_bit_iterator::operator++()
  333. {
  334. this->increment();
  335. return *this;
  336. }
  337. template< typename DynamicBitset >
  338. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset >
  339. const_bit_iterator< DynamicBitset >::operator++( int )
  340. {
  341. const_bit_iterator temp = *this;
  342. this->increment();
  343. return temp;
  344. }
  345. template< typename DynamicBitset >
  346. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset > &
  347. const_bit_iterator< DynamicBitset >::const_bit_iterator::operator--()
  348. {
  349. this->decrement();
  350. return *this;
  351. }
  352. template< typename DynamicBitset >
  353. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset >
  354. const_bit_iterator< DynamicBitset >::operator--( int )
  355. {
  356. const_bit_iterator temp = *this;
  357. this->decrement();
  358. return temp;
  359. }
  360. template< typename DynamicBitset >
  361. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset > &
  362. const_bit_iterator< DynamicBitset >::operator+=( difference_type n )
  363. {
  364. this->add( n );
  365. return *this;
  366. }
  367. template< typename DynamicBitset >
  368. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset > &
  369. const_bit_iterator< DynamicBitset >::operator-=( difference_type n )
  370. {
  371. this->add( -n );
  372. return *this;
  373. }
  374. template< typename DynamicBitset >
  375. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset >
  376. operator+( const const_bit_iterator< DynamicBitset > & it, typename const_bit_iterator< DynamicBitset >::difference_type n )
  377. {
  378. const_bit_iterator< DynamicBitset > temp = it;
  379. temp += n;
  380. return temp;
  381. }
  382. template< typename DynamicBitset >
  383. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset >
  384. operator+( typename const_bit_iterator< DynamicBitset >::difference_type n, const const_bit_iterator< DynamicBitset > & it )
  385. {
  386. return it + n;
  387. }
  388. template< typename DynamicBitset >
  389. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const_bit_iterator< DynamicBitset >
  390. operator-( const const_bit_iterator< DynamicBitset > & it, typename const_bit_iterator< DynamicBitset >::difference_type n )
  391. {
  392. const_bit_iterator< DynamicBitset > temp = it;
  393. temp -= n;
  394. return temp;
  395. }
  396. template< typename DynamicBitset >
  397. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename const_bit_iterator< DynamicBitset >::const_reference
  398. const_bit_iterator< DynamicBitset >::operator[]( difference_type n ) const
  399. {
  400. return *( *this + n );
  401. }
  402. template< typename BlockIterator, typename B, typename A >
  403. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  404. from_block_range( BlockIterator first, BlockIterator last, dynamic_bitset< B, A > & result )
  405. {
  406. // PRE: distance(first, last) <= numblocks()
  407. std::copy( first, last, result.m_bits.begin() );
  408. }
  409. template< typename Block, typename AllocatorOrContainer >
  410. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  411. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset()
  412. : m_num_bits( 0 )
  413. {
  414. }
  415. template< typename Block, typename AllocatorOrContainer >
  416. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  417. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( const allocator_type & alloc )
  418. : m_bits( alloc ), m_num_bits( 0 )
  419. {
  420. }
  421. template< typename Block, typename AllocatorOrContainer >
  422. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  423. dynamic_bitset< Block, AllocatorOrContainer >::
  424. dynamic_bitset( size_type num_bits, unsigned long value, const allocator_type & alloc )
  425. : m_bits( alloc ), m_num_bits( 0 )
  426. {
  427. init_from_unsigned_long( num_bits, value );
  428. }
  429. template< typename Block, typename AllocatorOrContainer >
  430. template< typename CharT, typename Traits, typename Alloc >
  431. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset(
  432. const std::basic_string< CharT, Traits, Alloc > & s,
  433. typename std::basic_string< CharT, Traits, Alloc >::size_type pos,
  434. typename std::basic_string< CharT, Traits, Alloc >::size_type n,
  435. size_type num_bits,
  436. const allocator_type & alloc )
  437. : m_bits( alloc ), m_num_bits( 0 )
  438. {
  439. init_from_string( s.c_str(), s.length(), pos, n, num_bits );
  440. }
  441. template< typename Block, typename AllocatorOrContainer >
  442. template< typename CharT >
  443. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset(
  444. const CharT * s,
  445. std::size_t n,
  446. size_type num_bits,
  447. const allocator_type & alloc )
  448. : m_bits( alloc ), m_num_bits( 0 )
  449. {
  450. init_from_string( s, std::char_traits< CharT >::length( s ), 0, n, num_bits );
  451. }
  452. #if defined( BOOST_DYNAMIC_BITSET_USE_CPP17_OR_LATER )
  453. template< typename Block, typename AllocatorOrContainer >
  454. template< typename CharT, typename Traits >
  455. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset(
  456. std::basic_string_view< CharT, Traits > sv,
  457. size_type num_bits,
  458. const allocator_type & alloc )
  459. : m_bits( alloc ), m_num_bits( 0 )
  460. {
  461. init_from_string( sv.data(), sv.length(), 0, sv.length(), num_bits );
  462. }
  463. #endif
  464. template< typename Block, typename AllocatorOrContainer >
  465. template< typename BlockInputIterator >
  466. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  467. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset(
  468. BlockInputIterator first,
  469. BlockInputIterator last,
  470. const allocator_type & alloc )
  471. : m_bits( alloc ), m_num_bits( 0 )
  472. {
  473. using boost::detail::dynamic_bitset_impl::is_numeric;
  474. using boost::detail::dynamic_bitset_impl::value_to_type;
  475. const value_to_type<
  476. is_numeric< BlockInputIterator >::value >
  477. selector;
  478. dispatch_init( first, last, selector );
  479. }
  480. // copy constructor
  481. template< typename Block, typename AllocatorOrContainer >
  482. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  483. dynamic_bitset< Block, AllocatorOrContainer >::dynamic_bitset( const dynamic_bitset & b )
  484. : m_bits( b.m_bits ), m_num_bits( b.m_num_bits )
  485. {
  486. }
  487. template< typename Block, typename AllocatorOrContainer >
  488. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >::~dynamic_bitset()
  489. {
  490. BOOST_ASSERT( m_check_invariants() );
  491. }
  492. template< typename Block, typename AllocatorOrContainer >
  493. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::iterator
  494. dynamic_bitset< Block, AllocatorOrContainer >::begin()
  495. {
  496. return iterator( m_bits.begin(), 0 );
  497. }
  498. template< typename Block, typename AllocatorOrContainer >
  499. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
  500. dynamic_bitset< Block, AllocatorOrContainer >::begin() const
  501. {
  502. return const_iterator( m_bits.cbegin(), 0 );
  503. }
  504. template< typename Block, typename AllocatorOrContainer >
  505. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::iterator
  506. dynamic_bitset< Block, AllocatorOrContainer >::end()
  507. {
  508. if ( count_extra_bits() == 0 ) {
  509. return iterator( m_bits.end(), 0 );
  510. } else {
  511. return iterator( std::prev( m_bits.end() ), size() % bits_per_block );
  512. }
  513. }
  514. template< typename Block, typename AllocatorOrContainer >
  515. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
  516. dynamic_bitset< Block, AllocatorOrContainer >::end() const
  517. {
  518. if ( count_extra_bits() == 0 ) {
  519. return const_iterator( m_bits.cend(), 0 );
  520. } else {
  521. return const_iterator( std::prev( m_bits.cend() ), size() % bits_per_block );
  522. }
  523. }
  524. template< typename Block, typename AllocatorOrContainer >
  525. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reverse_iterator
  526. dynamic_bitset< Block, AllocatorOrContainer >::rbegin()
  527. {
  528. return reverse_iterator( end() );
  529. }
  530. template< typename Block, typename AllocatorOrContainer >
  531. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
  532. dynamic_bitset< Block, AllocatorOrContainer >::rbegin() const
  533. {
  534. return const_reverse_iterator( end() );
  535. }
  536. template< typename Block, typename AllocatorOrContainer >
  537. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reverse_iterator
  538. dynamic_bitset< Block, AllocatorOrContainer >::rend()
  539. {
  540. return reverse_iterator( begin() );
  541. }
  542. template< typename Block, typename AllocatorOrContainer >
  543. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
  544. dynamic_bitset< Block, AllocatorOrContainer >::rend() const
  545. {
  546. return const_reverse_iterator( begin() );
  547. }
  548. template< typename Block, typename AllocatorOrContainer >
  549. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
  550. dynamic_bitset< Block, AllocatorOrContainer >::cbegin() const
  551. {
  552. return const_iterator( begin() );
  553. }
  554. template< typename Block, typename AllocatorOrContainer >
  555. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_iterator
  556. dynamic_bitset< Block, AllocatorOrContainer >::cend() const
  557. {
  558. return const_iterator( end() );
  559. }
  560. template< typename Block, typename AllocatorOrContainer >
  561. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
  562. dynamic_bitset< Block, AllocatorOrContainer >::crbegin() const
  563. {
  564. return const_reverse_iterator( end() );
  565. }
  566. template< typename Block, typename AllocatorOrContainer >
  567. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::const_reverse_iterator
  568. dynamic_bitset< Block, AllocatorOrContainer >::crend() const
  569. {
  570. return const_reverse_iterator( begin() );
  571. }
  572. template< typename Block, typename AllocatorOrContainer >
  573. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  574. dynamic_bitset< Block, AllocatorOrContainer >::
  575. swap( dynamic_bitset< Block, AllocatorOrContainer > & b ) noexcept
  576. {
  577. std::swap( m_bits, b.m_bits );
  578. std::swap( m_num_bits, b.m_num_bits );
  579. }
  580. template< typename Block, typename AllocatorOrContainer >
  581. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  582. dynamic_bitset< Block, AllocatorOrContainer >::
  583. operator=( const dynamic_bitset< Block, AllocatorOrContainer > & b )
  584. {
  585. m_bits = b.m_bits;
  586. m_num_bits = b.m_num_bits;
  587. return *this;
  588. }
  589. template< typename Block, typename AllocatorOrContainer >
  590. BOOST_DYNAMIC_BITSET_CONSTEXPR20
  591. dynamic_bitset< Block, AllocatorOrContainer >::
  592. dynamic_bitset( dynamic_bitset< Block, AllocatorOrContainer > && b )
  593. : m_bits( std::move( b.m_bits ) ), m_num_bits( std::move( b.m_num_bits ) )
  594. {
  595. // Required so that BOOST_ASSERT(m_check_invariants()); works.
  596. BOOST_ASSERT( ( b.m_bits = buffer_type( get_allocator() ) ).empty() );
  597. b.m_num_bits = 0;
  598. }
  599. template< typename Block, typename AllocatorOrContainer >
  600. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  601. dynamic_bitset< Block, AllocatorOrContainer >::
  602. operator=( dynamic_bitset< Block, AllocatorOrContainer > && b )
  603. {
  604. if ( &b == this ) {
  605. return *this;
  606. }
  607. m_bits = std::move( b.m_bits );
  608. m_num_bits = std::move( b.m_num_bits );
  609. // Required so that BOOST_ASSERT(m_check_invariants()); works.
  610. BOOST_ASSERT( ( b.m_bits = buffer_type( get_allocator() ) ).empty() );
  611. b.m_num_bits = 0;
  612. return *this;
  613. }
  614. template< typename Block, typename AllocatorOrContainer >
  615. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::allocator_type
  616. dynamic_bitset< Block, AllocatorOrContainer >::get_allocator() const
  617. {
  618. return m_bits.get_allocator();
  619. }
  620. //-----------------------------------------------------------------------------
  621. // size changing operations
  622. template< typename Block, typename AllocatorOrContainer >
  623. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  624. dynamic_bitset< Block, AllocatorOrContainer >::
  625. resize( size_type num_bits, bool value ) // strong guarantee
  626. {
  627. const size_type old_num_blocks = num_blocks();
  628. const size_type required_blocks = calc_num_blocks( num_bits );
  629. const block_type v = value ? Block( -1 ) : Block( 0 );
  630. if ( required_blocks != old_num_blocks ) {
  631. m_bits.resize( required_blocks, v ); // s.g. (copy)
  632. }
  633. // At this point:
  634. //
  635. // - if the buffer was shrunk, we have nothing more to do,
  636. // except a call to m_zero_unused_bits()
  637. //
  638. // - if it was enlarged, all the (used) bits in the new blocks have
  639. // the correct value, but we have not yet touched those bits, if
  640. // any, that were 'unused bits' before enlarging: if value == true,
  641. // they must be set.
  642. if ( value && ( num_bits > m_num_bits ) ) {
  643. const int extra_bits = count_extra_bits();
  644. if ( extra_bits ) {
  645. BOOST_ASSERT( old_num_blocks >= 1 && old_num_blocks <= m_bits.size() );
  646. // Set them.
  647. m_bits[ old_num_blocks - 1 ] |= ( v << extra_bits );
  648. }
  649. }
  650. m_num_bits = num_bits;
  651. m_zero_unused_bits();
  652. }
  653. template< typename Block, typename AllocatorOrContainer >
  654. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  655. dynamic_bitset< Block, AllocatorOrContainer >::
  656. clear() // no throw
  657. {
  658. m_bits.clear();
  659. m_num_bits = 0;
  660. }
  661. template< typename Block, typename AllocatorOrContainer >
  662. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  663. dynamic_bitset< Block, AllocatorOrContainer >::
  664. push_back( bool bit )
  665. {
  666. const int extra_bits = count_extra_bits();
  667. if ( extra_bits == 0 ) {
  668. m_bits.push_back( Block( bit ) );
  669. } else {
  670. m_bits.back() |= ( Block( bit ) << extra_bits );
  671. }
  672. ++m_num_bits;
  673. }
  674. template< typename Block, typename AllocatorOrContainer >
  675. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  676. dynamic_bitset< Block, AllocatorOrContainer >::
  677. push_front( bool bit )
  678. {
  679. resize( size() + 1 );
  680. *this <<= 1;
  681. set( 0, bit );
  682. }
  683. template< typename Block, typename AllocatorOrContainer >
  684. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  685. dynamic_bitset< Block, AllocatorOrContainer >::
  686. pop_back()
  687. {
  688. BOOST_ASSERT( ! empty() );
  689. if ( count_extra_bits() == 1 ) {
  690. m_bits.pop_back();
  691. --m_num_bits;
  692. } else {
  693. --m_num_bits;
  694. m_zero_unused_bits();
  695. }
  696. }
  697. template< typename Block, typename AllocatorOrContainer >
  698. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  699. dynamic_bitset< Block, AllocatorOrContainer >::
  700. pop_front()
  701. {
  702. BOOST_ASSERT( ! empty() );
  703. *this >>= 1;
  704. resize( size() - 1 );
  705. }
  706. template< typename Block, typename AllocatorOrContainer >
  707. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  708. dynamic_bitset< Block, AllocatorOrContainer >::
  709. append( Block value ) // strong guarantee
  710. {
  711. const int r = count_extra_bits();
  712. if ( r == 0 ) {
  713. // the buffer is empty, or all blocks are filled
  714. m_bits.push_back( value );
  715. } else {
  716. m_bits.push_back( value >> ( bits_per_block - r ) );
  717. m_bits[ m_bits.size() - 2 ] |= ( value << r ); // m_bits.size() >= 2
  718. }
  719. m_num_bits += bits_per_block;
  720. BOOST_ASSERT( m_check_invariants() );
  721. }
  722. template< typename Block, typename AllocatorOrContainer >
  723. template< typename BlockInputIterator >
  724. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  725. dynamic_bitset< Block, AllocatorOrContainer >::append( BlockInputIterator first, BlockInputIterator last ) // strong guarantee
  726. {
  727. typename std::iterator_traits< BlockInputIterator >::iterator_category cat;
  728. m_append( first, last, cat );
  729. }
  730. //-----------------------------------------------------------------------------
  731. // bitset operations
  732. template< typename Block, typename AllocatorOrContainer >
  733. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  734. dynamic_bitset< Block, AllocatorOrContainer >::operator&=( const dynamic_bitset & rhs )
  735. {
  736. BOOST_ASSERT( size() == rhs.size() );
  737. for ( size_type i = 0; i < num_blocks(); ++i ) {
  738. m_bits[ i ] &= rhs.m_bits[ i ];
  739. }
  740. return *this;
  741. }
  742. template< typename Block, typename AllocatorOrContainer >
  743. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  744. dynamic_bitset< Block, AllocatorOrContainer >::operator|=( const dynamic_bitset & rhs )
  745. {
  746. BOOST_ASSERT( size() == rhs.size() );
  747. for ( size_type i = 0; i < num_blocks(); ++i ) {
  748. m_bits[ i ] |= rhs.m_bits[ i ];
  749. }
  750. // m_zero_unused_bits();
  751. return *this;
  752. }
  753. template< typename Block, typename AllocatorOrContainer >
  754. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  755. dynamic_bitset< Block, AllocatorOrContainer >::operator^=( const dynamic_bitset & rhs )
  756. {
  757. BOOST_ASSERT( size() == rhs.size() );
  758. for ( size_type i = 0; i < this->num_blocks(); ++i ) {
  759. m_bits[ i ] ^= rhs.m_bits[ i ];
  760. }
  761. // m_zero_unused_bits();
  762. return *this;
  763. }
  764. template< typename Block, typename AllocatorOrContainer >
  765. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  766. dynamic_bitset< Block, AllocatorOrContainer >::operator-=( const dynamic_bitset & rhs )
  767. {
  768. BOOST_ASSERT( size() == rhs.size() );
  769. for ( size_type i = 0; i < num_blocks(); ++i ) {
  770. m_bits[ i ] &= ~rhs.m_bits[ i ];
  771. }
  772. // m_zero_unused_bits();
  773. return *this;
  774. }
  775. // NOTE:
  776. // Note that the 'if (r != 0)' is crucial to avoid undefined
  777. // behavior when the left hand operand of >> isn't promoted to a
  778. // wider type (because rs would be too large).
  779. //
  780. template< typename Block, typename AllocatorOrContainer >
  781. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  782. dynamic_bitset< Block, AllocatorOrContainer >::operator<<=( size_type n )
  783. {
  784. if ( n >= m_num_bits ) {
  785. return reset();
  786. }
  787. // else
  788. if ( n > 0 ) {
  789. const size_type last = num_blocks() - 1; // num_blocks() is >= 1
  790. const size_type div = n / bits_per_block; // div is <= last
  791. const int r = bit_index( n );
  792. buffer_type & b = m_bits;
  793. if ( r != 0 ) {
  794. const int rs = bits_per_block - r;
  795. for ( size_type i = last - div; i > 0; --i ) {
  796. b[ i + div ] = ( b[ i ] << r ) | ( b[ i - 1 ] >> rs );
  797. }
  798. b[ div ] = b[ 0 ] << r;
  799. } else {
  800. for ( size_type i = last - div; i > 0; --i ) {
  801. b[ i + div ] = b[ i ];
  802. }
  803. b[ div ] = b[ 0 ];
  804. }
  805. // zero out div blocks at the least significant end
  806. std::fill_n( m_bits.begin(), div, static_cast< block_type >( 0 ) );
  807. // zero out any 1 bit that flowed into the unused part
  808. m_zero_unused_bits(); // thanks to Lester Gong
  809. }
  810. return *this;
  811. }
  812. //
  813. // NOTE:
  814. // See the comments to operator <<=.
  815. //
  816. template< typename B, typename A >
  817. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< B, A > &
  818. dynamic_bitset< B, A >::operator>>=( size_type n )
  819. {
  820. if ( n >= m_num_bits ) {
  821. return reset();
  822. }
  823. // else
  824. if ( n > 0 ) {
  825. const size_type last = num_blocks() - 1; // num_blocks() is >= 1
  826. const size_type div = n / bits_per_block; // div is <= last
  827. const int r = bit_index( n );
  828. buffer_type & b = m_bits;
  829. if ( r != 0 ) {
  830. const int ls = bits_per_block - r;
  831. for ( size_type i = div; i < last; ++i ) {
  832. b[ i - div ] = ( b[ i ] >> r ) | ( b[ i + 1 ] << ls );
  833. }
  834. // r bits go to zero
  835. b[ last - div ] = b[ last ] >> r;
  836. }
  837. else {
  838. for ( size_type i = div; i <= last; ++i ) {
  839. b[ i - div ] = b[ i ];
  840. }
  841. // note the '<=': the last iteration 'absorbs'
  842. // b[last-div] = b[last] >> 0;
  843. }
  844. // div blocks are zero filled at the most significant end
  845. std::fill_n( m_bits.begin() + ( num_blocks() - div ), div, static_cast< block_type >( 0 ) );
  846. }
  847. return *this;
  848. }
  849. template< typename Block, typename AllocatorOrContainer >
  850. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  851. dynamic_bitset< Block, AllocatorOrContainer >::operator<<( size_type n ) const
  852. {
  853. dynamic_bitset r( *this );
  854. return r <<= n;
  855. }
  856. template< typename Block, typename AllocatorOrContainer >
  857. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  858. dynamic_bitset< Block, AllocatorOrContainer >::operator>>( size_type n ) const
  859. {
  860. dynamic_bitset r( *this );
  861. return r >>= n;
  862. }
  863. //-----------------------------------------------------------------------------
  864. // basic bit operations
  865. template< typename Block, typename AllocatorOrContainer >
  866. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  867. dynamic_bitset< Block, AllocatorOrContainer >::set( size_type pos, size_type len, bool val )
  868. {
  869. if ( val ) {
  870. return range_operation( pos, len, set_block_partial, set_block_full );
  871. } else {
  872. return range_operation( pos, len, reset_block_partial, reset_block_full );
  873. }
  874. }
  875. template< typename Block, typename AllocatorOrContainer >
  876. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  877. dynamic_bitset< Block, AllocatorOrContainer >::set( size_type pos, bool val )
  878. {
  879. BOOST_ASSERT( pos < m_num_bits );
  880. if ( val ) {
  881. m_bits[ block_index( pos ) ] |= bit_mask( pos );
  882. } else {
  883. reset( pos );
  884. }
  885. return *this;
  886. }
  887. template< typename Block, typename AllocatorOrContainer >
  888. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  889. dynamic_bitset< Block, AllocatorOrContainer >::set()
  890. {
  891. std::fill( m_bits.begin(), m_bits.end(), Block( -1 ) );
  892. m_zero_unused_bits();
  893. return *this;
  894. }
  895. template< typename Block, typename AllocatorOrContainer >
  896. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  897. dynamic_bitset< Block, AllocatorOrContainer >::reset( size_type pos, size_type len )
  898. {
  899. return range_operation( pos, len, reset_block_partial, reset_block_full );
  900. }
  901. template< typename Block, typename AllocatorOrContainer >
  902. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  903. dynamic_bitset< Block, AllocatorOrContainer >::reset( size_type pos )
  904. {
  905. BOOST_ASSERT( pos < m_num_bits );
  906. m_bits[ block_index( pos ) ] &= ~bit_mask( pos );
  907. return *this;
  908. }
  909. template< typename Block, typename AllocatorOrContainer >
  910. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  911. dynamic_bitset< Block, AllocatorOrContainer >::reset()
  912. {
  913. std::fill( m_bits.begin(), m_bits.end(), Block( 0 ) );
  914. return *this;
  915. }
  916. template< typename Block, typename AllocatorOrContainer >
  917. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  918. dynamic_bitset< Block, AllocatorOrContainer >::flip( size_type pos, size_type len )
  919. {
  920. return range_operation( pos, len, flip_block_partial, flip_block_full );
  921. }
  922. template< typename Block, typename AllocatorOrContainer >
  923. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  924. dynamic_bitset< Block, AllocatorOrContainer >::flip( size_type pos )
  925. {
  926. BOOST_ASSERT( pos < m_num_bits );
  927. m_bits[ block_index( pos ) ] ^= bit_mask( pos );
  928. return *this;
  929. }
  930. template< typename Block, typename AllocatorOrContainer >
  931. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  932. dynamic_bitset< Block, AllocatorOrContainer >::flip()
  933. {
  934. for ( size_type i = 0; i < num_blocks(); ++i ) {
  935. m_bits[ i ] = ~m_bits[ i ];
  936. }
  937. m_zero_unused_bits();
  938. return *this;
  939. }
  940. template< typename Block, typename AllocatorOrContainer >
  941. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference
  942. dynamic_bitset< Block, AllocatorOrContainer >::at( size_type pos )
  943. {
  944. if ( pos >= m_num_bits ) {
  945. BOOST_THROW_EXCEPTION( std::out_of_range( "boost::dynamic_bitset::at out_of_range" ) );
  946. }
  947. return ( *this )[ pos ];
  948. }
  949. template< typename Block, typename AllocatorOrContainer >
  950. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  951. dynamic_bitset< Block, AllocatorOrContainer >::at( size_type pos ) const
  952. {
  953. if ( pos >= m_num_bits ) {
  954. BOOST_THROW_EXCEPTION( std::out_of_range( "boost::dynamic_bitset::at out_of_range" ) );
  955. }
  956. return ( *this )[ pos ];
  957. }
  958. template< typename Block, typename AllocatorOrContainer >
  959. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  960. dynamic_bitset< Block, AllocatorOrContainer >::test( size_type pos ) const
  961. {
  962. BOOST_ASSERT( pos < m_num_bits );
  963. return m_unchecked_test( pos );
  964. }
  965. template< typename Block, typename AllocatorOrContainer >
  966. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  967. dynamic_bitset< Block, AllocatorOrContainer >::test_set( size_type pos, bool val )
  968. {
  969. const bool b = test( pos );
  970. if ( b != val ) {
  971. set( pos, val );
  972. }
  973. return b;
  974. }
  975. template< typename Block, typename AllocatorOrContainer >
  976. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  977. dynamic_bitset< Block, AllocatorOrContainer >::all() const
  978. {
  979. const int extra_bits = count_extra_bits();
  980. const block_type all_ones = Block( -1 );
  981. const size_type num_normal_blocks = num_blocks() - ( extra_bits != 0 ? 1 : 0 );
  982. for ( size_type i = 0; i < num_normal_blocks; ++i ) {
  983. if ( m_bits[ i ] != all_ones ) {
  984. return false;
  985. }
  986. }
  987. if ( extra_bits != 0 ) {
  988. const block_type mask = ( block_type( 1 ) << extra_bits ) - 1;
  989. if ( m_highest_block() != mask ) {
  990. return false;
  991. }
  992. }
  993. return true;
  994. }
  995. template< typename Block, typename AllocatorOrContainer >
  996. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  997. dynamic_bitset< Block, AllocatorOrContainer >::any() const
  998. {
  999. for ( size_type i = 0; i < num_blocks(); ++i ) {
  1000. if ( m_bits[ i ] ) {
  1001. return true;
  1002. }
  1003. }
  1004. return false;
  1005. }
  1006. template< typename Block, typename AllocatorOrContainer >
  1007. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1008. dynamic_bitset< Block, AllocatorOrContainer >::none() const
  1009. {
  1010. return ! any();
  1011. }
  1012. template< typename Block, typename AllocatorOrContainer >
  1013. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  1014. dynamic_bitset< Block, AllocatorOrContainer >::operator~() const
  1015. {
  1016. dynamic_bitset b( *this );
  1017. b.flip();
  1018. return b;
  1019. }
  1020. template< typename Block, typename AllocatorOrContainer >
  1021. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1022. dynamic_bitset< Block, AllocatorOrContainer >::count() const noexcept
  1023. {
  1024. size_type result = 0;
  1025. for ( block_type block : m_bits ) {
  1026. result += core::popcount( block );
  1027. }
  1028. return result;
  1029. }
  1030. //-----------------------------------------------------------------------------
  1031. // subscript
  1032. template< typename Block, typename AllocatorOrContainer >
  1033. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::reference
  1034. dynamic_bitset< Block, AllocatorOrContainer >::operator[]( size_type pos )
  1035. {
  1036. return reference( m_bits[ block_index( pos ) ], bit_index( pos ) );
  1037. }
  1038. template< typename Block, typename AllocatorOrContainer >
  1039. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1040. dynamic_bitset< Block, AllocatorOrContainer >::operator[]( size_type pos ) const
  1041. {
  1042. return test( pos );
  1043. }
  1044. //-----------------------------------------------------------------------------
  1045. // conversions
  1046. template< typename Block, typename AllocatorOrContainer >
  1047. BOOST_DYNAMIC_BITSET_CONSTEXPR20 unsigned long
  1048. dynamic_bitset< Block, AllocatorOrContainer >::
  1049. to_ulong() const
  1050. {
  1051. if ( m_num_bits == 0 ) {
  1052. return 0; // convention
  1053. }
  1054. // Check for overflows. This may be a performance burden on very large
  1055. // bitsets but is required by the specification, sorry.
  1056. if ( find_first( ulong_width ) != npos ) {
  1057. BOOST_THROW_EXCEPTION( std::overflow_error( "boost::dynamic_bitset::to_ulong overflow" ) );
  1058. }
  1059. // Ok, from now on we can be sure there's no "on" bit beyond the
  1060. // "allowed" positions.
  1061. typedef unsigned long result_type;
  1062. const size_type maximum_size =
  1063. (std::min)( m_num_bits, static_cast< size_type >( ulong_width ) );
  1064. const size_type last_block = block_index( maximum_size - 1 );
  1065. BOOST_ASSERT( ( last_block * bits_per_block ) < static_cast< size_type >( ulong_width ) );
  1066. result_type result = 0;
  1067. for ( size_type i = 0; i <= last_block; ++i ) {
  1068. const size_type offset = i * bits_per_block;
  1069. result |= ( static_cast< result_type >( m_bits[ i ] ) << offset );
  1070. }
  1071. return result;
  1072. }
  1073. template< typename Block, typename AllocatorOrContainer, typename StringT >
  1074. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1075. to_string( const dynamic_bitset< Block, AllocatorOrContainer > & b, StringT & s )
  1076. {
  1077. to_string_helper( b, s, false );
  1078. }
  1079. // Differently from to_string this function dumps out every bit of the
  1080. // internal representation (may be useful for debugging purposes)
  1081. template< typename B, typename A, typename StringT >
  1082. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1083. dump_to_string( const dynamic_bitset< B, A > & b, StringT & s )
  1084. {
  1085. to_string_helper( b, s, true /* = dump_all */ );
  1086. }
  1087. template< typename Block, typename AllocatorOrContainer, typename BlockOutputIterator >
  1088. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1089. to_block_range( const dynamic_bitset< Block, AllocatorOrContainer > & b, BlockOutputIterator result )
  1090. {
  1091. // Note how this copies *all* bits, including the unused ones in the
  1092. // last block (which are zero).
  1093. std::copy( b.m_bits.begin(), b.m_bits.end(), result );
  1094. }
  1095. template< typename Block, typename AllocatorOrContainer >
  1096. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1097. dynamic_bitset< Block, AllocatorOrContainer >::size() const noexcept
  1098. {
  1099. return m_num_bits;
  1100. }
  1101. template< typename Block, typename AllocatorOrContainer >
  1102. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1103. dynamic_bitset< Block, AllocatorOrContainer >::num_blocks() const noexcept
  1104. {
  1105. return m_bits.size();
  1106. }
  1107. template< typename Block, typename AllocatorOrContainer >
  1108. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1109. dynamic_bitset< Block, AllocatorOrContainer >::max_size() const noexcept
  1110. {
  1111. // The semantics of vector<>::max_size() aren't very clear (see lib
  1112. // issue 197).
  1113. //
  1114. // Because of that, I was tempted to not provide this function
  1115. // at all, but the user could need it if they provide their own
  1116. // allocator.
  1117. const size_type m = m_bits.max_size();
  1118. return m <= ( size_type( -1 ) / bits_per_block ) ? m * bits_per_block : size_type( -1 );
  1119. }
  1120. template< typename Block, typename AllocatorOrContainer >
  1121. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1122. dynamic_bitset< Block, AllocatorOrContainer >::empty() const noexcept
  1123. {
  1124. return size() == 0;
  1125. }
  1126. template< typename Block, typename AllocatorOrContainer >
  1127. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1128. dynamic_bitset< Block, AllocatorOrContainer >::capacity() const noexcept
  1129. {
  1130. return m_bits.capacity() * bits_per_block;
  1131. }
  1132. template< typename Block, typename AllocatorOrContainer >
  1133. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1134. dynamic_bitset< Block, AllocatorOrContainer >::reserve( size_type num_bits )
  1135. {
  1136. m_bits.reserve( calc_num_blocks( num_bits ) );
  1137. }
  1138. template< typename Block, typename AllocatorOrContainer >
  1139. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1140. dynamic_bitset< Block, AllocatorOrContainer >::shrink_to_fit()
  1141. {
  1142. if ( m_bits.size() < m_bits.capacity() ) {
  1143. buffer_type( m_bits ).swap( m_bits );
  1144. }
  1145. }
  1146. template< typename Block, typename AllocatorOrContainer >
  1147. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1148. dynamic_bitset< Block, AllocatorOrContainer >::
  1149. is_subset_of( const dynamic_bitset< Block, AllocatorOrContainer > & a ) const
  1150. {
  1151. BOOST_ASSERT( size() == a.size() );
  1152. for ( size_type i = 0; i < num_blocks(); ++i ) {
  1153. if ( m_bits[ i ] & ~a.m_bits[ i ] ) {
  1154. return false;
  1155. }
  1156. }
  1157. return true;
  1158. }
  1159. template< typename Block, typename AllocatorOrContainer >
  1160. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1161. dynamic_bitset< Block, AllocatorOrContainer >::
  1162. is_proper_subset_of( const dynamic_bitset< Block, AllocatorOrContainer > & a ) const
  1163. {
  1164. BOOST_ASSERT( size() == a.size() );
  1165. bool proper = false;
  1166. for ( size_type i = 0; i < num_blocks(); ++i ) {
  1167. const Block & bt = m_bits[ i ];
  1168. const Block & ba = a.m_bits[ i ];
  1169. if ( bt & ~ba ) {
  1170. return false; // not a subset at all
  1171. }
  1172. if ( ba & ~bt ) {
  1173. proper = true;
  1174. }
  1175. }
  1176. return proper;
  1177. }
  1178. template< typename Block, typename AllocatorOrContainer >
  1179. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1180. dynamic_bitset< Block, AllocatorOrContainer >::intersects( const dynamic_bitset & b ) const
  1181. {
  1182. const size_type common_blocks = num_blocks() < b.num_blocks()
  1183. ? num_blocks()
  1184. : b.num_blocks();
  1185. for ( size_type i = 0; i < common_blocks; ++i ) {
  1186. if ( m_bits[ i ] & b.m_bits[ i ] ) {
  1187. return true;
  1188. }
  1189. }
  1190. return false;
  1191. }
  1192. // --------------------------------
  1193. // lookup
  1194. // Look for the first bit with value `value`, starting from the block with index
  1195. // first_block.
  1196. template< typename Block, typename AllocatorOrContainer >
  1197. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1198. dynamic_bitset< Block, AllocatorOrContainer >::m_do_find_from( size_type first_block, bool value ) const
  1199. {
  1200. size_type i = std::distance( m_bits.begin(), std::find_if( m_bits.begin() + first_block, m_bits.end(), value ? m_not_empty : m_not_full ) );
  1201. if ( i >= num_blocks() ) {
  1202. return npos; // not found
  1203. }
  1204. const Block b = value
  1205. ? m_bits[ i ]
  1206. : m_bits[ i ] ^ Block( -1 );
  1207. return i * bits_per_block + static_cast< size_type >( detail::lowest_bit( b ) );
  1208. }
  1209. template< typename Block, typename AllocatorOrContainer >
  1210. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1211. dynamic_bitset< Block, AllocatorOrContainer >::find_first( size_type pos ) const
  1212. {
  1213. const size_type sz = size();
  1214. if ( pos >= sz ) {
  1215. return npos;
  1216. }
  1217. const size_type blk = block_index( pos );
  1218. const int ind = bit_index( pos );
  1219. // shift bits upto one immediately after current
  1220. const Block fore = m_bits[ blk ] >> ind;
  1221. const bool found = m_not_empty( fore );
  1222. return found ? pos + static_cast< size_type >( detail::lowest_bit( fore ) )
  1223. : m_do_find_from( blk + 1, true );
  1224. }
  1225. template< typename Block, typename AllocatorOrContainer >
  1226. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1227. dynamic_bitset< Block, AllocatorOrContainer >::find_first_off( size_type pos ) const
  1228. {
  1229. if ( pos >= size() ) {
  1230. return npos;
  1231. }
  1232. const size_type blk = block_index( pos );
  1233. const int ind = bit_index( pos );
  1234. const Block fore = m_bits[ blk ] >> ind;
  1235. bool found = false;
  1236. int lowest_off_bit_pos = -1;
  1237. if ( m_not_full( fore ) ) {
  1238. lowest_off_bit_pos = detail::lowest_bit( fore ^ Block( -1 ) );
  1239. // don't consider a zero introduced by m_bits[ blk ] >> ind as found
  1240. found = lowest_off_bit_pos <= ( bits_per_block - 1 - ind );
  1241. }
  1242. const size_type zero_pos = found
  1243. ? pos + lowest_off_bit_pos
  1244. : m_do_find_from( blk + 1, false );
  1245. return zero_pos >= size()
  1246. ? npos
  1247. : zero_pos;
  1248. }
  1249. template< typename Block, typename AllocatorOrContainer >
  1250. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1251. dynamic_bitset< Block, AllocatorOrContainer >::find_next( size_type pos ) const
  1252. {
  1253. return pos == npos
  1254. ? npos
  1255. : find_first( pos + 1 );
  1256. }
  1257. template< typename Block, typename AllocatorOrContainer >
  1258. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1259. dynamic_bitset< Block, AllocatorOrContainer >::find_next_off( size_type pos ) const
  1260. {
  1261. return pos == npos
  1262. ? npos
  1263. : find_first_off( pos + 1 );
  1264. }
  1265. //-----------------------------------------------------------------------------
  1266. // comparison
  1267. template< typename Block, typename AllocatorOrContainer >
  1268. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1269. operator==( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1270. {
  1271. return ( a.m_num_bits == b.m_num_bits )
  1272. && ( a.m_bits == b.m_bits );
  1273. }
  1274. template< typename Block, typename AllocatorOrContainer >
  1275. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1276. operator!=( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1277. {
  1278. return ! ( a == b );
  1279. }
  1280. template< typename Block, typename AllocatorOrContainer >
  1281. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1282. operator<( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1283. {
  1284. typedef BOOST_DEDUCED_TYPENAME dynamic_bitset< Block, AllocatorOrContainer >::size_type size_type;
  1285. size_type asize( a.size() );
  1286. size_type bsize( b.size() );
  1287. if ( ! bsize ) {
  1288. return false;
  1289. } else if ( ! asize ) {
  1290. return true;
  1291. } else if ( asize == bsize ) {
  1292. for ( size_type ii = a.num_blocks(); ii > 0; --ii ) {
  1293. size_type i = ii - 1;
  1294. if ( a.m_bits[ i ] < b.m_bits[ i ] ) {
  1295. return true;
  1296. } else if ( a.m_bits[ i ] > b.m_bits[ i ] ) {
  1297. return false;
  1298. }
  1299. }
  1300. return false;
  1301. } else {
  1302. size_type leqsize( std::min BOOST_PREVENT_MACRO_SUBSTITUTION( asize, bsize ) );
  1303. for ( size_type ii = 0; ii < leqsize; ++ii, --asize, --bsize ) {
  1304. size_type i = asize - 1;
  1305. size_type j = bsize - 1;
  1306. if ( a[ i ] < b[ j ] ) {
  1307. return true;
  1308. } else if ( a[ i ] > b[ j ] ) {
  1309. return false;
  1310. }
  1311. }
  1312. return a.size() < b.size();
  1313. }
  1314. }
  1315. template< typename Block, typename AllocatorOrContainer >
  1316. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1317. operator<=( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1318. {
  1319. return ! ( a > b );
  1320. }
  1321. template< typename Block, typename AllocatorOrContainer >
  1322. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1323. operator>( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1324. {
  1325. return b < a;
  1326. }
  1327. template< typename Block, typename AllocatorOrContainer >
  1328. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1329. operator>=( const dynamic_bitset< Block, AllocatorOrContainer > & a, const dynamic_bitset< Block, AllocatorOrContainer > & b )
  1330. {
  1331. return ! ( a < b );
  1332. }
  1333. template< typename B, typename A, typename StringT >
  1334. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1335. to_string_helper( const dynamic_bitset< B, A > & b, StringT & s, bool dump_all )
  1336. {
  1337. typedef typename StringT::traits_type Tr;
  1338. typedef typename StringT::value_type Ch;
  1339. const std::ctype< Ch > & fac = std::use_facet< std::ctype< Ch > >( std::locale() );
  1340. const Ch zero = fac.widen( '0' );
  1341. const Ch one = fac.widen( '1' );
  1342. // Note that this function may access (when
  1343. // dump_all == true) bits beyond position size() - 1
  1344. typedef typename dynamic_bitset< B, A >::size_type size_type;
  1345. const size_type len = dump_all ? dynamic_bitset< B, A >::bits_per_block * b.num_blocks() : b.size();
  1346. s.assign( len, zero );
  1347. for ( size_type i = 0; i < len; ++i ) {
  1348. if ( b.m_unchecked_test( i ) ) {
  1349. Tr::assign( s[ len - 1 - i ], one );
  1350. }
  1351. }
  1352. }
  1353. //-----------------------------------------------------------------------------
  1354. // hash operations
  1355. template< typename Block, typename AllocatorOrContainer >
  1356. std::size_t
  1357. hash_value( const dynamic_bitset< Block, AllocatorOrContainer > & a )
  1358. {
  1359. std::size_t res = hash_value( a.m_num_bits );
  1360. boost::hash_combine( res, a.m_bits );
  1361. return res;
  1362. }
  1363. //-----------------------------------------------------------------------------
  1364. // stream operations
  1365. template< typename Ch, typename Tr, typename Block, typename Alloc >
  1366. std::basic_ostream< Ch, Tr > &
  1367. operator<<( std::basic_ostream< Ch, Tr > & os, const dynamic_bitset< Block, Alloc > & b )
  1368. {
  1369. using namespace std;
  1370. const ios_base::iostate ok = ios_base::goodbit;
  1371. ios_base::iostate err = ok;
  1372. typename basic_ostream< Ch, Tr >::sentry cerberos( os );
  1373. if ( cerberos ) {
  1374. const Ch zero = os.widen( '0' );
  1375. const Ch one = os.widen( '1' );
  1376. BOOST_TRY
  1377. {
  1378. typedef typename dynamic_bitset< Block, Alloc >::size_type bitset_size_type;
  1379. typedef basic_streambuf< Ch, Tr > buffer_type;
  1380. buffer_type * buf = os.rdbuf();
  1381. // careful: os.width() is signed (and can be < 0)
  1382. const bitset_size_type width = ( os.width() <= 0 ) ? 0 : static_cast< bitset_size_type >( os.width() );
  1383. streamsize npad = ( width <= b.size() ) ? 0 : width - b.size();
  1384. const Ch fill_char = os.fill();
  1385. const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield;
  1386. // if needed fill at left; pad is decreased along the way
  1387. if ( adjustfield != ios_base::left ) {
  1388. for ( ; 0 < npad; --npad ) {
  1389. if ( Tr::eq_int_type( Tr::eof(), buf->sputc( fill_char ) ) ) {
  1390. err |= ios_base::failbit;
  1391. break;
  1392. }
  1393. }
  1394. }
  1395. if ( err == ok ) {
  1396. // output the bitset
  1397. for ( bitset_size_type i = b.size(); 0 < i; --i ) {
  1398. typename buffer_type::int_type
  1399. ret = buf->sputc( b.test( i - 1 ) ? one : zero );
  1400. if ( Tr::eq_int_type( Tr::eof(), ret ) ) {
  1401. err |= ios_base::failbit;
  1402. break;
  1403. }
  1404. }
  1405. }
  1406. if ( err == ok ) {
  1407. // if needed fill at right
  1408. for ( ; 0 < npad; --npad ) {
  1409. if ( Tr::eq_int_type( Tr::eof(), buf->sputc( fill_char ) ) ) {
  1410. err |= ios_base::failbit;
  1411. break;
  1412. }
  1413. }
  1414. }
  1415. os.width( 0 );
  1416. }
  1417. BOOST_CATCH( ... )
  1418. {
  1419. bool rethrow = false;
  1420. BOOST_TRY
  1421. {
  1422. os.setstate( ios_base::badbit );
  1423. }
  1424. BOOST_CATCH( ... )
  1425. {
  1426. rethrow = true;
  1427. }
  1428. BOOST_CATCH_END
  1429. if ( rethrow ) {
  1430. BOOST_RETHROW
  1431. }
  1432. }
  1433. BOOST_CATCH_END
  1434. }
  1435. if ( err != ok ) {
  1436. os.setstate( err ); // may throw exception
  1437. }
  1438. return os;
  1439. }
  1440. template< typename Ch, typename Tr, typename Block, typename Alloc >
  1441. std::basic_istream< Ch, Tr > &
  1442. operator>>( std::basic_istream< Ch, Tr > & is, dynamic_bitset< Block, Alloc > & b )
  1443. {
  1444. using namespace std;
  1445. typedef dynamic_bitset< Block, Alloc > bitset_type;
  1446. typedef typename bitset_type::size_type size_type;
  1447. const streamsize w = is.width();
  1448. const size_type limit = 0 < w && static_cast< size_type >( w ) < b.max_size() ? static_cast< size_type >( w ) : b.max_size();
  1449. bool exceptions_are_from_vector = false;
  1450. ios_base::iostate err = ios_base::goodbit;
  1451. typename basic_istream< Ch, Tr >::sentry cerberos( is ); // skips whitespace
  1452. if ( cerberos ) {
  1453. // in accordance with the resolution of library issue 303
  1454. const Ch zero = is.widen( '0' );
  1455. const Ch one = is.widen( '1' );
  1456. b.clear();
  1457. BOOST_TRY
  1458. {
  1459. typename bitset_type::bit_appender appender( b );
  1460. basic_streambuf< Ch, Tr > * buf = is.rdbuf();
  1461. typename Tr::int_type c = buf->sgetc();
  1462. for ( ; appender.get_count() < limit; c = buf->snextc() ) {
  1463. if ( Tr::eq_int_type( Tr::eof(), c ) ) {
  1464. err |= ios_base::eofbit;
  1465. break;
  1466. } else {
  1467. const Ch to_c = Tr::to_char_type( c );
  1468. const bool is_one = Tr::eq( to_c, one );
  1469. if ( ! is_one && ! Tr::eq( to_c, zero ) ) {
  1470. break; // non digit character
  1471. }
  1472. exceptions_are_from_vector = true;
  1473. appender.do_append( is_one );
  1474. exceptions_are_from_vector = false;
  1475. }
  1476. } // for
  1477. }
  1478. BOOST_CATCH( ... )
  1479. {
  1480. // catches from stream buf, or from vector:
  1481. //
  1482. // bits_stored bits have been extracted and stored, and
  1483. // either no further character is extractable or we can't
  1484. // append to the underlying vector (out of memory)
  1485. if ( exceptions_are_from_vector ) {
  1486. BOOST_RETHROW
  1487. }
  1488. bool rethrow = false;
  1489. BOOST_TRY
  1490. {
  1491. is.setstate( ios_base::badbit );
  1492. }
  1493. BOOST_CATCH( ... )
  1494. {
  1495. rethrow = true;
  1496. }
  1497. BOOST_CATCH_END
  1498. if ( rethrow ) {
  1499. BOOST_RETHROW
  1500. }
  1501. }
  1502. BOOST_CATCH_END
  1503. }
  1504. is.width( 0 );
  1505. if ( b.size() == 0 /*|| !cerberos*/ ) {
  1506. err |= ios_base::failbit;
  1507. }
  1508. if ( err != ios_base::goodbit ) {
  1509. is.setstate( err ); // may throw
  1510. }
  1511. return is;
  1512. }
  1513. //-----------------------------------------------------------------------------
  1514. // bitset operations
  1515. template< typename Block, typename AllocatorOrContainer >
  1516. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  1517. operator&( const dynamic_bitset< Block, AllocatorOrContainer > & x, const dynamic_bitset< Block, AllocatorOrContainer > & y )
  1518. {
  1519. dynamic_bitset< Block, AllocatorOrContainer > b( x );
  1520. return b &= y;
  1521. }
  1522. template< typename Block, typename AllocatorOrContainer >
  1523. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  1524. operator|( const dynamic_bitset< Block, AllocatorOrContainer > & x, const dynamic_bitset< Block, AllocatorOrContainer > & y )
  1525. {
  1526. dynamic_bitset< Block, AllocatorOrContainer > b( x );
  1527. return b |= y;
  1528. }
  1529. template< typename Block, typename AllocatorOrContainer >
  1530. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  1531. operator^( const dynamic_bitset< Block, AllocatorOrContainer > & x, const dynamic_bitset< Block, AllocatorOrContainer > & y )
  1532. {
  1533. dynamic_bitset< Block, AllocatorOrContainer > b( x );
  1534. return b ^= y;
  1535. }
  1536. template< typename Block, typename AllocatorOrContainer >
  1537. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer >
  1538. operator-( const dynamic_bitset< Block, AllocatorOrContainer > & x, const dynamic_bitset< Block, AllocatorOrContainer > & y )
  1539. {
  1540. dynamic_bitset< Block, AllocatorOrContainer > b( x );
  1541. return b -= y;
  1542. }
  1543. //-----------------------------------------------------------------------------
  1544. // namespace scope swap
  1545. template< typename Block, typename AllocatorOrContainer >
  1546. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1547. swap( dynamic_bitset< Block, AllocatorOrContainer > & a, dynamic_bitset< Block, AllocatorOrContainer > & b ) noexcept
  1548. {
  1549. a.swap( b );
  1550. }
  1551. template< typename Block, typename AllocatorOrContainer >
  1552. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1553. dynamic_bitset< Block, AllocatorOrContainer >::m_unchecked_test( size_type pos ) const
  1554. {
  1555. return ( m_bits[ block_index( pos ) ] & bit_mask( pos ) ) != 0;
  1556. }
  1557. template< typename Block, typename AllocatorOrContainer >
  1558. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1559. dynamic_bitset< Block, AllocatorOrContainer >::calc_num_blocks( size_type num_bits )
  1560. {
  1561. return num_bits / bits_per_block
  1562. + static_cast< size_type >( num_bits % bits_per_block != 0 );
  1563. }
  1564. // gives a reference to the highest block
  1565. //
  1566. template< typename Block, typename AllocatorOrContainer >
  1567. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block &
  1568. dynamic_bitset< Block, AllocatorOrContainer >::m_highest_block()
  1569. {
  1570. return const_cast< Block & >( static_cast< const dynamic_bitset * >( this )->m_highest_block() );
  1571. }
  1572. // gives a const-reference to the highest block
  1573. //
  1574. template< typename Block, typename AllocatorOrContainer >
  1575. BOOST_DYNAMIC_BITSET_CONSTEXPR20 const Block &
  1576. dynamic_bitset< Block, AllocatorOrContainer >::m_highest_block() const
  1577. {
  1578. BOOST_ASSERT( num_blocks() > 0 );
  1579. return m_bits.back();
  1580. }
  1581. template< typename Block, typename AllocatorOrContainer >
  1582. BOOST_DYNAMIC_BITSET_CONSTEXPR20 dynamic_bitset< Block, AllocatorOrContainer > &
  1583. dynamic_bitset< Block, AllocatorOrContainer >::range_operation(
  1584. size_type pos, size_type len, Block ( *partial_block_operation )( Block, size_type, size_type ), Block ( *full_block_operation )( Block ) )
  1585. {
  1586. BOOST_ASSERT( pos + len <= m_num_bits );
  1587. // Do nothing in case of zero length
  1588. if ( ! len ) {
  1589. return *this;
  1590. }
  1591. // Use an additional asserts in order to detect size_type overflow
  1592. // For example: pos = 10, len = size_type_limit - 2, pos + len = 7
  1593. // In case of overflow, 'pos + len' is always smaller than 'len'
  1594. BOOST_ASSERT( pos + len >= len );
  1595. // Start and end blocks of the [pos; pos + len - 1] sequence
  1596. const size_type first_block = block_index( pos );
  1597. const size_type last_block = block_index( pos + len - 1 );
  1598. const size_type first_bit_index = bit_index( pos );
  1599. const size_type last_bit_index = bit_index( pos + len - 1 );
  1600. if ( first_block == last_block ) {
  1601. // Filling only a sub-block of a block
  1602. m_bits[ first_block ] = partial_block_operation( m_bits[ first_block ], first_bit_index, last_bit_index );
  1603. } else {
  1604. // Check if the corner blocks won't be fully filled with 'val'
  1605. const size_type first_block_shift = bit_index( pos ) ? 1 : 0;
  1606. const size_type last_block_shift = ( bit_index( pos + len - 1 )
  1607. == bits_per_block - 1 )
  1608. ? 0
  1609. : 1;
  1610. // Blocks that will be filled with ~0 or 0 at once
  1611. const size_type first_full_block = first_block + first_block_shift;
  1612. const size_type last_full_block = last_block - last_block_shift;
  1613. for ( size_type i = first_full_block; i <= last_full_block; ++i ) {
  1614. m_bits[ i ] = full_block_operation( m_bits[ i ] );
  1615. }
  1616. // Fill the first block from the 'first' bit index to the end
  1617. if ( first_block_shift ) {
  1618. m_bits[ first_block ] = partial_block_operation( m_bits[ first_block ], first_bit_index, bits_per_block - 1 );
  1619. }
  1620. // Fill the last block from the start to the 'last' bit index
  1621. if ( last_block_shift ) {
  1622. m_bits[ last_block ] = partial_block_operation( m_bits[ last_block ], 0, last_bit_index );
  1623. }
  1624. }
  1625. return *this;
  1626. }
  1627. // If size() is not a multiple of bits_per_block then not all the bits
  1628. // in the last block are used. This function resets the unused bits
  1629. // (convenient for the implementation of many member functions).
  1630. template< typename Block, typename AllocatorOrContainer >
  1631. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1632. dynamic_bitset< Block, AllocatorOrContainer >::m_zero_unused_bits()
  1633. {
  1634. BOOST_ASSERT( num_blocks() == calc_num_blocks( m_num_bits ) );
  1635. // if != 0, this is the number of bits used in the last block.
  1636. const int extra_bits = count_extra_bits();
  1637. if ( extra_bits != 0 ) {
  1638. m_highest_block() &= ( Block( 1 ) << extra_bits ) - 1;
  1639. }
  1640. }
  1641. // check class invariants
  1642. template< typename Block, typename AllocatorOrContainer >
  1643. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1644. dynamic_bitset< Block, AllocatorOrContainer >::m_check_invariants() const
  1645. {
  1646. const int extra_bits = count_extra_bits();
  1647. if ( extra_bits > 0 ) {
  1648. const block_type mask = Block( -1 ) << extra_bits;
  1649. if ( ( m_highest_block() & mask ) != 0 ) {
  1650. return false;
  1651. }
  1652. }
  1653. if ( m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks( size() ) ) {
  1654. return false;
  1655. }
  1656. return true;
  1657. }
  1658. template< typename Block, typename AllocatorOrContainer >
  1659. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1660. dynamic_bitset< Block, AllocatorOrContainer >::m_not_empty( Block x )
  1661. {
  1662. return x != Block( 0 );
  1663. }
  1664. template< typename Block, typename AllocatorOrContainer >
  1665. BOOST_DYNAMIC_BITSET_CONSTEXPR20 bool
  1666. dynamic_bitset< Block, AllocatorOrContainer >::m_not_full( Block x )
  1667. {
  1668. return x != Block( -1 );
  1669. }
  1670. template< typename Block, typename AllocatorOrContainer >
  1671. BOOST_DYNAMIC_BITSET_CONSTEXPR20 int
  1672. dynamic_bitset< Block, AllocatorOrContainer >::count_extra_bits() const noexcept
  1673. {
  1674. return bit_index( size() );
  1675. }
  1676. template< typename Block, typename AllocatorOrContainer >
  1677. BOOST_DYNAMIC_BITSET_CONSTEXPR20 typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1678. dynamic_bitset< Block, AllocatorOrContainer >::block_index( size_type pos ) noexcept
  1679. {
  1680. return pos / bits_per_block;
  1681. }
  1682. template< typename Block, typename AllocatorOrContainer >
  1683. BOOST_DYNAMIC_BITSET_CONSTEXPR20 int
  1684. dynamic_bitset< Block, AllocatorOrContainer >::bit_index( size_type pos ) noexcept
  1685. {
  1686. return static_cast< int >( pos % bits_per_block );
  1687. }
  1688. template< typename Block, typename AllocatorOrContainer >
  1689. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1690. dynamic_bitset< Block, AllocatorOrContainer >::bit_mask( size_type pos ) noexcept
  1691. {
  1692. return Block( 1 ) << bit_index( pos );
  1693. }
  1694. template< typename Block, typename AllocatorOrContainer >
  1695. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1696. dynamic_bitset< Block, AllocatorOrContainer >::bit_mask( size_type first, size_type last ) noexcept
  1697. {
  1698. Block res = ( last == bits_per_block - 1 )
  1699. ? Block( -1 )
  1700. : ( ( Block( 1 ) << ( last + 1 ) ) - 1 );
  1701. res ^= ( Block( 1 ) << first ) - 1;
  1702. return res;
  1703. }
  1704. template< typename Block, typename AllocatorOrContainer >
  1705. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1706. dynamic_bitset< Block, AllocatorOrContainer >::set_block_bits(
  1707. Block block,
  1708. size_type first,
  1709. size_type last,
  1710. bool val ) noexcept
  1711. {
  1712. if ( val ) {
  1713. return block | bit_mask( first, last );
  1714. } else {
  1715. return block & static_cast< Block >( ~bit_mask( first, last ) );
  1716. }
  1717. }
  1718. // Functions for operations on ranges
  1719. template< typename Block, typename AllocatorOrContainer >
  1720. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1721. dynamic_bitset< Block, AllocatorOrContainer >::set_block_partial(
  1722. Block block,
  1723. size_type first,
  1724. size_type last ) noexcept
  1725. {
  1726. return set_block_bits( block, first, last, true );
  1727. }
  1728. template< typename Block, typename AllocatorOrContainer >
  1729. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1730. dynamic_bitset< Block, AllocatorOrContainer >::set_block_full( Block ) noexcept
  1731. {
  1732. return Block( -1 );
  1733. }
  1734. template< typename Block, typename AllocatorOrContainer >
  1735. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1736. dynamic_bitset< Block, AllocatorOrContainer >::reset_block_partial(
  1737. Block block,
  1738. size_type first,
  1739. size_type last ) noexcept
  1740. {
  1741. return set_block_bits( block, first, last, false );
  1742. }
  1743. template< typename Block, typename AllocatorOrContainer >
  1744. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1745. dynamic_bitset< Block, AllocatorOrContainer >::reset_block_full( Block ) noexcept
  1746. {
  1747. return 0;
  1748. }
  1749. template< typename Block, typename AllocatorOrContainer >
  1750. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1751. dynamic_bitset< Block, AllocatorOrContainer >::flip_block_partial(
  1752. Block block,
  1753. size_type first,
  1754. size_type last ) noexcept
  1755. {
  1756. return block ^ bit_mask( first, last );
  1757. }
  1758. template< typename Block, typename AllocatorOrContainer >
  1759. BOOST_DYNAMIC_BITSET_CONSTEXPR20 Block
  1760. dynamic_bitset< Block, AllocatorOrContainer >::flip_block_full( Block block ) noexcept
  1761. {
  1762. return ~block;
  1763. }
  1764. template< typename Block, typename AllocatorOrContainer >
  1765. template< typename T >
  1766. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1767. dynamic_bitset< Block, AllocatorOrContainer >::dispatch_init(
  1768. T num_bits,
  1769. unsigned long value,
  1770. detail::dynamic_bitset_impl::value_to_type< true > )
  1771. {
  1772. init_from_unsigned_long( static_cast< size_type >( num_bits ), value );
  1773. }
  1774. template< typename Block, typename AllocatorOrContainer >
  1775. template< typename T >
  1776. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1777. dynamic_bitset< Block, AllocatorOrContainer >::dispatch_init(
  1778. T first,
  1779. T last,
  1780. detail::dynamic_bitset_impl::value_to_type< false > )
  1781. {
  1782. init_from_block_range( first, last );
  1783. }
  1784. template< typename Block, typename AllocatorOrContainer >
  1785. template< typename BlockIter >
  1786. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1787. dynamic_bitset< Block, AllocatorOrContainer >::init_from_block_range( BlockIter first, BlockIter last )
  1788. {
  1789. BOOST_ASSERT( m_bits.size() == 0 );
  1790. m_bits.insert( m_bits.end(), first, last );
  1791. m_num_bits = m_bits.size() * bits_per_block;
  1792. }
  1793. template< typename Block, typename AllocatorOrContainer >
  1794. template< typename CharT, typename Traits >
  1795. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1796. dynamic_bitset< Block, AllocatorOrContainer >::init_from_string(
  1797. const CharT * s, // caution: not necessarily null-terminated
  1798. std::size_t string_length,
  1799. std::size_t pos,
  1800. std::size_t n,
  1801. size_type num_bits )
  1802. {
  1803. BOOST_ASSERT( pos <= string_length );
  1804. const std::size_t rlen = (std::min)( n, string_length - pos );
  1805. const size_type sz = ( num_bits != npos ? num_bits : rlen );
  1806. m_bits.resize( calc_num_blocks( sz ) );
  1807. m_num_bits = sz;
  1808. const std::ctype< CharT > & fac = std::use_facet< std::ctype< CharT > >( std::locale() );
  1809. const CharT one = fac.widen( '1' );
  1810. const size_type m = num_bits < rlen ? num_bits : rlen;
  1811. for ( std::size_t i = 0; i < m; ++i ) {
  1812. const CharT c = s[ ( pos + m - 1 ) - i ];
  1813. if ( Traits::eq( c, one ) ) {
  1814. set( i );
  1815. } else {
  1816. BOOST_ASSERT( Traits::eq( c, fac.widen( '0' ) ) );
  1817. }
  1818. }
  1819. }
  1820. template< typename Block, typename AllocatorOrContainer >
  1821. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1822. dynamic_bitset< Block, AllocatorOrContainer >::init_from_unsigned_long(
  1823. size_type num_bits,
  1824. unsigned long value )
  1825. {
  1826. BOOST_ASSERT( m_bits.size() == 0 );
  1827. m_bits.resize( calc_num_blocks( num_bits ) );
  1828. m_num_bits = num_bits;
  1829. typedef unsigned long num_type;
  1830. typedef boost::detail::dynamic_bitset_impl::shifter< num_type, bits_per_block, ulong_width > shifter;
  1831. // if (num_bits == 0)
  1832. // return;
  1833. // zero out all bits at pos >= num_bits, if any;
  1834. // note that: num_bits == 0 implies value == 0
  1835. if ( num_bits < static_cast< size_type >( ulong_width ) ) {
  1836. const num_type mask = ( num_type( 1 ) << num_bits ) - 1;
  1837. value &= mask;
  1838. }
  1839. typename buffer_type::iterator it = m_bits.begin();
  1840. for ( ; value; shifter::left_shift( value ), ++it ) {
  1841. *it = static_cast< block_type >( value );
  1842. }
  1843. }
  1844. template< typename Block, typename AllocatorOrContainer >
  1845. template< typename BlockInputIterator >
  1846. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1847. dynamic_bitset< Block, AllocatorOrContainer >::m_append( BlockInputIterator first, BlockInputIterator last, std::input_iterator_tag )
  1848. {
  1849. for ( ; first != last; ++first ) {
  1850. append( *first );
  1851. }
  1852. }
  1853. template< typename Block, typename AllocatorOrContainer >
  1854. template< typename BlockInputIterator >
  1855. BOOST_DYNAMIC_BITSET_CONSTEXPR20 void
  1856. dynamic_bitset< Block, AllocatorOrContainer >::m_append( BlockInputIterator first, BlockInputIterator last, std::forward_iterator_tag )
  1857. {
  1858. if ( first != last ) {
  1859. const int r = count_extra_bits();
  1860. const std::size_t d = std::distance( first, last );
  1861. m_bits.reserve( num_blocks() + d );
  1862. if ( r == 0 ) {
  1863. do {
  1864. m_bits.push_back( *first ); // could use vector<>::insert()
  1865. ++first;
  1866. } while ( first != last );
  1867. } else {
  1868. m_highest_block() |= ( *first << r );
  1869. do {
  1870. Block b = *first >> ( bits_per_block - r );
  1871. ++first;
  1872. m_bits.push_back( b | ( first == last ? 0 : *first << r ) );
  1873. } while ( first != last );
  1874. }
  1875. m_num_bits += bits_per_block * d;
  1876. }
  1877. }
  1878. // bit appender
  1879. template< typename Block, typename AllocatorOrContainer >
  1880. dynamic_bitset< Block, AllocatorOrContainer >::bit_appender::bit_appender( dynamic_bitset & r )
  1881. : bs( r ), n( 0 ), mask( 0 ), current( 0 )
  1882. {
  1883. }
  1884. template< typename Block, typename AllocatorOrContainer >
  1885. dynamic_bitset< Block, AllocatorOrContainer >::bit_appender::~bit_appender()
  1886. {
  1887. // Reverse the order of the blocks, shift if needed, and then
  1888. // resize.
  1889. //
  1890. std::reverse( bs.m_bits.begin(), bs.m_bits.end() );
  1891. const int offs = bit_index( n );
  1892. if ( offs ) {
  1893. bs >>= ( bits_per_block - offs );
  1894. }
  1895. bs.resize( n ); // doesn't enlarge, so can't throw
  1896. BOOST_ASSERT( bs.m_check_invariants() );
  1897. }
  1898. template< typename Block, typename AllocatorOrContainer >
  1899. void
  1900. dynamic_bitset< Block, AllocatorOrContainer >::bit_appender::do_append( bool value )
  1901. {
  1902. if ( mask == 0 ) {
  1903. bs.append( Block( 0 ) );
  1904. current = &bs.m_highest_block();
  1905. mask = Block( 1 ) << ( bits_per_block - 1 );
  1906. }
  1907. if ( value ) {
  1908. *current |= mask;
  1909. }
  1910. mask /= 2;
  1911. ++n;
  1912. }
  1913. template< typename Block, typename AllocatorOrContainer >
  1914. typename dynamic_bitset< Block, AllocatorOrContainer >::size_type
  1915. dynamic_bitset< Block, AllocatorOrContainer >::bit_appender::get_count() const
  1916. {
  1917. return n;
  1918. }
  1919. } // namespace boost
  1920. // std::hash support
  1921. #if defined( BOOST_DYNAMIC_BITSET_SPECIALIZE_STD_HASH )
  1922. namespace std {
  1923. template< typename Block, typename AllocatorOrContainer >
  1924. struct hash< boost::dynamic_bitset< Block, AllocatorOrContainer > >
  1925. {
  1926. typedef boost::dynamic_bitset< Block, AllocatorOrContainer > argument_type;
  1927. typedef std::size_t result_type;
  1928. result_type
  1929. operator()( const argument_type & a ) const noexcept
  1930. {
  1931. boost::hash< argument_type > hasher;
  1932. return hasher( a );
  1933. }
  1934. };
  1935. }
  1936. #endif