d92ab6f0 |
// ==========================================================================
// 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 <david.weese@fu-berlin.de>
// ==========================================================================
// 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 <typename TValue>
struct StoredTupleValue_
{
typedef TValue Type;
};
template <typename TValue, typename TSpec>
struct StoredTupleValue_< SimpleType<TValue, TSpec> >
{
typedef TValue Type;
};
/*!
* @class Tuple
* @headerfile <seqan/basic.h>
* @brief A constant-size tuple of the same type.
*
* @signature template <typename TValue, unsigned SIZE[, typename TSpec]>
* 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 <typename TValue, unsigned SIZE, typename TSpec = void>
struct Tuple
{
// -----------------------------------------------------------------------
// Members
// -----------------------------------------------------------------------
typename StoredTupleValue_<TValue>::Type i[SIZE];
// -----------------------------------------------------------------------
// Subscription Operators; Have to be declared in class.
// -----------------------------------------------------------------------
// TODO(holtgrew): Return Value<>::Type?
template <typename TPos>
inline
typename StoredTupleValue_<TValue>::Type &
operator[](TPos k)
{
SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
return i[k];
}
template <typename TPos>
inline
typename StoredTupleValue_<TValue>::Type const &
operator[](TPos k) const
{
SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
return i[k];
}
// This has to be inline because elements (like this tuple) of packed
// structs can't be arguments.
template <typename TPos, typename TValue2>
inline TValue2
assignValue(TPos k, TValue2 const source)
{
return i[k] = source;
}
};
#pragma pack(push,1)
template <typename TValue, unsigned SIZE>
struct Tuple<TValue, SIZE, Pack>
{
// -----------------------------------------------------------------------
// Members
// -----------------------------------------------------------------------
typename StoredTupleValue_<TValue>::Type i[SIZE];
// -----------------------------------------------------------------------
// Subscription Operators; Have to be declared in class.
// -----------------------------------------------------------------------
// TODO(holtgrew): Return Value<>::Type?
template <typename TPos>
inline typename StoredTupleValue_<TValue>::Type &
operator[](TPos k)
{
SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
return i[k];
}
template <typename TPos>
inline typename StoredTupleValue_<TValue>::Type const &
operator[](TPos k) const
{
SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
return i[k];
}
// This has to be inline because elements (like this tuple) of packed
// structs can't be arguments.
template <typename TPos, typename TValue2>
inline TValue2
assignValue(TPos k, TValue2 const source)
{
return i[k] = source;
}
};
#pragma pack(pop)
//template <typename TValue, unsigned SIZE>
//const unsigned Tuple<TValue, SIZE, Pack>::SIZE = SIZE;
// ============================================================================
// Metafunctions
// ============================================================================
// -----------------------------------------------------------------------
// Metafunction LENGTH
// -----------------------------------------------------------------------
/*!
* @mfn Tuple#LENGTH
* @brief Return the length of a tuple.
*
* @signature LENGTH<TTuple>::VALUE;
*
* @tparam TTuple The tuple to query for its length.
*
* @return VALUE The length of the tuple.
*/
template <typename TValue, unsigned SIZE, typename TSpec>
struct LENGTH<Tuple<TValue, SIZE, TSpec> >
{
enum { VALUE = SIZE };
};
// -----------------------------------------------------------------------
// Metafunction Value
// -----------------------------------------------------------------------
/*!
* @mfn Tuple#Value
* @brief Return the value type of a tuple.
*
* @signature Value<TTuple>::Type;
*
* @tparam TTuple The tuple type to query for its value type.
*
* @return Type The resulting value type.
*/
template <typename TValue, unsigned SIZE, typename TSpec>
struct Value<Tuple<TValue, SIZE, TSpec> >
{
typedef TValue Type;
};
// -----------------------------------------------------------------------
// Metafunction Spec
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpec>
struct Spec<Tuple<TValue, SIZE, TSpec> >
{
typedef TSpec Type;
};
// ============================================================================
// Functions
// ============================================================================
// -----------------------------------------------------------------------
// Function operator<<(); Stream Output.
// -----------------------------------------------------------------------
template <typename TTarget, typename TValue, unsigned SIZE, typename TSpec>
inline void
write(TTarget &target, Tuple<TValue, SIZE, TSpec> 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 <typename TStream, typename TValue, unsigned SIZE, typename TSpec>
inline TStream &
operator<<(TStream & target,
Tuple<TValue, SIZE, TSpec> const & source)
{
typename DirectionIterator<TStream, Output>::Type it = directionIterator(target, Output());
write(it, source);
return target;
}
// ----------------------------------------------------------------------------
// Function set().
// ----------------------------------------------------------------------------
template <typename TTuple1, typename TTuple2>
struct TupleMoveSetWorkerContext_
{
TTuple1 & t1;
TTuple2 & t2;
TupleMoveSetWorkerContext_(TTuple1 & _t1, TTuple2 & _t2)
: t1(_t1), t2(_t2)
{}
};
struct TupleSetWorker_
{
template <typename TArg>
static inline void body(TArg & arg, unsigned I)
{
set(arg.t1.i[I - 1], arg.t2.i[I - 1]);
}
};
template <typename TValue, unsigned SIZE, typename TSpec>
inline void
set(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> const & t2)
{
typedef Tuple<TValue, SIZE, TSpec> TTuple1;
typedef Tuple<TValue, SIZE, TSpec> const TTuple2;
TupleMoveSetWorkerContext_<TTuple1, TTuple2> context(t1, t2);
Loop<TupleSetWorker_, SIZE>::run(context);
}
template <typename TValue, unsigned SIZE, typename TSpec>
inline void
set(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> & t2)
{
set(t1, const_cast<Tuple<TValue, SIZE, TSpec> const &>(t2));
}
// ----------------------------------------------------------------------------
// Function move().
// ----------------------------------------------------------------------------
struct TupleMoveWorker_
{
template <typename TArg>
static inline void body(TArg & arg, unsigned I)
{
move(arg.t1.i[I - 1], arg.t2.i[I - 1]);
}
};
template <typename TValue, unsigned SIZE, typename TSpec>
inline void
move(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> & t2)
{
typedef Tuple<TValue, SIZE, TSpec> TTuple1;
typedef Tuple<TValue, SIZE, TSpec> TTuple2;
TupleMoveSetWorkerContext_<TTuple1, TTuple2> context(t1, t2);
Loop<TupleMoveWorker_, SIZE>::run(context);
}
// -----------------------------------------------------------------------
// Function assignValue()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
inline TValue2
assignValue(Tuple<TValue, SIZE, TSpec> & 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 <typename TValue, unsigned SIZE, typename TSpec, typename TPos>
inline TValue
getValue(Tuple<TValue, SIZE, TSpec> & me, TPos k)
{
SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
return me.i[k];
}
template <typename TValue, unsigned SIZE, typename TSpec, typename TPos>
inline TValue
getValue(Tuple<TValue, SIZE, TSpec> 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 <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
inline void
setValue(Tuple<TValue, SIZE, TSpec> & 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 <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
inline void
moveValue(Tuple<TValue, SIZE, TSpec> & 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 <typename TArg>
static inline void body(TArg & arg, unsigned I)
{
arg[I-1] = arg[I]; // TODO(holtgrew): Do we really want assignment or movement here?
}
};
template <typename TValue, unsigned SIZE, typename TSpec>
inline void shiftLeft(Tuple<TValue, SIZE, TSpec> &me)
{
Loop<TupleShiftLeftWorker_, SIZE - 1>::run(me.i);
}
// -----------------------------------------------------------------------
// Function shiftRight()
// -----------------------------------------------------------------------
// TODO(holtgrew): Document!
struct TupleShiftRightWorker_
{
template <typename TArg>
static inline void body(TArg & arg, unsigned I)
{
arg[I] = arg[I - 1]; // TODO(holtgrew): Do we really want assignment or movement here?
}
};
template <typename TValue, unsigned SIZE, typename TSpec>
inline void shiftRight(Tuple<TValue, SIZE, TSpec> & me)
{
LoopReverse<TupleShiftRightWorker_, SIZE - 1>::run(me.i);
}
// -----------------------------------------------------------------------
// Function length()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpec>
inline unsigned length(Tuple<TValue, SIZE, TSpec> const &)
{
return SIZE;
}
// -----------------------------------------------------------------------
// Function clear()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpec>
inline void clear(Tuple<TValue, SIZE, TSpec> & me)
{
memset<sizeof(me.i), 0>(&(me.i));
}
// -----------------------------------------------------------------------
// Function operator==()
// -----------------------------------------------------------------------
template <typename TTupleL, typename TTupleR>
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 <typename TArg>
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 <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator==(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
ComparisonWorkerContext_<TTupleL, TTupleR> context(1, left, right);
Loop<TupleComparisonWorkerEq_, SIZE>::run(context);
return context.result == 1;
}
// -----------------------------------------------------------------------
// Function operator!=()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator!=(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
return !operator==(left, right);
}
// -----------------------------------------------------------------------
// Function operator<()
// -----------------------------------------------------------------------
struct TupleComparisonWorkerLt_
{
template <typename TArg>
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 <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator<(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
ComparisonWorkerContext_<TTupleL, TTupleR> context(-1, left, right);
Loop<TupleComparisonWorkerLt_, SIZE>::run(context);
return context.result == 1;
}
// -----------------------------------------------------------------------
// Function operator>()
// -----------------------------------------------------------------------
struct TupleComparisonWorkerGt_
{
template <typename TArg>
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 <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator>(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
ComparisonWorkerContext_<TTupleL, TTupleR> context(-1, left, right);
Loop<TupleComparisonWorkerGt_, SIZE>::run(context);
return context.result == 1;
}
// -----------------------------------------------------------------------
// Function operator<=()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator<=(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
return !operator>(left, right);
}
// -----------------------------------------------------------------------
// Function operator>=()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline bool
operator>=(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
return !operator<(left, right);
}
// -----------------------------------------------------------------------
// Function operator+()
// -----------------------------------------------------------------------
template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
inline Tuple<TValue, SIZE, TSpecL>
operator+(Tuple<TValue, SIZE, TSpecL> const & left,
Tuple<TValue, SIZE, TSpecR> const & right)
{
Tuple<TValue, SIZE, TSpecL> tuple;
for (unsigned j = 0; j < SIZE; ++j)
tuple[j] = left[j] + right[j];
return tuple;
}
template <typename TValue1, unsigned SIZE, typename TSpecL, typename TValue2, typename TSpecR>
inline Tuple<TValue1, SIZE, TSpecL>
operator+(Tuple<TValue1, SIZE, TSpecL> const & left,
Tuple<TValue2, SIZE, TSpecR> const & right)
{
Tuple<TValue1, SIZE, TSpecL> 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_
|