summaryrefslogtreecommitdiffstats
path: root/scilab/modules/core
diff options
context:
space:
mode:
authorBernard HUGUENEY <bernard.hugueney@scilab.org>2010-04-15 17:08:22 +0200
committerBernard HUGUENEY <bernard.hugueney@scilab.org>2010-04-16 09:03:21 +0200
commit388a3f48470ad6896f60e24752241687486c9a3e (patch)
treed3ddbc22f0df4095cac56bd2f8547ce3de0ca218 /scilab/modules/core
parent7af76bbb251d9f9d7494118fac5d5db25966bc0c (diff)
downloadscilab-388a3f48470ad6896f60e24752241687486c9a3e.zip
scilab-388a3f48470ad6896f60e24752241687486c9a3e.tar.gz
Code documentation and coding convention conformance (->4 spaces indent)
moved to C comments // -> /* */
Diffstat (limited to 'scilab/modules/core')
-rw-r--r--scilab/modules/core/src/cpp/namstr.cpp143
-rw-r--r--scilab/modules/core/src/cpp/search_functions.cpp261
-rw-r--r--scilab/modules/core/src/cpp/unrolled_algorithms.hxx230
3 files changed, 319 insertions, 315 deletions
diff --git a/scilab/modules/core/src/cpp/namstr.cpp b/scilab/modules/core/src/cpp/namstr.cpp
index d356963..3dba511 100644
--- a/scilab/modules/core/src/cpp/namstr.cpp
+++ b/scilab/modules/core/src/cpp/namstr.cpp
@@ -9,21 +9,22 @@
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt 9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 * 10 *
11 */ 11 */
12#include "machine.h" // C2F 12#include "machine.h" /* C2F */
13#include "stack-def.h" // nsiz, nlgh 13#include "stack-def.h" /* nsiz, nlgh */
14 14
15extern "C" 15extern "C"
16{ 16{
17 void C2F(namstr)(int* id, int* str, int* n, char* job); 17 void C2F(namstr)(int* id, int* str, int* n, char* job);
18} 18}
19 19
20namespace 20namespace
21{ 21{
22 int const blank=40; /* @TOD: What is 40 */ 22 int const blank=40; /* a scilab encoded blank character: used for padding id when name has < nsiz*6 characters*/
23 int const one_blank= (blank<<24); 23/* constant below are used for fast padding 1->4 blanks at once */
24 int const two_blanks= one_blank + (blank<<16); 24 int const one_blank= (blank<<24);
25 int const three_blanks= two_blanks + (blank<<8); 25 int const two_blanks= one_blank + (blank<<16);
26 int const four_blanks= three_blanks + blank; 26 int const three_blanks= two_blanks + (blank<<8);
27 int const four_blanks= three_blanks + blank;
27} 28}
28 29
29/* 30/*
@@ -41,70 +42,72 @@ namespace
41 */ 42 */
42void C2F(namstr)(int* id,int* str, int* n, char* job) 43void C2F(namstr)(int* id,int* str, int* n, char* job)
43{ 44{
44 if(*job) // id -> str 45 if (*job) /* id -> str */
45 { 46 {
46 47
47 unsigned int i1(0); 48 unsigned int i1(0); /* starting character from constructed str when processing an int from id */
48
49 for(unsigned int j= 0; j != nsiz; ++j, i1 += 4) /* @TODO: add comment */
50 {
51 int id_j(id[j]);
52 for(unsigned int i(i1); i!=i1+4; ++i, id_j >>= 8) /* @TODO: add comment */
53 {
54 int ch((id_j & 0x80) ? (id_j |0xffffff00) : (id_j & 0xff));
55/* @TODO: add comment: what is 0x80 0xffffff00 0xff */
56 if(ch == blank)
57 {
58 *n = i;
59 return;
60 }
61 id_j += 128;
62 str[i]= ch;
63 }
64 }
65 49
66 *n= nlgh; 50 for (unsigned int j= 0; j != nsiz; ++j, i1 += 4) /* processing id[j] into str[i1...ii+4] */
51 {
52 int id_j(id[j]);/* caching id[j] because we could not tell the compiler that id and str do not alias */
53 for (unsigned int i(i1); i!=i1+4; ++i, id_j >>= 8)/* processing each byte from id[j] into an int in str*/
54 {
55 /* extracting the *signed* lower byte: & 0x80 tests the 7th bit (sign bit of the byte)
56 * |0xffffff00 : lower <0, byte & 0xff : lower >0 byte */
57 int ch((id_j & 0x80) ? (id_j |0xffffff00) : (id_j & 0xff));
58 if (ch == blank)/* we encounter a blank -> end of string. */
59 {
60 *n = i;
61 return;
62 }
63 id_j += 128;/* propagate sign bit to upper bits */
64 str[i]= ch;
65 }
66 }
67 67
68 } 68 *n= nlgh;/* no blank encountered str length is nlgh= nsiz*8 */
69 else
70 { // str -> id
71 // n (<= nsiz*4 = nlgh) int in str packed into id
72 unsigned int j;
73 unsigned const int full_ids((*n)>>2); /* @TODO: add comment: 2 ?*/
74 69
75 for(j= 0; j!=full_ids; ++j) 70 }
76 { 71 else
77 id[j]= str[4*j+0] +(str[4*j+1]<<8)+(str[4*j+2]<<16)+(str[4*j+3]<<24); /* @TODO: add comment */ 72 { /* str -> id */
78 } 73 /* n (<= nsiz*4 = nlgh) int in str packed into id */
79 if(j!= nsiz) 74 unsigned int j;
80 { 75 /* a full id contains 4 ints from str, so we have *n/4 full ids the remaing are padded with blanks */
81 switch((*n)&0x3) /* @TODO: add comment */ 76 unsigned const int full_ids((*n)/4);
82 {
83 case 3:
84 {
85 id[j]= one_blank + (str[4*j+2] << 16) + (str[4*j+1] << 8) + str[4*j + 0]; /* @TODO: add comment */
86 ++j;
87 break;
88 }
89 case 2:
90 {
91 id[j]= two_blanks + (str[4*j+1]<<8) + str[4*j+0]; /* @TODO: add comment */
92 ++j;
93 break;
94 }
95 case 1:
96 {
97 id[j]= three_blanks + str[4*j+0]; /* @TODO: add comment */
98 ++j;
99 break;
100 }
101 }
102 77
103 for(;j != nsiz; ++j) /* @TODO: add comment */ 78 for (j= 0; j!=full_ids; ++j)
104 { 79 { /* str int are signed bytes in fact, we pack them using shifts */
105 id[j]= four_blanks; 80 id[j]= str[4*j+0] +(str[4*j+1]<<8)+(str[4*j+2]<<16)+(str[4*j+3]<<24);
106 } 81 }
107 } 82 if (j!= nsiz)/* we had < nsiz int in str : padd with blank chars */
108 } 83 {
109 return; 84 switch ((*n ) & 0x3) /* pad partial id int according modulo 4= nb of remaining ints in str */
85 {
86 case 3: /* three remaining ints and one blank */
87 {
88 id[j]= one_blank + (str[4*j+2] << 16) + (str[4*j+1] << 8) + str[4*j + 0];
89 ++j;
90 break;
91 }
92 case 2: /* two remaining ints and two blanks */
93 {
94 id[j]= two_blanks + (str[4*j+1]<<8) + str[4*j+0];
95 ++j;
96 break;
97 }
98 case 1:/* one remaining int and three blanks*/
99 {
100 id[j]= three_blanks + str[4*j+0];
101 ++j;
102 break;
103 }
104 }
105
106 for (;j != nsiz; ++j) /* pad empty ints in id with four blanks at once */
107 {
108 id[j]= four_blanks;
109 }
110 }
111 }
112 return;
110} 113}
diff --git a/scilab/modules/core/src/cpp/search_functions.cpp b/scilab/modules/core/src/cpp/search_functions.cpp
index d6339c3..7fa7b6f 100644
--- a/scilab/modules/core/src/cpp/search_functions.cpp
+++ b/scilab/modules/core/src/cpp/search_functions.cpp
@@ -18,137 +18,154 @@ extern "C" {
18#include "stack-def.h" /* C2F(basbrk) */ 18#include "stack-def.h" /* C2F(basbrk) */
19#include "intmacr2tree.h" /*#define idstk(x,y) (C2F(vstk).idstk+(x-1)+(y-1)*nsiz) */ 19#include "intmacr2tree.h" /*#define idstk(x,y) (C2F(vstk).idstk+(x-1)+(y-1)*nsiz) */
20 20
21 void C2F(siflibs)(int* id, int* k_ptr, int* istr, int* lbibn, int* nbibn, int* ilp, int* nn, int* should_return); 21 void C2F(siflibs)(int* id, int* k_ptr, int* istr, int* lbibn, int* nbibn, int* ilp, int* nn, int* should_return);
22 void C2F(sivars)(int* id, int* should_return); 22 void C2F(sivars)(int* id, int* should_return);
23 void C2F(namstr)(int* id, int* str, int* n, char const* job); 23 void C2F(namstr)(int* id, int* str, int* n, char const* job);
24} 24}
25 25
26namespace 26
27/*
28 * These are C++ reimplementations of some (as few as possible) code from funs.f
29 * The goal was to improve speed with :
30 * 1°) avoiding a call to namstr_ when only the first (two) caracters where needed
31 * 2°) allowing the compiler to replace eqid() calls with inlined faster C++ implementation of eq_n<nsiz>
32 */
33
34namespace
27{ 35{
28 char const f_true = 1; 36 char const f_true = 1;
29 char const f_false = 0; 37 char const f_false = 0;
30 int const percent = 56; 38 int const percent = 56;
31 int const nclas = 29; 39 int const nclas = 29;
32 char const from_id = 1; 40 char const from_id = 1;
33 41
34 // directly convert from id to upper char 42 /* directly convert from id to upper char */
35 int upper_char(int id) 43 int upper_char(int id)
36 { 44 {
37 /* @TODO: add comment about 0xffffff00 and the other */ 45 /* scilab character encoding is using signed bytes packed into an int.
38 return std::abs((int)((id & 0x80) ? (id |0xffffff00) : (id & 0xff))); 46 * testing for the 7th bit with & 0x80 gives us the sign
39 } 47 * & 0xff extracts the byte if positive,
40 48 * |0xffffff00 extracts the byte if negative (assuming two's complement negative numbers representations)
41 // gives the discriminating char (either first of second if first=percent) 49 * abs() takes the upper value in scilab character encoding.
42 int id_char(int const* id) 50 */
43 { 51 return std::abs((int)((id & 0x80) ? (id |0xffffff00) : (id & 0xff)));
44 int ch(upper_char(*id)); 52 }
45 if(ch == percent) 53
46 { 54 /* gives the discriminating char (either first of second if first=percent) */
47 return upper_char((*id)>>8); 55 int id_char(int const* id)
48 } 56 {
49 return ch; 57 int ch(upper_char(*id));
50 } 58 if (ch == percent)
59 {
60 return upper_char((*id)>>8);
61 }
62 return ch;
63 }
51} 64}
52// search for an id in the libraries 65/* search for an id in the libraries
66 * as we reimplement part of Fortran function, we now use a 'bool' (for Fortran) should_return to tell calling
67 * function that it should return at once.
68 * other variables are lifted straight from Fortran code.
69 */
53void C2F(siflibs)(int* id, int* k_ptr, int* istr, int* lbibn_ptr, int* nbibn_ptr, int* ilp_ptr, int* nn_ptr, int* should_return) 70void C2F(siflibs)(int* id, int* k_ptr, int* istr, int* lbibn_ptr, int* nbibn_ptr, int* ilp_ptr, int* nn_ptr, int* should_return)
54{ 71{
55 72
56 static int const* const lstk_ptr = (int*)C2F(vstk).lstk-1; 73 static int const* const lstk_ptr = (int*)C2F(vstk).lstk-1;
57 static int const* const istk_ptr = ((int*)C2F(stack).Stk)-1; 74 static int const* const istk_ptr = ((int*)C2F(stack).Stk)-1;
58 int k, ilp, nbibn, lbibn; 75 int k, ilp, nbibn, lbibn;
59 76
60 *should_return= f_false; 77 *should_return= f_false;
61 78
62 for (k= Bot; k < C2F(vstk).isiz; ++k) 79 for (k= Bot; k < C2F(vstk).isiz; ++k)
63 { 80 {
64 int il = iadr(lstk_ptr[k]); 81 int il = iadr(lstk_ptr[k]);
65 int ip; 82 int ip;
66 83
67 if (istk_ptr[il] == sci_lib) 84 if (istk_ptr[il] == sci_lib)
68 { 85 {
69 nbibn = istk_ptr[il+1]; 86 nbibn = istk_ptr[il+1];
70 lbibn = il+2; 87 lbibn = il+2;
71 il += nbibn+2; 88 il += nbibn+2;
72 ilp = il+1; 89 ilp = il+1;
73 ip = std::max(1, id_char(id)-9); 90 ip = std::max(1, id_char(id)-9);
74 if (ip <= nclas) 91 if (ip <= nclas)
75 { 92 {
76 93
77 int n = istk_ptr[ilp+ip] -istk_ptr[ilp+ip-1]; 94 int n = istk_ptr[ilp+ip] -istk_ptr[ilp+ip-1];
78 if (n != 0) 95 if (n != 0)
79 { 96 {
80 int iln= ilp+nclas+1+(istk_ptr[ilp+ip-1]-1)*nsiz; 97 int iln= ilp+nclas+1+(istk_ptr[ilp+ip-1]-1)*nsiz;
81 98
82 for (int i = 1; i<=n; ++i, iln+= nsiz) 99 for (int i = 1; i<=n; ++i, iln+= nsiz)
83 { 100 {
84 if(eq_n<nsiz>(id, istk_ptr+iln)) 101 if (eq_n<nsiz>(id, istk_ptr+iln))
85 { // 39 102 { /* 39 */
86 if((Fin == -1) || (Fin == -3)) 103 if ((Fin == -1) || (Fin == -3))
87 { 104 {
88 C2F(com).fun= k; 105 C2F(com).fun= k;
89 Fin= i; 106 Fin= i;
90 *should_return= f_true; 107 *should_return= f_true;
91 return; 108 return;
92 } 109 }
93 110
94 Fin= i; 111 Fin= i;
95 if(C2F(errgst).err1 != 0) 112 if (C2F(errgst).err1 != 0)
96 { 113 {
97 C2F(com).fun= Fin= 0; 114 C2F(com).fun= Fin= 0;
98 *should_return= f_true; 115 *should_return= f_true;
99 return; 116 return;
100 } 117 }
101 118
102 C2F(namstr)(id,istr, nn_ptr, &from_id); 119 C2F(namstr)(id,istr, nn_ptr, &from_id);
103 *k_ptr= k; 120 *k_ptr= k;
104 *lbibn_ptr= lbibn; 121 *lbibn_ptr= lbibn;
105 *nbibn_ptr= nbibn; 122 *nbibn_ptr= nbibn;
106 *ilp_ptr= ilp; 123 *ilp_ptr= ilp;
107 *should_return= f_false; 124 *should_return= f_false;
108 return; 125 return;
109 } 126 }
110 } 127 }
111 } 128 }
112 129
113 } 130 }
114 131
115 } 132 }
116 133
117 } 134 }
118 C2F(com).fun= Fin= 0; 135 C2F(com).fun= Fin= 0;
119 *should_return= f_true; 136 *should_return= f_true;
120 return; 137 return;
121} 138}
122 139
123// search for an id in vars 140/* search for an id in vars, also lifted from Fortran code in funs.f */
124void C2F(sivars)(int* id, int* should_return) 141void C2F(sivars)(int* id, int* should_return)
125{ 142{
126 int* const lstk_ptr = (int*)C2F(vstk).lstk-1; 143 int* const lstk_ptr = (int*)C2F(vstk).lstk-1;
127 144
128 int k; 145 int k;
129 // idstk(x,y) (C2F(vstk).idstk+(x-1)+(y-1)*nsiz) 146 /* idstk(x,y) (C2F(vstk).idstk+(x-1)+(y-1)*nsiz) */
130 int* id_addr=C2F(vstk).idstk; 147 int* id_addr=C2F(vstk).idstk;
131 for( *should_return= f_false, k= Bot, id_addr+=(k-1)*nsiz; 148 for (*should_return= f_false, k= Bot, id_addr+=(k-1)*nsiz;
132 k <= C2F(vstk).isiz && !eq_n<nsiz>(id_addr, id); 149 k <= C2F(vstk).isiz && !eq_n<nsiz>(id_addr, id);
133 ++k, id_addr+=nsiz) 150 ++k, id_addr+=nsiz)
134 { 151 {
135 } 152 }
136 153
137 if( k <= C2F(vstk).isiz ) 154 if (k <= C2F(vstk).isiz)
138 {// eq_id 155 {/* eq_id */
139 int il=lstk_ptr[k];//iadr() 156 int il=lstk_ptr[k];/* iadr() */
140 il<<=1; 157 il<<=1;
141 ++il; 158 ++il;
142 159
143 if((*istk(il)!=sci_u_function) &&(*istk(il)!=sci_c_function)) 160 if ((*istk(il) != sci_u_function) && (*istk(il) != sci_c_function))
144 { 161 {
145 C2F(com).fun= Fin= 0; 162 C2F(com).fun= Fin= 0;
146 *should_return= f_true; 163 *should_return= f_true;
147 } 164 }
148 165
149 C2F(com).fun= -1; 166 C2F(com).fun= -1;
150 Fin= k; 167 Fin= k;
151 *should_return= f_true; 168 *should_return= f_true;
152 } 169 }
153 return; // *should_return= f_false; 170 return; /* *should_return= f_false; */
154} 171}
diff --git a/scilab/modules/core/src/cpp/unrolled_algorithms.hxx b/scilab/modules/core/src/cpp/unrolled_algorithms.hxx
index d1c8b6b..43ec12e 100644
--- a/scilab/modules/core/src/cpp/unrolled_algorithms.hxx
+++ b/scilab/modules/core/src/cpp/unrolled_algorithms.hxx
@@ -14,175 +14,159 @@
14#define UNROLLED_ALGORITHMS_HXX 14#define UNROLLED_ALGORITHMS_HXX
15 15
16namespace { 16namespace {
17 /* 17 /*
18 * generic template unrolling for small vectors 18 * generic template unrolling for small vectors
19 */ 19 */
20 20
21/** 21/**
22 * @TODO add comment 22 * C++ does not allow function template partial specialization so eq_n<> delegates to work to a eq_n_t<> struct
23 * which implements the function in operator().
23 * 24 *
24 * @param 25 * @param i1 : iterator to the beginning of the first sequence
25 * @return <ReturnValue> 26 * @param i2 : iterator to the beginning of the second sequence
27 * @return true iff *i1 == *i2 &&...&& *(i1+N-1) == *(i2+N-1)
26 */ 28 */
27 template<typename It1, typename It2, int N> struct eq_n_t 29 template<typename It1, typename It2, int N> struct eq_n_t
28 { 30 {
29 bool operator()(It1 i1, It2 i2) const 31 bool operator()(It1 i1, It2 i2) const /* generic recursive implementation */
30 { 32 {
31 return (*i1 == *i2) && eq_n_t<It1, It2, N-1>()(++i1, ++i2) ; 33 return (*i1 == *i2) && eq_n_t<It1, It2, N-1>()(++i1, ++i2) ;
32 } 34 }
33 }; 35 };
34 36 template<typename It1, typename It2> struct eq_n_t<It1, It2, 0> {
35/** 37 bool operator()(It1 i1, It2 i2) const /* partial specialization for N=0 */
36 * @TODO add comment 38 {
37 * 39 return true ;
38 * @param 40 }
39 * @return <ReturnValue> 41 };
40 */
41 template<typename It1, typename It2> struct eq_n_t<It1, It2, 0> {
42 bool operator()(It1 i1, It2 i2) const {
43 return true ;
44 }
45 };
46
47/** 42/**
48 * @TODO add comment 43 * Compares two sequences for equality when the size in know at compile time.
44 * Uses template metaprogramming to ensure loop unrolling.
49 * 45 *
50 * @param i1 46 * @param i1 : iterator to the beginning of the first sequence
51 * @param i2 47 * @param i2 : iterator to the beginning of the second sequence
52 * @return <ReturnValue> 48 * @return true iff *i1 == *i2 &&...&& *(i1+N-1) == *(i2+N-1)
53 */ 49 */
54 template<int N, typename It1, typename It2> bool eq_n(It1 i1, It2 i2) { 50 template<int N, typename It1, typename It2> bool eq_n(It1 i1, It2 i2)
55 return eq_n_t<It1, It2, N>()(i1, i2); 51 {
56 } 52 return eq_n_t<It1, It2, N>()(i1, i2);
53 }
57 54
58/** 55/**
59 * ensure most efficient inlining irrespectively of optimization compiler options for ids of nsiz=6 ints 56 * ensure most efficient inlining irrespectively of optimization compiler options for ids of nsiz=6 ints
60 * 57 *
61 * @param id1 58 * we make all the (4) combinations of (const or not) arguments.
62 * @param id2 59 *
60 * @param i1 : int* beginning of the first int[6]
61 * @param i2 : int* beginning of the second int[6]
62 * @return true iff *i1 == *i2 &&...&& *(i1+5) == *(i2+5)
63 */ 63 */
64 template<> bool eq_n<6,int const*, int const*>(int const* id1, int const* id2) { 64 template<> bool eq_n<6,int const*, int const*>(int const* id1, int const* id2)
65 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]); 65 {
66 } 66 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]);
67 }
67 68
68/** 69/**
69 * @TODO add comment 70 * See above.
70 *
71 * @param id1
72 * @param id2
73 */ 71 */
74 template<> bool eq_n<6,int const*, int*>(int const* id1, int* id2) 72 template<> bool eq_n<6,int const*, int*>(int const* id1, int* id2)
75 { 73 {
76 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]); 74 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]);
77 } 75 }
78 76
79/** 77/**
80 * @TODO add comment 78 * See above.
81 *
82 * @param id1
83 * @param id2
84 */ 79 */
85 template<> bool eq_n<6,int*, int const*>(int* id1, int const* id2) 80 template<> bool eq_n<6,int*, int const*>(int* id1, int const* id2)
86 { 81 {
87 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]); 82 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]);
88 } 83 }
89 84
90 85
91/** 86/**
92 * @TODO add comment 87 * See above.
93 *
94 * @param id1
95 * @param id2
96 */ 88 */
97 template<> bool eq_n<6,int*, int*>(int* id1, int* id2) 89 template<> bool eq_n<6,int*, int*>(int* id1, int* id2)
98 { 90 {
99 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]); 91 return (id1[0]==id2[0]) && (id1[1]==id2[1]) && (id1[2]==id2[2]) && (id1[3]==id2[3]) && (id1[4]==id2[4]) && (id1[5]==id2[5]);
100 } 92 }
101 93
102/** 94/**
103 * @TODO add comment 95 * C++ does not allow function template partial specialization so less_n<> delegates to work to a less_n_t<> struct
96 * which implements the function in operator().
104 * 97 *
105 * @param i1 98 * @param i1 : iterator to the beginning of the first sequence
106 * @param i2 99 * @param i2 : iterator to the beginning of the second sequence
107 * @return <ReturnValue> 100 * @return true iff [i1...i1+N[ < [i2...i2+N[ in lexicographical order
108 */ 101 */
109 template<typename It1, typename It2, int N> struct less_n_t
110 {
111 bool operator()(It1 i1, It2 i2) const
112 {
113 return (*i1<*i2) ? true : ( (*i1>*i2) ? false : less_n_t<It1, It2, N-1>()(++i1, ++i2));
114 }
115 };
116 102
117/** 103 template<typename It1, typename It2, int N> struct less_n_t
118 * @TODO add comment 104 {
119 * 105 bool operator()(It1 i1, It2 i2) const /*/ generic recursive case */
120 * @param i1 106 {
121 * @param i2 107 return (*i1<*i2) ? true : ( (*i1>*i2) ? false : less_n_t<It1, It2, N-1>()(++i1, ++i2));
122 * @return <ReturnValue> 108 }
123 */ 109 };
124 template<typename It1, typename It2> struct less_n_t<It1, It2, 0> 110
125 { 111 template<typename It1, typename It2> struct less_n_t<It1, It2, 0>
126 bool operator()(It1 i1, It2 i2) const 112 {
127 { 113 bool operator()(It1 i1, It2 i2) const /* special case for empty sequences */
128 return false ; 114 {
129 } 115 return false ;
130 }; 116 }
117 };
131 118
132/** 119/**
133 * @TODO add comment 120 * Compares two sequences for lexicographical order when the size in know at compile time.
121 * Uses template metaprogramming to ensure loop unrolling.
134 * 122 *
135 * @param i1 123 * @param i1 : iterator to the beginning of the first sequence
136 * @param i2 124 * @param i2 : iterator to the beginning of the second sequence
137 * @return <ReturnValue> 125 * @return true iff [i1...i1+N[ < [i2...i2+N[ in lexicographical order
138 */ 126 */
139 template<int N, typename It1, typename It2> bool less_n(It1 i1, It2 i2) 127 template<int N, typename It1, typename It2> bool less_n(It1 i1, It2 i2)
140 { 128 {
141 return less_n_t<It1, It2, N>()(i1, i2); 129 return less_n_t<It1, It2, N>()(i1, i2);
142 } 130 }
143 131
144/** 132/**
145 * @TODO add comment 133 * C++ does not allow function template partial specialization so copy_n<> delegates the work to a copy_n_t<> struct
134 * which implements the function in operator().
146 * 135 *
147 * @param in 136 * @param i1 : iterator to the beginning of the first sequence
148 * @param out 137 * @param i2 : iterator to the beginning of the second sequence
149 * @return <ReturnValue> 138 * @return i1+N
150 */ 139 */
151 template<typename In, typename Out, int N> struct copy_n_t
152 {
153 Out operator()(In in, Out out) const
154 {
155 *out= *in;
156 return copy_n_t<In, Out, N-1>()(++in, ++out);
157 }
158 };
159 140
160/** 141 template<typename In, typename Out, int N> struct copy_n_t
161 * @TODO add comment 142 {
162 * 143 Out operator()(In in, Out out) const /* generic case for N>0 */
163 * @param in 144 {
164 * @param out 145 *out= *in;
165 * @return <ReturnValue> 146 return copy_n_t<In, Out, N-1>()(++in, ++out);
166 */ 147 }
167 template<typename In, typename Out> struct copy_n_t<In, Out, 0> 148 };
168 { 149
169 Out operator()(In, Out out) const 150 template<typename In, typename Out> struct copy_n_t<In, Out, 0>
170 { 151 {
171 return out; 152 Out operator()(In, Out out) const /* special case for empty sequences */
172 } 153 {
173 }; 154 return out;
155 }
156 };
174 157
175/** 158/**
176 * @TODO add comment 159 * Copy one sequence to another when the size in know at compile time.
160 * Uses template metaprogramming to ensure loop unrolling.
177 * 161 *
178 * @param in 162 * @param i1 : iterator to the beginning of the input sequence
179 * @param out 163 * @param i2 : iterator to the beginning of the output sequence
180 * @return <ReturnValue> 164 * @return in+N
181 */ 165 */
182 template<int N, typename In, typename Out> Out copy_n(In in, Out out) 166 template<int N, typename In, typename Out> Out copy_n(In in, Out out)
183 { 167 {
184 return copy_n_t<In, Out, N>()(in, out); 168 return copy_n_t<In, Out, N>()(in, out);
185 } 169 }
186 170
187} 171}
188#endif 172#endif