SDSL: Succinct Data Structure Library
A C++ template library for succinct data structures
|
00001 /* sdsl - succinct data structures library 00002 Copyright (C) 2012 Simon Gog 00003 00004 This program is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program. If not, see http://www.gnu.org/licenses/ . 00016 */ 00021 #ifndef INCLUDED_SDSL_UINT256 00022 #define INCLUDED_SDSL_UINT256 00023 00024 #include <iostream> 00025 #include "bitmagic.hpp" 00026 #include "uint128_t.hpp" 00027 00028 namespace sdsl 00029 { 00030 00031 class uint256_t 00032 { 00033 public: 00034 friend std::ostream& operator << (std::ostream&, const uint256_t&); 00035 private: 00036 uint64_t m_lo; 00037 uint64_t m_mid; 00038 uint128_t m_high; 00039 00040 public: 00041 uint256_t(uint64_t lo=0, uint64_t mid=0, 00042 uint128_t high=0):m_lo(lo), 00043 m_mid(mid), 00044 m_high(high) {} 00045 00046 uint256_t(const uint256_t& x):m_lo(x.m_lo), m_mid(x.m_mid), m_high(x.m_high) {} 00047 00048 uint16_t popcount() { 00049 return ((uint16_t)bit_magic::b1Cnt(m_lo)) + bit_magic::b1Cnt(m_mid) 00050 + bit_magic::b1Cnt(m_high>>64) + bit_magic::b1Cnt(m_high); 00051 } 00052 00053 uint16_t l1BP() { 00054 if (m_high == 0) { 00055 if (m_mid) { 00056 return bit_magic::l1BP(m_mid) + 64; 00057 } else { 00058 return bit_magic::l1BP(m_lo); 00059 } 00060 } else { 00061 uint64_t hh = (m_high >> 64); 00062 if (hh) { 00063 return bit_magic::l1BP(hh) + 192; 00064 } else { 00065 return bit_magic::l1BP(m_high) + 128; 00066 } 00067 } 00068 } 00069 00070 uint16_t select(uint32_t i) { 00071 uint16_t x = 0; 00072 if ((x=bit_magic::b1Cnt(m_lo)) >= i) { 00073 return bit_magic::i1BP(m_lo, i); 00074 } 00075 i -= x; 00076 if ((x=bit_magic::b1Cnt(m_mid)) >= i) { 00077 return bit_magic::i1BP(m_mid, i) + 64; 00078 } 00079 i -= x; 00080 uint64_t hh = m_high >> 64; 00081 uint64_t lh = m_high; 00082 if ((x=bit_magic::b1Cnt(lh)) >= i) { 00083 return bit_magic::i1BP(lh, i) + 128; 00084 } 00085 i -= x; 00086 return bit_magic::i1BP(hh, i) + 192; 00087 } 00088 00089 uint256_t& operator+=(const uint256_t& x) { 00090 uint128_t lo = (uint128_t)m_lo + x.m_lo; 00091 uint128_t mid = (uint128_t)m_mid + x.m_mid + (lo >> 64); 00092 m_lo = lo; m_mid = mid; 00093 m_high += x.m_high + (mid >> 64); 00094 return *this; 00095 // return uint256_t(lo, mid, m_high + x.m_high + (mid >> 64)); 00096 } 00097 00098 uint256_t operator+(uint256_t x) { 00099 uint128_t lo = (uint128_t)m_lo + x.m_lo; 00100 uint128_t mid = (uint128_t)m_mid + x.m_mid + (lo >> 64); 00101 return uint256_t(lo, mid, m_high + x.m_high + (mid >> 64)); 00102 } 00103 00104 uint256_t operator-(uint256_t x) { 00105 // add two's complement of x 00106 uint128_t lo = (uint128_t)m_lo + (~x.m_lo) + 1; 00107 uint128_t mid = (uint128_t)m_mid + (~x.m_mid) + (lo >> 64); 00108 return uint256_t(lo, mid, m_high + (~x.m_high) + (mid >> 64)); 00109 } 00110 00111 uint256_t& operator-=(const uint256_t& x) { 00112 // add two's complement of x 00113 uint128_t lo = (uint128_t)m_lo + (~x.m_lo) + 1; 00114 uint128_t mid = (uint128_t)m_mid + (~x.m_mid) + (lo >> 64); 00115 m_lo = lo; 00116 m_mid = mid; 00117 m_high += (~x.m_high) + (mid >> 64); 00118 return *this; 00119 } 00120 00121 00122 uint256_t operator|(const uint256_t& x) { 00123 return uint256_t(m_lo|x.m_lo, m_mid|x.m_mid, m_high|x.m_high); 00124 } 00125 00126 uint256_t& operator|=(const uint256_t& x) { 00127 m_lo |= x.m_lo; m_mid |= x.m_mid; m_high |= x.m_high; 00128 return *this; 00129 } 00130 00131 uint256_t operator&(const uint256_t& x) { 00132 return uint256_t(m_lo&x.m_lo, m_mid&x.m_mid, m_high&x.m_high); 00133 } 00134 /* // is not needed since we can convert uint256_t to uint64_t 00135 uint64_t operator&(uint64_t x){ 00136 return m_lo & x; 00137 } 00138 */ 00139 00140 uint256_t operator<<(int x) { 00141 if (x < 128) { 00142 uint128_t high = m_high << x; 00143 uint128_t low = (((uint128_t)m_mid<<64) | m_lo); 00144 high |= (low >> (128-x)); 00145 low = low << x; 00146 return uint256_t(low, low>>64, high); 00147 } else { // x >= 128 00148 uint128_t high = (((uint128_t)m_mid<<64) | m_lo) << (x-128); // TODO: check x==128 00149 return uint256_t(0, 0, high); 00150 } 00151 } 00152 00153 uint256_t operator>>(int x) { 00154 if (x < 128) { 00155 uint128_t low = (((uint128_t)m_mid<<64) | m_lo) >> x; 00156 low |= ((m_high << (127-x))<<1); 00157 return uint256_t(low, low>>64, m_high>>x); 00158 } else { // x >= 128 00159 uint128_t low = (m_high >> (x-128)); // TODO: check x=128 00160 return uint256_t(low, low>>64, 0); 00161 } 00162 } 00163 00164 uint256_t& operator=(const uint64_t& x) { 00165 m_high = 0; 00166 m_mid = 0; 00167 m_lo = x; 00168 return *this; 00169 } 00170 00171 bool operator==(const uint256_t& x) const { 00172 return (m_lo == x.m_lo) and (m_mid == x.m_mid) and (m_high == x.m_high); 00173 } 00174 00175 bool operator!=(const uint256_t& x) const { 00176 return !(*this == x); 00177 } 00178 00179 bool operator>=(const uint256_t& x) const { 00180 if (m_high != x.m_high) { 00181 return m_high > x.m_high; 00182 } 00183 if (m_mid != x.m_mid) { 00184 return m_mid > x.m_mid; 00185 } else { 00186 return m_lo >= x.m_lo; 00187 } 00188 } 00189 00190 bool operator<=(const uint256_t& x) const { 00191 if (m_high != x.m_high) { 00192 return m_high < x.m_high; 00193 } 00194 if (m_mid != x.m_mid) { 00195 return m_mid < x.m_mid; 00196 } else { 00197 return m_lo <= x.m_lo; 00198 } 00199 } 00200 00201 bool operator>(const uint256_t& x) const { 00202 if (m_high != x.m_high) { 00203 return m_high > x.m_high; 00204 } 00205 if (m_mid != x.m_mid) { 00206 return m_mid > x.m_mid; 00207 } else { 00208 return m_lo > x.m_lo; 00209 } 00210 } 00211 00212 bool operator>(const uint64_t& x) const { 00213 if (m_high > 0 or m_mid > 0) { 00214 return true; 00215 } 00216 return m_lo > x; 00217 } 00218 00219 bool operator<(const uint256_t& x) const { 00220 if (m_high != x.m_high) { 00221 return m_high < x.m_high; 00222 } 00223 if (m_mid != x.m_mid) { 00224 return m_mid < x.m_mid; 00225 } else { 00226 return m_lo < x.m_lo; 00227 } 00228 } 00229 00230 operator uint64_t() { 00231 return m_lo; 00232 } 00233 }; 00234 00235 std::ostream& operator<<(std::ostream& os, const uint256_t& x) 00236 { 00237 uint64_t X[4] = {(uint64_t)(x.m_high >> 64), (uint64_t)x.m_high, x.m_mid, x.m_lo}; 00238 for (int j=0; j < 4; ++j) { 00239 for (int i=0; i < 16; ++i) { 00240 os << std::hex << ((X[j]>>60)&0xFULL) << std::dec; 00241 X[j] <<= 4; 00242 } 00243 } 00244 return os; 00245 } 00246 00247 } // end namespace 00248 00249 #endif