#ifndef PAIREDDBG_DINUC_H #define PAIREDDBG_DINUC_H 1 #include "Common/BitUtil.h" #include #include /** A pair of nucleotides. */ class Dinuc { public: /** The number of symbols. */ static const unsigned NUM = 16; /** A nucleotide. A bit vector of two bits. */ typedef uint8_t Nuc; /** A dinucleotide. A bit vector of four bits. */ typedef uint8_t Bits; /** Default constructor. */ Dinuc() { } /** Construct a Dinuc from two nucleotides. */ Dinuc(Nuc a, Nuc b) : m_data(a | (b << 2)) { } /** Construct a Dinuc from an integer. */ explicit Dinuc(Bits x) : m_data(x) { } /** Cast to an integer. */ Bits toInt() const { return m_data; } /** Return the first nucleotide. */ Nuc a() const { return m_data & 0x3; } /** Return the first nucleotide. */ Nuc b() const { return (m_data >> 2) & 0x3; } /** Compare two dinucleotides. */ bool operator<(const Dinuc& x) const { return m_data < x.m_data; } /** Complement a single base. */ static Nuc complementNuc(Nuc x) { return 3 - x; } /** Return the reverse complement of this dinucleotide. */ Dinuc reverseComplement() const { return Dinuc(complementNuc(b()), complementNuc(a())); } /** Increment this dinucleotide. */ Dinuc& operator++() { ++m_data; return *this; } /** Return the first dinucleotide. */ static Dinuc begin() { return Dinuc(0); } /** Return the last dinucleotide. */ static Dinuc end() { return Dinuc(NUM); } private: /** Two nucleotides packed into a single scalar. */ Bits m_data; }; /** Return the reverse complement of this dinucleotide. */ static inline Dinuc reverseComplement(const Dinuc& x) { return x.reverseComplement(); } /** A set of dinucleotides. */ class DinucSet { public: typedef Dinuc Symbol; /** The number of symbols. */ static const unsigned NUM = Dinuc::NUM; /** A bit vector. */ typedef uint16_t Bits; /** Default constructor. */ DinucSet() : m_data(0) { } /** Construct a set containing a single element. */ DinucSet(const Dinuc& x) : m_data(1 << x.toInt()) { } /** Return a set with the specified bits set. */ static DinucSet mask(Bits x) { DinucSet s; s.m_data = x; return s; } /** Return whether the specified element is present in this set. */ bool checkBase(const Dinuc& x) const { return m_data & (1 << x.toInt()); } /** Return the number of elements in this set. */ unsigned outDegree() const { return popcount(m_data); } /** Return whether this set is non-empty. */ bool hasExtension() const { return m_data != 0; } /** Return whether this set has two or more elements. */ bool isAmbiguous() const { return outDegree() > 1; } /** Add the specified element to this set. */ void setBase(const Dinuc& x) { m_data |= 1 << x.toInt(); } /** Remove all elements from this set. */ void clear() { m_data = 0; } /** Remove the specified elements from this set. */ void clear(const DinucSet& x) { m_data &= ~x.m_data; } /** Return the complementary nucleotides of this set. */ DinucSet complement() const { DinucSet x; for (Dinuc i = Dinuc::begin(); i < Dinuc::end(); ++i) { if (checkBase(i)) x.setBase(i.reverseComplement()); } return x; } bool operator==(const DinucSet& x) const { return m_data == x.m_data; } private: /** A bit vector representing a set. */ Bits m_data; }; #endif