const& _h)
	{
		return (*this |= _h.template bloomPart());
	}
	template  inline bool containsBloom(FixedHash const& _h)
	{
		return contains(_h.template bloomPart());
	}
	template  inline FixedHash bloomPart() const
	{
		unsigned const c_bloomBits = M * 8;
		unsigned const c_mask = c_bloomBits - 1;
		unsigned const c_bloomBytes = (StaticLog2::result + 7) / 8;
		static_assert((M & (M - 1)) == 0, "M must be power-of-two");
		static_assert(P * c_bloomBytes <= N, "out of range");
		FixedHash ret;
		byte const* p = data();
		for (unsigned i = 0; i < P; ++i)
		{
			unsigned index = 0;
			for (unsigned j = 0; j < c_bloomBytes; ++j, ++p)
				index = (index << 8) | *p;
			index &= c_mask;
			ret[M - 1 - index / 8] |= (1 << (index % 8));
		}
		return ret;
	}
	/// Returns the index of the first bit set to one, or size() * 8 if no bits are set.
	inline unsigned firstBitSet() const
	{
		unsigned ret = 0;
		for (auto d: m_data)
			if (d)
				for (;; ++ret, d <<= 1)
					if (d & 0x80)
						return ret;
					else {}
			else
				ret += 8;
		return ret;
	}
	void clear() { m_data.fill(0); }
private:
	std::array m_data;		///< The binary data.
};
/// Fast equality operator for h256.
template<> inline bool FixedHash<32>::operator==(FixedHash<32> const& _other) const
{
	const uint64_t* hash1 = (const uint64_t*)data();
	const uint64_t* hash2 = (const uint64_t*)_other.data();
	return (hash1[0] == hash2[0]) && (hash1[1] == hash2[1]) && (hash1[2] == hash2[2]) && (hash1[3] == hash2[3]);
}
/// Fast std::hash compatible hash function object for h256.
template<> inline size_t FixedHash<32>::hash::operator()(FixedHash<32> const& value) const
{
	uint64_t const* data = reinterpret_cast(value.data());
	return boost::hash_range(data, data + 4);
}
/// Stream I/O for the FixedHash class.
template 
inline std::ostream& operator<<(std::ostream& _out, FixedHash const& _h)
{
	_out << std::noshowbase << std::hex << std::setfill('0');
	for (unsigned i = 0; i < N; ++i)
		_out << std::setw(2) << (int)_h[i];
	_out << std::dec;
	return _out;
}
// Common types of FixedHash.
using h2048 = FixedHash<256>;
using h1024 = FixedHash<128>;
using h520 = FixedHash<65>;
using h512 = FixedHash<64>;
using h256 = FixedHash<32>;
using h160 = FixedHash<20>;
using h128 = FixedHash<16>;
using h64 = FixedHash<8>;
using h512s = std::vector;
using h256s = std::vector;
using h160s = std::vector;
using h256Set = std::set;
using h160Set = std::set;
using h256Hash = std::unordered_set;
using h160Hash = std::unordered_set;
/// Convert the given value into h160 (160-bit unsigned integer) using the right 20 bytes.
inline h160 right160(h256 const& _t)
{
	h160 ret;
	memcpy(ret.data(), _t.data() + 12, 20);
	return ret;
}
/// Convert the given value into h160 (160-bit unsigned integer) using the left 20 bytes.
inline h160 left160(h256 const& _t)
{
	h160 ret;
	memcpy(&ret[0], _t.data(), 20);
	return ret;
}
inline std::string toString(h256s const& _bs)
{
	std::ostringstream out;
	out << "[ ";
	for (auto i: _bs)
		out << i.abridged() << ", ";
	out << "]";
	return out.str();
}
}
namespace std
{
	/// Forward std::hash to dev::FixedHash::hash.
	template<> struct hash: dev::h64::hash {};
	template<> struct hash: dev::h128::hash {};
	template<> struct hash: dev::h160::hash {};
	template<> struct hash: dev::h256::hash {};
	template<> struct hash: dev::h512::hash {};
}