// ========================================================================== // SeqAn - The Library for Sequence Analysis // ========================================================================== // Copyright (c) 2006-2018, Knut Reinert, FU Berlin // Copyright (c) 2013 NVIDIA Corporation // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of Knut Reinert or the FU Berlin nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // // ========================================================================== // Author: David Weese // ========================================================================== // Tuple base class. // ========================================================================== // TODO(holtgrew): What about move construction? Useful for pairs of strings and such. Tricky to implement since ints have no move constructor, for example. #ifndef SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_ #define SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_ namespace seqan { // ============================================================================ // Forwards // ============================================================================ // ============================================================================ // Tags, Classes, Enums // ============================================================================ template struct StoredTupleValue_ { typedef TValue Type; }; template struct StoredTupleValue_< SimpleType > { typedef TValue Type; }; /*! * @class Tuple * @headerfile * @brief A constant-size tuple of the same type. * * @signature template * class Tuple; * * @tparam TValue The value that the tuple should be over. * @tparam SIZE The number of entries in the tuple. * @tparam TSpec Specialization tag, optional; defaults to void. */ /*! * @fn Tuple::i * @brief Array of tuple value. * * @signature TValue Tuple::i[SIZE]; * * The array of the tuple's values. */ template struct Tuple { // ----------------------------------------------------------------------- // Members // ----------------------------------------------------------------------- typename StoredTupleValue_::Type i[SIZE]; // ----------------------------------------------------------------------- // Subscription Operators; Have to be declared in class. // ----------------------------------------------------------------------- // TODO(holtgrew): Return Value<>::Type? template inline typename StoredTupleValue_::Type & operator[](TPos k) { SEQAN_ASSERT_GEQ(static_cast(k), 0); SEQAN_ASSERT_LT(static_cast(k), static_cast(SIZE)); return i[k]; } template inline typename StoredTupleValue_::Type const & operator[](TPos k) const { SEQAN_ASSERT_GEQ(static_cast(k), 0); SEQAN_ASSERT_LT(static_cast(k), static_cast(SIZE)); return i[k]; } // This has to be inline because elements (like this tuple) of packed // structs can't be arguments. template inline TValue2 assignValue(TPos k, TValue2 const source) { return i[k] = source; } }; #pragma pack(push,1) template struct Tuple { // ----------------------------------------------------------------------- // Members // ----------------------------------------------------------------------- typename StoredTupleValue_::Type i[SIZE]; // ----------------------------------------------------------------------- // Subscription Operators; Have to be declared in class. // ----------------------------------------------------------------------- // TODO(holtgrew): Return Value<>::Type? template inline typename StoredTupleValue_::Type & operator[](TPos k) { SEQAN_ASSERT_GEQ(static_cast(k), 0); SEQAN_ASSERT_LT(static_cast(k), static_cast(SIZE)); return i[k]; } template inline typename StoredTupleValue_::Type const & operator[](TPos k) const { SEQAN_ASSERT_GEQ(static_cast(k), 0); SEQAN_ASSERT_LT(static_cast(k), static_cast(SIZE)); return i[k]; } // This has to be inline because elements (like this tuple) of packed // structs can't be arguments. template inline TValue2 assignValue(TPos k, TValue2 const source) { return i[k] = source; } }; #pragma pack(pop) //template //const unsigned Tuple::SIZE = SIZE; // ============================================================================ // Metafunctions // ============================================================================ // ----------------------------------------------------------------------- // Metafunction LENGTH // ----------------------------------------------------------------------- /*! * @mfn Tuple#LENGTH * @brief Return the length of a tuple. * * @signature LENGTH::VALUE; * * @tparam TTuple The tuple to query for its length. * * @return VALUE The length of the tuple. */ template struct LENGTH > { enum { VALUE = SIZE }; }; // ----------------------------------------------------------------------- // Metafunction Value // ----------------------------------------------------------------------- /*! * @mfn Tuple#Value * @brief Return the value type of a tuple. * * @signature Value::Type; * * @tparam TTuple The tuple type to query for its value type. * * @return Type The resulting value type. */ template struct Value > { typedef TValue Type; }; // ----------------------------------------------------------------------- // Metafunction Spec // ----------------------------------------------------------------------- template struct Spec > { typedef TSpec Type; }; // ============================================================================ // Functions // ============================================================================ // ----------------------------------------------------------------------- // Function operator<<(); Stream Output. // ----------------------------------------------------------------------- template inline void write(TTarget &target, Tuple const &a) { writeValue(target, '['); if (SIZE > 0) write(target, (TValue)a[0]); for (unsigned j = 1; j < SIZE; ++j) { writeValue(target, ' '); write(target, (TValue)a[j]); } writeValue(target, ']'); } template inline TStream & operator<<(TStream & target, Tuple const & source) { typename DirectionIterator::Type it = directionIterator(target, Output()); write(it, source); return target; } // ---------------------------------------------------------------------------- // Function set(). // ---------------------------------------------------------------------------- template struct TupleMoveSetWorkerContext_ { TTuple1 & t1; TTuple2 & t2; TupleMoveSetWorkerContext_(TTuple1 & _t1, TTuple2 & _t2) : t1(_t1), t2(_t2) {} }; struct TupleSetWorker_ { template static inline void body(TArg & arg, unsigned I) { set(arg.t1.i[I - 1], arg.t2.i[I - 1]); } }; template inline void set(Tuple & t1, Tuple const & t2) { typedef Tuple TTuple1; typedef Tuple const TTuple2; TupleMoveSetWorkerContext_ context(t1, t2); Loop::run(context); } template inline void set(Tuple & t1, Tuple & t2) { set(t1, const_cast const &>(t2)); } // ---------------------------------------------------------------------------- // Function move(). // ---------------------------------------------------------------------------- struct TupleMoveWorker_ { template static inline void body(TArg & arg, unsigned I) { move(arg.t1.i[I - 1], arg.t2.i[I - 1]); } }; template inline void move(Tuple & t1, Tuple & t2) { typedef Tuple TTuple1; typedef Tuple TTuple2; TupleMoveSetWorkerContext_ context(t1, t2); Loop::run(context); } // ----------------------------------------------------------------------- // Function assignValue() // ----------------------------------------------------------------------- template inline TValue2 assignValue(Tuple & me, TPos k, TValue2 const source) { SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE)); return me.i[k] = source; } // ----------------------------------------------------------------------- // Function getValue() // ----------------------------------------------------------------------- template inline TValue getValue(Tuple & me, TPos k) { SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE)); return me.i[k]; } template inline TValue getValue(Tuple const & me, TPos k) { SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE)); return me.i[k]; } // ----------------------------------------------------------------------- // Function setValue() // ----------------------------------------------------------------------- template inline void setValue(Tuple & me, TPos k, TValue2 const & source) { SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE)); set(me.i[k], source); } // ----------------------------------------------------------------------- // Function moveValue() // ----------------------------------------------------------------------- template inline void moveValue(Tuple & me, TPos k, TValue2 & source) { SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE)); move(me.i[k], source); } // ----------------------------------------------------------------------- // Function shiftLeft() // ----------------------------------------------------------------------- // TODO(holtgrew): Document! struct TupleShiftLeftWorker_ { template static inline void body(TArg & arg, unsigned I) { arg[I-1] = arg[I]; // TODO(holtgrew): Do we really want assignment or movement here? } }; template inline void shiftLeft(Tuple &me) { Loop::run(me.i); } // ----------------------------------------------------------------------- // Function shiftRight() // ----------------------------------------------------------------------- // TODO(holtgrew): Document! struct TupleShiftRightWorker_ { template static inline void body(TArg & arg, unsigned I) { arg[I] = arg[I - 1]; // TODO(holtgrew): Do we really want assignment or movement here? } }; template inline void shiftRight(Tuple & me) { LoopReverse::run(me.i); } // ----------------------------------------------------------------------- // Function length() // ----------------------------------------------------------------------- template inline unsigned length(Tuple const &) { return SIZE; } // ----------------------------------------------------------------------- // Function clear() // ----------------------------------------------------------------------- template inline void clear(Tuple & me) { memset(&(me.i)); } // ----------------------------------------------------------------------- // Function operator==() // ----------------------------------------------------------------------- template struct ComparisonWorkerContext_ { int result; TTupleL const & left; TTupleR const & right; ComparisonWorkerContext_(int b, TTupleL const & l, TTupleR const & r) : result(b), left(l), right(r) {} }; struct TupleComparisonWorkerEq_ { template static inline void body(TArg & arg, unsigned I) { if (arg.result != 1) return; if (getValue(arg.left, I - 1) != getValue(arg.right, I - 1)) arg.result = 0; } }; template inline bool operator==(Tuple const & left, Tuple const & right) { typedef Tuple TTupleL; typedef Tuple TTupleR; ComparisonWorkerContext_ context(1, left, right); Loop::run(context); return context.result == 1; } // ----------------------------------------------------------------------- // Function operator!=() // ----------------------------------------------------------------------- template inline bool operator!=(Tuple const & left, Tuple const & right) { return !operator==(left, right); } // ----------------------------------------------------------------------- // Function operator<() // ----------------------------------------------------------------------- struct TupleComparisonWorkerLt_ { template static inline void body(TArg & arg, unsigned I) { if (arg.result != -1) return; if (arg.left.i[I - 1] == arg.right.i[I - 1]) return; if (arg.left.i[I - 1] < arg.right.i[I - 1]) arg.result = 1; if (arg.left.i[I - 1] > arg.right.i[I - 1]) arg.result = 0; } }; template inline bool operator<(Tuple const & left, Tuple const & right) { typedef Tuple TTupleL; typedef Tuple TTupleR; ComparisonWorkerContext_ context(-1, left, right); Loop::run(context); return context.result == 1; } // ----------------------------------------------------------------------- // Function operator>() // ----------------------------------------------------------------------- struct TupleComparisonWorkerGt_ { template static inline void body(TArg & arg, unsigned I) { if (arg.result != -1) return; if (arg.left.i[I - 1] == arg.right.i[I - 1]) return; if (arg.left.i[I - 1] > arg.right.i[I - 1]) arg.result = 1; if (arg.left.i[I - 1] < arg.right.i[I - 1]) arg.result = 0; } }; template inline bool operator>(Tuple const & left, Tuple const & right) { typedef Tuple TTupleL; typedef Tuple TTupleR; ComparisonWorkerContext_ context(-1, left, right); Loop::run(context); return context.result == 1; } // ----------------------------------------------------------------------- // Function operator<=() // ----------------------------------------------------------------------- template inline bool operator<=(Tuple const & left, Tuple const & right) { return !operator>(left, right); } // ----------------------------------------------------------------------- // Function operator>=() // ----------------------------------------------------------------------- template inline bool operator>=(Tuple const & left, Tuple const & right) { return !operator<(left, right); } // ----------------------------------------------------------------------- // Function operator+() // ----------------------------------------------------------------------- template inline Tuple operator+(Tuple const & left, Tuple const & right) { Tuple tuple; for (unsigned j = 0; j < SIZE; ++j) tuple[j] = left[j] + right[j]; return tuple; } template inline Tuple operator+(Tuple const & left, Tuple const & right) { Tuple tuple; for (unsigned j = 0; j < SIZE; ++j) tuple[j] = left[j] + right[j]; return tuple; } } // namespace seqan #endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_