1 /*==========================================================================
2 SeqAn - The Library for Sequence Analysis
4 ============================================================================
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 ============================================================================
18 $Id: basic_metaprogramming.h,v 1.2 2009/02/19 01:51:23 langmead Exp $
19 ==========================================================================*/
21 #ifndef SEQAN_BASIC_METAPROGRAMMING_H
22 #define SEQAN_BASIC_METAPROGRAMMING_H
24 namespace SEQAN_NAMESPACE_MAIN
27 //////////////////////////////////////////////////////////////////////////////
28 // generic "if" (using meta-programming)
29 // if Flag is true, the resulting type is Type1
30 // if Flag is false, the resulting type is Type2
31 //////////////////////////////////////////////////////////////////////////////
33 template <bool Flag,class Type1, class Type2>
39 template <class Type1, class Type2>
40 struct IF<false,Type1,Type2>
46 //////////////////////////////////////////////////////////////////////////////
47 // generic type comparison (using meta-programming)
48 // if Type1 equals Type2, VALUE is true
49 // if Type1 differs from Type2, VALUE is false
50 //////////////////////////////////////////////////////////////////////////////
52 template <class Type1, class Type2>
56 enum { VALUE = false };
59 template <class Type1>
60 struct TYPECMP<Type1, Type1>
63 enum { VALUE = true };
66 //////////////////////////////////////////////////////////////////////////////
67 // generic "switch" (using meta-programming)
68 //////////////////////////////////////////////////////////////////////////////
70 const int DEFAULT = ~(~0u >> 1); // initialize with the smallest int
74 template <int tag_,class Type_,class Next_ = NilCase>
82 template <int tag,class Case>
85 typedef typename Case::Next NextCase;
89 found = (caseTag == tag || caseTag == DEFAULT)
96 typename SWITCH<tag,NextCase>::Type
101 class SWITCH<tag,NilCase>
104 typedef NilCase Type;
108 //////////////////////////////////////////////////////////////////////////////
109 // generic loops (using meta-programming)
110 // corresponds to for(i=1; i<=I; ++i) ...
111 //////////////////////////////////////////////////////////////////////////////
113 // example of a loop Worker class
116 template <typename Arg>
117 static inline void body(Arg &arg, int I) {}
120 template <typename Worker, int I>
123 template <typename Arg>
124 static inline void run(Arg &arg) {
125 LOOP<Worker, I - 1>::run(arg);
126 Worker::body(arg, I);
130 template <typename Worker>
131 class LOOP<Worker, 0> {
134 template <typename Arg>
135 static inline void run(Arg &) {}
138 //////////////////////////////////////////////////////////////////////////////
139 // generic reverse loops (using meta-programming)
140 // corresponds to for(i=I; i>0; --i) ...
141 //////////////////////////////////////////////////////////////////////////////
143 template <typename Worker, int I>
146 template <typename Arg>
147 static inline void run(Arg &arg) {
148 Worker::body(arg, I);
149 LOOP_REVERSE<Worker, I - 1>::run(arg);
153 template <typename Worker>
154 class LOOP_REVERSE<Worker, 0> {
157 template <typename Arg>
158 static inline void run(Arg &) {}
161 //////////////////////////////////////////////////////////////////////////////
162 // logarithmus dualis (using meta-programming)
163 //////////////////////////////////////////////////////////////////////////////
165 template < __int64 numerus >
167 enum { VALUE = Log2<(numerus + 1) / 2>::VALUE + 1 }; // ceil(log_2(n))
170 template < __int64 numerus >
172 enum { VALUE = Log2Floor<numerus / 2>::VALUE + 1 }; // floor(log_2(n))
175 template <> struct Log2<1> { enum { VALUE = 0 }; };
176 template <> struct Log2<0> { enum { VALUE = 0 }; };
177 template <> struct Log2Floor<1> { enum { VALUE = 0 }; };
178 template <> struct Log2Floor<0> { enum { VALUE = 0 }; };
181 //////////////////////////////////////////////////////////////////////////////
182 // exponentiation (using meta-programming)
183 //////////////////////////////////////////////////////////////////////////////
185 template < __int64 base, __int64 exponent >
189 Power<base, exponent / 2>::VALUE *
190 Power<base, exponent - (exponent / 2)>::VALUE
194 template < __int64 base > struct Power<base, 1> { enum { VALUE = base }; };
195 template < __int64 base > struct Power<base, 0> { enum { VALUE = 1 }; };
198 //////////////////////////////////////////////////////////////////////////////
199 // memset with fill size (using meta-programming)
200 //////////////////////////////////////////////////////////////////////////////
204 template <unsigned SIZE, bool direct>
205 struct MemsetWorker {
206 finline static void run(unsigned char* ptr, unsigned char c) { memset(ptr, c, SIZE); }
209 template <unsigned SIZE>
210 struct MemsetWorker<SIZE, true> {
211 finline static void run(unsigned char* ptr, unsigned char c) {
212 *((unsigned*)ptr) = ((unsigned)c << 24) + ((unsigned)c << 16) + ((unsigned)c << 8) + (unsigned)c;
213 MemsetWorker<SIZE - 4, true>::run(ptr + 4, c);
218 struct MemsetWorker<0, true> {
219 finline static void run(unsigned char*, unsigned char) {}
223 struct MemsetWorker<1, true> {
224 finline static void run(unsigned char* ptr, unsigned char c) { *ptr = c; }
228 struct MemsetWorker<2, true> {
229 finline static void run(unsigned char* ptr, unsigned char c) { *(unsigned short *)ptr = ((unsigned short)c << 8) + (unsigned short)c; }
233 struct MemsetWorker<3, true> {
234 finline static void run(unsigned char* ptr, unsigned char c) {
235 MemsetWorker<2, true>::run(ptr, c);
236 MemsetWorker<1, true>::run(ptr + 2, c);
240 template <unsigned SIZE>
241 finline void memset(void* ptr, unsigned char c) {
242 MemsetWorker<SIZE, SIZE <= 32>::run((unsigned char*)ptr, c);
246 //////////////////////////////////////////////////////////////////////////////
247 // memset with fill value (using meta-programming)
248 //////////////////////////////////////////////////////////////////////////////
250 template <unsigned SIZE, bool direct, unsigned char c>
251 struct MemsetConstValueWorker {
252 finline static void run(unsigned char* ptr) { memset(ptr, c, SIZE); }
255 template <unsigned SIZE, unsigned char c>
256 struct MemsetConstValueWorker<SIZE, true, c> {
257 finline static void run(unsigned char* ptr) {
258 *((unsigned*)ptr) = ((unsigned)c << 24) + ((unsigned)c << 16) + ((unsigned)c << 8) + (unsigned)c;
259 MemsetConstValueWorker<SIZE - 4, true, c>::run(ptr + 4);
263 template <unsigned char c>
264 struct MemsetConstValueWorker<0, true, c> {
265 finline static void run(unsigned char* ptr) {}
268 template <unsigned char c>
269 struct MemsetConstValueWorker<1, true, c> {
270 finline static void run(unsigned char* ptr) { *ptr = c; }
273 template <unsigned char c>
274 struct MemsetConstValueWorker<2, true, c> {
275 finline static void run(unsigned char* ptr) { *(unsigned short *)ptr = ((unsigned short)c << 8) + (unsigned short)c; }
278 template <unsigned char c>
279 struct MemsetConstValueWorker<3, true, c> {
280 finline static void run(unsigned char* ptr) {
281 MemsetConstValueWorker<2, true, c>::run(ptr);
282 MemsetConstValueWorker<1, true, c>::run(ptr + 2);
286 template <unsigned SIZE, unsigned char c>
287 finline void memset(void* ptr) {
288 MemsetConstValueWorker<SIZE, SIZE <= 32, c>::run((unsigned char*)ptr);