/* This file is part of Jellyfish.
Jellyfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jellyfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jellyfish. If not, see .
*/
#ifndef __JELLYFISH_MISC_HPP__
#define __JELLYFISH_MISC_HPP__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace jellyfish {
#define bsizeof(v) (8 * sizeof(v))
typedef uint_fast64_t uint_t;
//#define UINT_C(x)
#define PRIUINTu PRIuFAST64
#define PRIUINTx PRIxFAST64
inline int leading_zeroes(int x) { return __builtin_clz(x); } // CLK
inline int leading_zeroes(unsigned int x) { return __builtin_clz(x); }
inline int leading_zeroes(unsigned long x) { return __builtin_clzl(x); }
inline int leading_zeroes(unsigned long long x) { return __builtin_clzll(x); }
/// The floor of the log base two of n. Undefined if n == 0
template
uint16_t floorLog2(T n) {
return sizeof(T) * 8 - 1 - leading_zeroes(n);
}
/// The ceiling of the log base two of n. Undefined if n == 0
template
uint16_t ceilLog2(T n) {
uint16_t r = floorLog2(n);
return n > (((T)1) << r) ? r + 1 : r;
}
/// The ceiling of the quotient of the division of a by b. I.e. if b
/// divides a, then div_ceil(a, b) == a / b. Otherwise, div_ceil(a, b)
/// == a / b + 1
template
T div_ceil(T a, T b) {
T q = a / b;
return a % b == 0 ? q : q + 1;
}
/// Number of bits necessary to encode number n. Undefined if n ==
/// 0. The following should be true: 2^bitsize(n) - 1 >= n >
/// 2^(bitsize(n) - 1)
template
uint16_t bitsize(T n) {
return floorLog2(n) + 1;
}
inline uint32_t reverse_bits(uint32_t v) {
// swap odd and even bits
v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
// swap bytes
v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
// swap 2-byte long pairs
v = ( v >> 16 ) | ( v << 16);
return v;
}
inline uint64_t reverse_bits(uint64_t v) {
v = ((v >> 1) & 0x5555555555555555UL) | ((v & 0x5555555555555555UL) << 1);
v = ((v >> 2) & 0x3333333333333333UL) | ((v & 0x3333333333333333UL) << 2);
v = ((v >> 4) & 0x0F0F0F0F0F0F0F0FUL) | ((v & 0x0F0F0F0F0F0F0F0FUL) << 4);
v = ((v >> 8) & 0x00FF00FF00FF00FFUL) | ((v & 0x00FF00FF00FF00FFUL) << 8);
v = ((v >> 16) & 0x0000FFFF0000FFFFUL) | ((v & 0x0000FFFF0000FFFFUL) << 16);
v = ( v >> 32 ) | ( v << 32);
return v;
}
uint64_t bogus_sum(void *data, size_t len);
template
size_t bits_to_bytes(T bits) {
return (size_t)((bits / 8) + (bits % 8 != 0));
}
template
union Tptr {
void *v;
T *t;
};
template
T *calloc_align(size_t nmemb, size_t alignment) {
Tptr ptr;
if(posix_memalign(&ptr.v, alignment, sizeof(T) * nmemb) < 0)
throw std::bad_alloc();
return ptr.t;
}
/* Be pedantic about memory access. Any misaligned access will
* generate a BUS error.
*/
void disabled_misaligned_mem_access();
/* Raison d'etre of this version of mem_copy: It seems we have slow
* down due to misaligned cache accesses. glibc memcpy does unaligned
* memory accesses and crashes when they are disabled. This version
* does only aligned memory access (see above).
*/
template
void mem_copy(char *dest, const char *src, const T &len) {
// dumb copying char by char
for(T i = (T)0; i < len; ++i)
*dest++ = *src++;
}
/* Slice a large number (total) in almost equal parts. return [start,
end) corresponding to the ith part (0 <= i < number_of_slices)
*/
template
std::pair slice(T i, T number_of_slices, T total) {
const T slice_size = total / number_of_slices;
const T slice_remain = total % number_of_slices;
const T start = std::max((T)0,
std::min(total, i * slice_size + (i > 0 ? slice_remain : 0)));
const T end = std::max((T)0,
std::min(total, (i + 1) * slice_size + slice_remain));
return std::make_pair(start, end);
}
uint64_t random_bits(int length);
inline uint64_t random_bits() { return random_bits(64); }
// Quote string that could contain shell special characters
std::string quote_arg(const std::string& arg);
std::streamoff get_file_size(std::istream& is);
/// Find the first element for which the predicate p is false. The
/// input range [first, last) is assumed to be sorted according to the
/// predicate p: p(x) is false and p(y) is true implies x comes after
/// y in the input range. (I.e., the elements for which p(x) is true
/// come first followed by the elements for which p(x) is false).
template
ForwardIterator binary_search_first_false(ForwardIterator first, ForwardIterator last, Predicate p)
{
ForwardIterator it;
typename std::iterator_traits::difference_type count, step;
count = std::distance(first,last);
while(count>0) {
it = first; step = count / 2; std::advance(it,step);
if(p(*it)) {
first = ++it;
count -= step + 1;
} else
count=step;
}
return first;
}
/// An integer type which behaves like a random pointer to
/// itself. Meaning, with `it(5)`, then `*it == 5` and `*++it ==
/// 6`. In other words, it is a pointer to an array `a` initialized
/// with `a[i] = i`, except the array is not instantiated and does not
/// have a fixed size.
template
class pointer_integer : public std::iterator {
T x_;
typedef typename std::iterator super;
public:
typedef T value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
typedef typename super::iterator_category iterator_category;
pointer_integer() : x_(0) { }
explicit pointer_integer(T x) : x_(x) { }
pointer_integer(const pointer_integer& rhs) : x_(rhs.x_) { }
pointer_integer& operator=(const pointer_integer& rhs) {
x_ = rhs.x_;
return *this;
}
pointer_integer& operator++() { ++x_; return *this; }
pointer_integer operator++(int) {
pointer_integer res(*this);
++x_;
return res;
}
pointer_integer& operator--() { --x_; return *this; }
pointer_integer operator--(int) {
pointer_integer res(*this);
--x_;
return res;
}
bool operator==(const pointer_integer& rhs) const { return x_ == rhs.x_; }
bool operator!=(const pointer_integer& rhs) const { return x_ != rhs.x_; }
bool operator<(const pointer_integer& rhs) const { return x_ < rhs.x_; }
bool operator>(const pointer_integer& rhs) const { return x_ > rhs.x_; }
bool operator<=(const pointer_integer& rhs) const { return x_ <= rhs.x_; }
bool operator>=(const pointer_integer& rhs) const { return x_ >= rhs.x_; }
reference operator*() { return x_; }
pointer operator->() { return &x_; } // Probably useless
difference_type operator-(pointer_integer& rhs) { return x_ - rhs.x_; }
pointer_integer operator+(T x) const { return pointer_integer(x_ + x); }
pointer_integer operator-(T x) const { return pointer_integer(x_ - x); }
pointer_integer& operator+=(T x) { x_ += x; return *this; }
pointer_integer& operator-=(T x) { x_ -= x; return *this; }
value_type operator[](T i) const { return x_ + i; }
};
template
pointer_integer operator+(T x, pointer_integer& p) { return pointer_integer(x + *p); }
template
pointer_integer operator-(T x, pointer_integer& p) { return pointer_integer(x - *p); }
} // namespace jellyfish
#endif // __MISC_HPP__