Browse code

seqan header files

aguang authored on 15/02/2018 18:04:57
Showing1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,625 @@
1
+// ==========================================================================
2
+//                 SeqAn - The Library for Sequence Analysis
3
+// ==========================================================================
4
+// Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5
+// Copyright (c) 2013 NVIDIA Corporation
6
+// All rights reserved.
7
+//
8
+// Redistribution and use in source and binary forms, with or without
9
+// modification, are permitted provided that the following conditions are met:
10
+//
11
+//     * Redistributions of source code must retain the above copyright
12
+//       notice, this list of conditions and the following disclaimer.
13
+//     * Redistributions in binary form must reproduce the above copyright
14
+//       notice, this list of conditions and the following disclaimer in the
15
+//       documentation and/or other materials provided with the distribution.
16
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
17
+//       its contributors may be used to endorse or promote products derived
18
+//       from this software without specific prior written permission.
19
+//
20
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
24
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30
+// DAMAGE.
31
+//
32
+// ==========================================================================
33
+// Author: David Weese <david.weese@fu-berlin.de>
34
+// ==========================================================================
35
+// Tuple base class.
36
+// ==========================================================================
37
+
38
+// TODO(holtgrew): What about move construction? Useful for pairs of strings and such. Tricky to implement since ints have no move constructor, for example.
39
+
40
+#ifndef SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_
41
+#define SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_
42
+
43
+namespace seqan {
44
+
45
+// ============================================================================
46
+// Forwards
47
+// ============================================================================
48
+
49
+// ============================================================================
50
+// Tags, Classes, Enums
51
+// ============================================================================
52
+
53
+template <typename TValue>
54
+struct StoredTupleValue_
55
+{
56
+    typedef TValue Type;
57
+};
58
+
59
+template <typename TValue, typename TSpec>
60
+struct StoredTupleValue_< SimpleType<TValue, TSpec> >
61
+{
62
+    typedef TValue Type;
63
+};
64
+
65
+/*!
66
+ * @class Tuple
67
+ * @headerfile <seqan/basic.h>
68
+ * @brief A constant-size tuple of the same type.
69
+ *
70
+ * @signature template <typename TValue, unsigned SIZE[, typename TSpec]>
71
+ *            class Tuple;
72
+ *
73
+ * @tparam TValue The value that the tuple should be over.
74
+ * @tparam SIZE   The number of entries in the tuple.
75
+ * @tparam TSpec  Specialization tag, optional;  defaults to void.
76
+ */
77
+
78
+/*!
79
+ * @fn Tuple::i
80
+ * @brief Array of tuple value.
81
+ *
82
+ * @signature TValue Tuple::i[SIZE];
83
+ *
84
+ * The array of the tuple's values.
85
+ */
86
+
87
+template <typename TValue, unsigned SIZE, typename TSpec = void>
88
+struct Tuple
89
+{
90
+    // -----------------------------------------------------------------------
91
+    // Members
92
+    // -----------------------------------------------------------------------
93
+
94
+    typename StoredTupleValue_<TValue>::Type i[SIZE];
95
+
96
+    // -----------------------------------------------------------------------
97
+    // Subscription Operators;  Have to be declared in class.
98
+    // -----------------------------------------------------------------------
99
+
100
+    // TODO(holtgrew): Return Value<>::Type?
101
+
102
+    template <typename TPos>
103
+    inline
104
+    typename StoredTupleValue_<TValue>::Type &
105
+    operator[](TPos k)
106
+    {
107
+        SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
108
+        SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
109
+        return i[k];
110
+    }
111
+
112
+    template <typename TPos>
113
+    inline
114
+    typename StoredTupleValue_<TValue>::Type const &
115
+    operator[](TPos k) const
116
+    {
117
+        SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
118
+        SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
119
+        return i[k];
120
+    }
121
+
122
+    // This has to be inline because elements (like this tuple) of packed
123
+    // structs can't be arguments.
124
+    template <typename TPos, typename TValue2>
125
+    inline TValue2
126
+    assignValue(TPos k, TValue2 const source)
127
+    {
128
+        return i[k] = source;
129
+    }
130
+};
131
+
132
+
133
+#pragma pack(push,1)
134
+template <typename TValue, unsigned SIZE>
135
+struct Tuple<TValue, SIZE, Pack>
136
+{
137
+    // -----------------------------------------------------------------------
138
+    // Members
139
+    // -----------------------------------------------------------------------
140
+
141
+    typename StoredTupleValue_<TValue>::Type i[SIZE];
142
+
143
+    // -----------------------------------------------------------------------
144
+    // Subscription Operators;  Have to be declared in class.
145
+    // -----------------------------------------------------------------------
146
+
147
+    // TODO(holtgrew): Return Value<>::Type?
148
+
149
+    template <typename TPos>
150
+    inline typename StoredTupleValue_<TValue>::Type &
151
+    operator[](TPos k)
152
+    {
153
+        SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
154
+        SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
155
+        return i[k];
156
+    }
157
+
158
+    template <typename TPos>
159
+    inline typename StoredTupleValue_<TValue>::Type const &
160
+    operator[](TPos k) const
161
+    {
162
+        SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
163
+        SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
164
+        return i[k];
165
+    }
166
+
167
+    // This has to be inline because elements (like this tuple) of packed
168
+    // structs can't be arguments.
169
+    template <typename TPos, typename TValue2>
170
+    inline TValue2
171
+    assignValue(TPos k, TValue2 const source)
172
+    {
173
+        return i[k] = source;
174
+    }
175
+};
176
+#pragma pack(pop)
177
+
178
+//template <typename TValue, unsigned SIZE>
179
+//const unsigned Tuple<TValue, SIZE, Pack>::SIZE = SIZE;
180
+
181
+// ============================================================================
182
+// Metafunctions
183
+// ============================================================================
184
+
185
+// -----------------------------------------------------------------------
186
+// Metafunction LENGTH
187
+// -----------------------------------------------------------------------
188
+
189
+/*!
190
+ * @mfn Tuple#LENGTH
191
+ * @brief Return the length of a tuple.
192
+ *
193
+ * @signature LENGTH<TTuple>::VALUE;
194
+ *
195
+ * @tparam TTuple The tuple to query for its length.
196
+ *
197
+ * @return VALUE The length of the tuple.
198
+ */
199
+
200
+template <typename TValue, unsigned SIZE, typename TSpec>
201
+struct LENGTH<Tuple<TValue, SIZE, TSpec> >
202
+{
203
+    enum { VALUE = SIZE };
204
+};
205
+
206
+// -----------------------------------------------------------------------
207
+// Metafunction Value
208
+// -----------------------------------------------------------------------
209
+
210
+/*!
211
+ * @mfn Tuple#Value
212
+ * @brief Return the value type of a tuple.
213
+ *
214
+ * @signature Value<TTuple>::Type;
215
+ *
216
+ * @tparam TTuple The tuple type to query for its value type.
217
+ *
218
+ * @return Type The resulting value type.
219
+ */
220
+
221
+template <typename TValue, unsigned SIZE, typename TSpec>
222
+struct Value<Tuple<TValue, SIZE, TSpec> >
223
+{
224
+    typedef TValue Type;
225
+};
226
+
227
+// -----------------------------------------------------------------------
228
+// Metafunction Spec
229
+// -----------------------------------------------------------------------
230
+
231
+template <typename TValue, unsigned SIZE, typename TSpec>
232
+struct Spec<Tuple<TValue, SIZE, TSpec> >
233
+{
234
+    typedef TSpec Type;
235
+};
236
+
237
+// ============================================================================
238
+// Functions
239
+// ============================================================================
240
+
241
+// -----------------------------------------------------------------------
242
+// Function operator<<();  Stream Output.
243
+// -----------------------------------------------------------------------
244
+
245
+template <typename TTarget, typename TValue, unsigned SIZE, typename TSpec>
246
+inline void
247
+write(TTarget &target, Tuple<TValue, SIZE, TSpec> const &a)
248
+{
249
+    writeValue(target, '[');
250
+    if (SIZE > 0)
251
+        write(target, (TValue)a[0]);
252
+    for (unsigned j = 1; j < SIZE; ++j)
253
+    {
254
+        writeValue(target, ' ');
255
+        write(target, (TValue)a[j]);
256
+    }
257
+    writeValue(target, ']');
258
+}
259
+
260
+template <typename TStream, typename TValue, unsigned SIZE, typename TSpec>
261
+inline TStream &
262
+operator<<(TStream & target,
263
+           Tuple<TValue, SIZE, TSpec> const & source)
264
+{
265
+    typename DirectionIterator<TStream, Output>::Type it = directionIterator(target, Output());
266
+    write(it, source);
267
+    return target;
268
+}
269
+
270
+// ----------------------------------------------------------------------------
271
+// Function set().
272
+// ----------------------------------------------------------------------------
273
+
274
+template <typename TTuple1, typename TTuple2>
275
+struct TupleMoveSetWorkerContext_
276
+{
277
+    TTuple1 & t1;
278
+    TTuple2 & t2;
279
+
280
+    TupleMoveSetWorkerContext_(TTuple1 & _t1, TTuple2 & _t2)
281
+            : t1(_t1), t2(_t2)
282
+    {}
283
+};
284
+
285
+struct TupleSetWorker_
286
+{
287
+    template <typename TArg>
288
+    static inline void body(TArg & arg, unsigned I)
289
+    {
290
+        set(arg.t1.i[I - 1], arg.t2.i[I - 1]);
291
+    }
292
+};
293
+
294
+template <typename TValue, unsigned SIZE, typename TSpec>
295
+inline void
296
+set(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> const & t2)
297
+{
298
+    typedef Tuple<TValue, SIZE, TSpec> TTuple1;
299
+    typedef Tuple<TValue, SIZE, TSpec> const TTuple2;
300
+    TupleMoveSetWorkerContext_<TTuple1, TTuple2> context(t1, t2);
301
+    Loop<TupleSetWorker_, SIZE>::run(context);
302
+}
303
+
304
+template <typename TValue, unsigned SIZE, typename TSpec>
305
+inline void
306
+set(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> & t2)
307
+{
308
+    set(t1, const_cast<Tuple<TValue, SIZE, TSpec> const &>(t2));
309
+}
310
+
311
+// ----------------------------------------------------------------------------
312
+// Function move().
313
+// ----------------------------------------------------------------------------
314
+
315
+struct TupleMoveWorker_
316
+{
317
+    template <typename TArg>
318
+    static inline void body(TArg & arg, unsigned I)
319
+    {
320
+        move(arg.t1.i[I - 1], arg.t2.i[I - 1]);
321
+    }
322
+};
323
+
324
+template <typename TValue, unsigned SIZE, typename TSpec>
325
+inline void
326
+move(Tuple<TValue, SIZE, TSpec> & t1, Tuple<TValue, SIZE, TSpec> & t2)
327
+{
328
+    typedef Tuple<TValue, SIZE, TSpec> TTuple1;
329
+    typedef Tuple<TValue, SIZE, TSpec> TTuple2;
330
+    TupleMoveSetWorkerContext_<TTuple1, TTuple2> context(t1, t2);
331
+    Loop<TupleMoveWorker_, SIZE>::run(context);
332
+}
333
+
334
+// -----------------------------------------------------------------------
335
+// Function assignValue()
336
+// -----------------------------------------------------------------------
337
+
338
+template <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
339
+inline TValue2
340
+assignValue(Tuple<TValue, SIZE, TSpec> & me, TPos k, TValue2 const source)
341
+{
342
+    SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
343
+    return me.i[k] = source;
344
+}
345
+
346
+// -----------------------------------------------------------------------
347
+// Function getValue()
348
+// -----------------------------------------------------------------------
349
+
350
+template <typename TValue, unsigned SIZE, typename TSpec, typename TPos>
351
+inline TValue
352
+getValue(Tuple<TValue, SIZE, TSpec> & me, TPos k)
353
+{
354
+    SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
355
+    return me.i[k];
356
+}
357
+
358
+template <typename TValue, unsigned SIZE, typename TSpec, typename TPos>
359
+inline TValue
360
+getValue(Tuple<TValue, SIZE, TSpec> const & me, TPos k)
361
+{
362
+    SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
363
+    return me.i[k];
364
+}
365
+
366
+// -----------------------------------------------------------------------
367
+// Function setValue()
368
+// -----------------------------------------------------------------------
369
+
370
+template <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
371
+inline void
372
+setValue(Tuple<TValue, SIZE, TSpec> & me, TPos k, TValue2 const & source)
373
+{
374
+    SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
375
+    set(me.i[k], source);
376
+}
377
+
378
+// -----------------------------------------------------------------------
379
+// Function moveValue()
380
+// -----------------------------------------------------------------------
381
+
382
+template <typename TValue, unsigned SIZE, typename TSpec, typename TPos, typename TValue2>
383
+inline void
384
+moveValue(Tuple<TValue, SIZE, TSpec> & me, TPos k, TValue2 & source)
385
+{
386
+    SEQAN_CHECK((unsigned(k) < SIZE), "Invalid position, k = %u, SIZE = %u.", unsigned(k), unsigned(SIZE));
387
+    move(me.i[k], source);
388
+}
389
+
390
+// -----------------------------------------------------------------------
391
+// Function shiftLeft()
392
+// -----------------------------------------------------------------------
393
+
394
+// TODO(holtgrew): Document!
395
+
396
+struct TupleShiftLeftWorker_
397
+{
398
+    template <typename TArg>
399
+    static inline void body(TArg & arg, unsigned I)
400
+    {
401
+        arg[I-1] = arg[I];  // TODO(holtgrew): Do we really want assignment or movement here?
402
+    }
403
+};
404
+
405
+template <typename TValue, unsigned SIZE, typename TSpec>
406
+inline void shiftLeft(Tuple<TValue, SIZE, TSpec> &me)
407
+{
408
+    Loop<TupleShiftLeftWorker_, SIZE - 1>::run(me.i);
409
+}
410
+
411
+// -----------------------------------------------------------------------
412
+// Function shiftRight()
413
+// -----------------------------------------------------------------------
414
+
415
+// TODO(holtgrew): Document!
416
+
417
+struct TupleShiftRightWorker_
418
+{
419
+    template <typename TArg>
420
+    static inline void body(TArg & arg, unsigned I)
421
+    {
422
+        arg[I] = arg[I - 1];  // TODO(holtgrew): Do we really want assignment or movement here?
423
+    }
424
+};
425
+
426
+template <typename TValue, unsigned SIZE, typename TSpec>
427
+inline void shiftRight(Tuple<TValue, SIZE, TSpec> & me)
428
+{
429
+    LoopReverse<TupleShiftRightWorker_, SIZE - 1>::run(me.i);
430
+}
431
+
432
+// -----------------------------------------------------------------------
433
+// Function length()
434
+// -----------------------------------------------------------------------
435
+
436
+template <typename TValue, unsigned SIZE, typename TSpec>
437
+inline unsigned length(Tuple<TValue, SIZE, TSpec> const &)
438
+{
439
+    return SIZE;
440
+}
441
+
442
+// -----------------------------------------------------------------------
443
+// Function clear()
444
+// -----------------------------------------------------------------------
445
+
446
+template <typename TValue, unsigned SIZE, typename TSpec>
447
+inline void clear(Tuple<TValue, SIZE, TSpec> & me)
448
+{
449
+   memset<sizeof(me.i), 0>(&(me.i));
450
+}
451
+
452
+// -----------------------------------------------------------------------
453
+// Function operator==()
454
+// -----------------------------------------------------------------------
455
+
456
+template <typename TTupleL, typename TTupleR>
457
+struct ComparisonWorkerContext_
458
+{
459
+    int result;
460
+    TTupleL const & left;
461
+    TTupleR const & right;
462
+
463
+    ComparisonWorkerContext_(int b, TTupleL const & l, TTupleR const & r)
464
+            : result(b), left(l), right(r)
465
+    {}
466
+};
467
+
468
+struct TupleComparisonWorkerEq_
469
+{
470
+    template <typename TArg>
471
+    static inline void body(TArg & arg, unsigned I)
472
+    {
473
+        if (arg.result != 1)
474
+            return;
475
+        if (getValue(arg.left, I - 1) != getValue(arg.right, I - 1))
476
+            arg.result = 0;
477
+    }
478
+};
479
+
480
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
481
+inline bool
482
+operator==(Tuple<TValue, SIZE, TSpecL> const & left,
483
+           Tuple<TValue, SIZE, TSpecR> const & right)
484
+{
485
+    typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
486
+    typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
487
+    ComparisonWorkerContext_<TTupleL, TTupleR> context(1, left, right);
488
+    Loop<TupleComparisonWorkerEq_, SIZE>::run(context);
489
+    return context.result == 1;
490
+}
491
+
492
+// -----------------------------------------------------------------------
493
+// Function operator!=()
494
+// -----------------------------------------------------------------------
495
+
496
+
497
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
498
+inline bool
499
+operator!=(Tuple<TValue, SIZE, TSpecL> const & left,
500
+           Tuple<TValue, SIZE, TSpecR> const & right)
501
+{
502
+    return !operator==(left, right);
503
+}
504
+
505
+// -----------------------------------------------------------------------
506
+// Function operator<()
507
+// -----------------------------------------------------------------------
508
+
509
+struct TupleComparisonWorkerLt_
510
+{
511
+    template <typename TArg>
512
+    static inline void body(TArg & arg, unsigned I)
513
+    {
514
+        if (arg.result != -1)
515
+            return;
516
+        if (arg.left.i[I - 1] == arg.right.i[I - 1])
517
+            return;
518
+        if (arg.left.i[I - 1] < arg.right.i[I - 1])
519
+            arg.result = 1;
520
+        if (arg.left.i[I - 1] > arg.right.i[I - 1])
521
+            arg.result = 0;
522
+    }
523
+};
524
+
525
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
526
+inline bool
527
+operator<(Tuple<TValue, SIZE, TSpecL> const & left,
528
+          Tuple<TValue, SIZE, TSpecR> const & right)
529
+{
530
+    typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
531
+    typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
532
+    ComparisonWorkerContext_<TTupleL, TTupleR> context(-1, left, right);
533
+    Loop<TupleComparisonWorkerLt_, SIZE>::run(context);
534
+    return context.result == 1;
535
+}
536
+
537
+// -----------------------------------------------------------------------
538
+// Function operator>()
539
+// -----------------------------------------------------------------------
540
+
541
+struct TupleComparisonWorkerGt_
542
+{
543
+    template <typename TArg>
544
+    static inline void body(TArg & arg, unsigned I)
545
+    {
546
+        if (arg.result != -1)
547
+            return;
548
+        if (arg.left.i[I - 1] == arg.right.i[I - 1])
549
+            return;
550
+        if (arg.left.i[I - 1] > arg.right.i[I - 1])
551
+            arg.result = 1;
552
+        if (arg.left.i[I - 1] < arg.right.i[I - 1])
553
+            arg.result = 0;
554
+    }
555
+};
556
+
557
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
558
+inline bool
559
+operator>(Tuple<TValue, SIZE, TSpecL> const & left,
560
+          Tuple<TValue, SIZE, TSpecR> const & right)
561
+{
562
+    typedef Tuple<TValue, SIZE, TSpecL> TTupleL;
563
+    typedef Tuple<TValue, SIZE, TSpecR> TTupleR;
564
+    ComparisonWorkerContext_<TTupleL, TTupleR> context(-1, left, right);
565
+    Loop<TupleComparisonWorkerGt_, SIZE>::run(context);
566
+    return context.result == 1;
567
+}
568
+
569
+// -----------------------------------------------------------------------
570
+// Function operator<=()
571
+// -----------------------------------------------------------------------
572
+
573
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
574
+inline bool
575
+operator<=(Tuple<TValue, SIZE, TSpecL> const & left,
576
+           Tuple<TValue, SIZE, TSpecR> const & right)
577
+{
578
+    return !operator>(left, right);
579
+}
580
+
581
+// -----------------------------------------------------------------------
582
+// Function operator>=()
583
+// -----------------------------------------------------------------------
584
+
585
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
586
+inline bool
587
+operator>=(Tuple<TValue, SIZE, TSpecL> const & left,
588
+           Tuple<TValue, SIZE, TSpecR> const & right)
589
+{
590
+    return !operator<(left, right);
591
+}
592
+
593
+// -----------------------------------------------------------------------
594
+// Function operator+()
595
+// -----------------------------------------------------------------------
596
+
597
+template <typename TValue, unsigned SIZE, typename TSpecL, typename TSpecR>
598
+inline Tuple<TValue, SIZE, TSpecL>
599
+operator+(Tuple<TValue, SIZE, TSpecL> const & left,
600
+          Tuple<TValue, SIZE, TSpecR> const & right)
601
+{
602
+    Tuple<TValue, SIZE, TSpecL>  tuple;
603
+
604
+    for (unsigned j = 0; j < SIZE; ++j)
605
+        tuple[j] = left[j] + right[j];
606
+
607
+    return tuple;
608
+}
609
+
610
+template <typename TValue1, unsigned SIZE, typename TSpecL, typename TValue2, typename TSpecR>
611
+inline Tuple<TValue1, SIZE, TSpecL>
612
+operator+(Tuple<TValue1, SIZE, TSpecL> const & left,
613
+          Tuple<TValue2, SIZE, TSpecR> const & right)
614
+{
615
+    Tuple<TValue1, SIZE, TSpecL>  tuple;
616
+
617
+    for (unsigned j = 0; j < SIZE; ++j)
618
+        tuple[j] = left[j] + right[j];
619
+
620
+    return tuple;
621
+}
622
+
623
+}  // namespace seqan
624
+
625
+#endif  // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_TUPLE_BASE_H_