QUDA v0.4.0
A library for QCD on GPUs
|
00001 /* 00002 MAC: 00003 00004 On my mark, unleash template hell 00005 00006 Here we are templating on the following 00007 - input precision 00008 - output precision 00009 - number of colors 00010 - number of spins 00011 - short vector lengh (float, float2, float4 etc.) 00012 00013 This is still quite a mess. Options to reduce to the amount of code 00014 bloat here include: 00015 00016 1. Using functors to define arbitrary ordering 00017 2. Use class inheritance to the same effect 00018 3. Abuse the C preprocessor to define arbitrary mappings 00019 4. Something else 00020 00021 Solution is to use class inheritance to defined different mappings, 00022 and combine it with templating on the return type. Initial attempt 00023 at this is in the cpuColorSpinorField, but this will eventually roll 00024 out here too. 00025 00026 */ 00027 00028 00029 /* 00030 00031 Packing routines 00032 00033 */ 00034 00035 #define PRESERVE_SPINOR_NORM 00036 00037 #ifdef PRESERVE_SPINOR_NORM // Preserve the norm regardless of basis 00038 double kP = (1.0/sqrt(2.0)); 00039 double kU = (1.0/sqrt(2.0)); 00040 #else // More numerically accurate not to preserve the norm between basis 00041 double kP = 0.5; 00042 double kU = 1.0; 00043 #endif 00044 00045 // SPACE_SPIN_COLOR -> FLOAT1, FLOAT2 or FLOAT4 (no "internal re-ordering") 00046 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00047 inline void packSpinorField(FloatN* a, Float *b, int V) { 00048 for (int sc=0; sc<(Ns*Nc*2)/N; sc++) { 00049 for (int zc=0; zc<N; zc++) { 00050 (a+N*V*sc)[zc] = b[sc*N+zc]; 00051 } 00052 } 00053 } 00054 00055 // SPACE_COLOR_SPIN -> FLOATN (maintain Dirac basis) 00056 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00057 inline void packQLASpinorField(FloatN* a, Float *b, int V) { 00058 for (int s=0; s<Ns; s++) { 00059 for (int c=0; c<Nc; c++) { 00060 for (int z=0; z<2; z++) { 00061 (a+(((s*Nc+c)*2+z)/N)*V*N) [((s*Nc+c)*2+z) % N] = b[(c*Ns+s)*2+z]; 00062 } 00063 } 00064 } 00065 00066 } 00067 00068 // SPACE_SPIN_COLOR -> FLOATN (Chiral -> non-relativistic) 00069 template <int Nc, int N, typename Float, typename FloatN> 00070 inline void packNonRelSpinorField(FloatN* a, Float *b, int V) { 00071 int s1[4] = {1, 2, 3, 0}; 00072 int s2[4] = {3, 0, 1, 2}; 00073 Float K1[4] = {kP, -kP, -kP, -kP}; 00074 Float K2[4] = {kP, -kP, kP, kP}; 00075 00076 for (int s=0; s<4; s++) { 00077 for (int c=0; c<Nc; c++) { 00078 for (int z=0; z<2; z++) { 00079 (a+(((s*Nc+c)*2+z)/N)*V*N )[((s*Nc+c)*2+z) % N] = 00080 K1[s]*b[(s1[s]*Nc+c)*2+z] + K2[s]*b[(s2[s]*Nc+c)*2+z]; 00081 } 00082 } 00083 } 00084 00085 } 00086 00087 // SPACE_COLOR_SPIN -> FLOATN (Chiral -> non-relativistic) 00088 template <int Nc, int N, typename Float, typename FloatN> 00089 inline void packNonRelQLASpinorField(FloatN* a, Float *b, int V) { 00090 int s1[4] = {1, 2, 3, 0}; 00091 int s2[4] = {3, 0, 1, 2}; 00092 Float K1[4] = {kP, -kP, -kP, -kP}; 00093 Float K2[4] = {kP, -kP, kP, kP}; 00094 00095 for (int s=0; s<4; s++) { 00096 for (int c=0; c<Nc; c++) { 00097 for (int z=0; z<2; z++) { 00098 (a+(((s*Nc+c)*2+z)/N)*V*N )[((s*Nc+c)*2+z) % N] = 00099 K1[s]*b[(c*4+s1[s])*2+z] + K2[s]*b[(c*4+s2[s])*2+z]; 00100 } 00101 } 00102 } 00103 00104 } 00105 00106 // Standard spinor packing, colour inside spin 00107 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00108 void packParitySpinor(FloatN *dest, Float *src, int Vh, int pad, 00109 QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00110 if (destBasis==srcBasis) { 00111 for (int i = 0; i < Vh; i++) { 00112 packSpinorField<Nc, Ns, N>(dest+N*i, src+2*Nc*Ns*i, Vh+pad); 00113 } 00114 } else if (destBasis == QUDA_UKQCD_GAMMA_BASIS && srcBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00115 if (Ns != 4) errorQuda("Can only change basis with Nspin = 4, not Nspin = %d", Ns); 00116 for (int i = 0; i < Vh; i++) { 00117 packNonRelSpinorField<Nc, N>(dest+N*i, src+2*Nc*Ns*i, Vh+pad); 00118 } 00119 } else { 00120 errorQuda("Basis change not supported"); 00121 } 00122 } 00123 00124 // QLA spinor packing, spin inside colour 00125 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00126 void packQLAParitySpinor(FloatN *dest, Float *src, int Vh, int pad, 00127 QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00128 if (destBasis==srcBasis) { 00129 for (int i = 0; i < Vh; i++) { 00130 packQLASpinorField<Nc, Ns, N>(dest+N*i, src+2*Nc*Ns*i, Vh+pad); 00131 } 00132 } else if (destBasis == QUDA_UKQCD_GAMMA_BASIS && srcBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00133 if (Ns != 4) errorQuda("Can only change basis with Nspin = 4, not Nspin = %d", Ns); 00134 for (int i = 0; i < Vh; i++) { 00135 packNonRelQLASpinorField<Nc, N>(dest+N*i, src+2*Nc*Ns*i, Vh+pad); 00136 } 00137 } else { 00138 errorQuda("Basis change not supported"); 00139 } 00140 } 00141 00142 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00143 void packFullSpinor(FloatN *dest, Float *src, int V, int pad, const int x[], int destLength, 00144 QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00145 00146 int Vh = V/2; 00147 if (destBasis==srcBasis) { 00148 for (int i=0; i<V/2; i++) { 00149 00150 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00151 00152 { // even sites 00153 int k = 2*i + boundaryCrossings%2; 00154 packSpinorField<Nc,Ns,N>(dest+N*i, src+2*Nc*Ns*k, Vh+pad); 00155 } 00156 00157 { // odd sites 00158 int k = 2*i + (boundaryCrossings+1)%2; 00159 packSpinorField<Nc,Ns,N>(dest+destLength/2+N*i, src+ 2*Nc*Ns*k, Vh+pad); 00160 } 00161 } 00162 } else if (destBasis == QUDA_UKQCD_GAMMA_BASIS && srcBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00163 if (Ns != 4) errorQuda("Can only change basis with Nspin = 4, not Nspin = %d", Ns); 00164 for (int i=0; i<V/2; i++) { 00165 00166 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00167 00168 { // even sites 00169 int k = 2*i + boundaryCrossings%2; 00170 packNonRelSpinorField<Nc,N>(dest+N*i, src+2*Nc*Ns*k, Vh+pad); 00171 } 00172 00173 { // odd sites 00174 int k = 2*i + (boundaryCrossings+1)%2; 00175 packNonRelSpinorField<Nc,N>(dest+destLength/2+N*i, src+2*Nc*Ns*k, Vh+pad); 00176 } 00177 } 00178 } else { 00179 errorQuda("Basis change not supported"); 00180 } 00181 } 00182 00183 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00184 void packQLAFullSpinor(FloatN *dest, Float *src, int V, int pad, const int x[], 00185 int destLength, QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00186 00187 int Vh = V/2; 00188 if (destBasis==srcBasis) { 00189 for (int i=0; i<V/2; i++) { 00190 00191 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00192 00193 { // even sites 00194 int k = 2*i + boundaryCrossings%2; 00195 packQLASpinorField<Nc,Ns,N>(dest+N*i, src+2*Nc*Ns*k, Vh+pad); 00196 } 00197 00198 { // odd sites 00199 int k = 2*i + (boundaryCrossings+1)%2; 00200 packQLASpinorField<Nc,Ns,N>(dest+destLength/2+N*i, src+2*Nc*Ns*k, Vh+pad); 00201 } 00202 } 00203 } else if (destBasis == QUDA_UKQCD_GAMMA_BASIS && srcBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00204 for (int i=0; i<V/2; i++) { 00205 00206 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00207 00208 { // even sites 00209 int k = 2*i + boundaryCrossings%2; 00210 packNonRelQLASpinorField<Nc,N>(dest+N*i, src+2*Nc*Ns*k, Vh+pad); 00211 } 00212 00213 { // odd sites 00214 int k = 2*i + (boundaryCrossings+1)%2; 00215 packNonRelQLASpinorField<Nc,N>(dest+destLength/2+N*i, src+2*Nc*Ns*k, Vh+pad); 00216 } 00217 } 00218 } else { 00219 errorQuda("Basis change not supported"); 00220 } 00221 } 00222 00223 00224 /* 00225 00226 Unpacking routines 00227 00228 */ 00229 00230 // SPACE_SPIN_COLOR -> FLOAT1, FLOAT2 or FLOAT4 (no "internal re-ordering") 00231 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00232 inline void unpackSpinorField(Float* a, FloatN *b, int V) { 00233 for (int sc=0; sc<(Ns*Nc*2)/N; sc++) { 00234 for (int zc=0; zc<N; zc++) { 00235 a[sc*N+zc] = (b+N*V*sc)[zc]; 00236 } 00237 } 00238 } 00239 00240 // SPACE_COLOR_SPIN -> FLOATN (maintain Dirac basis) 00241 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00242 inline void unpackQLASpinorField(Float* a, FloatN *b, int V) { 00243 for (int s=0; s<Ns; s++) { 00244 for (int c=0; c<Nc; c++) { 00245 for (int z=0; z<2; z++) { 00246 a[(c*Ns+s)*2+z] = (b+(((s*Nc+c)*2+z)/N)*V*N) [((s*Nc+c)*2+z) % N]; 00247 } 00248 } 00249 } 00250 00251 } 00252 00253 // SPACE_SPIN_COLOR -> FLOATN (Chiral -> non-relativistic) 00254 template <int Nc, int N, typename Float, typename FloatN> 00255 inline void unpackNonRelSpinorField(Float* a, FloatN *b, int V) { 00256 int s1[4] = {1, 2, 3, 0}; 00257 int s2[4] = {3, 0, 1, 2}; 00258 Float K1[4] = {-kU, kU, kU, kU}; 00259 Float K2[4] = {-kU, kU, -kU, -kU}; 00260 00261 for (int s=0; s<4; s++) { 00262 for (int c=0; c<Nc; c++) { 00263 for (int z=0; z<2; z++) { 00264 a[(s*Nc+c)*2+z] = 00265 K1[s]*(b+(((s1[s]*Nc+c)*2+z)/N)*V*N )[((s1[s]*Nc+c)*2+z) % N] + 00266 K2[s]*(b+(((s2[s]*Nc+c)*2+z)/N)*V*N )[((s2[s]*Nc+c)*2+z) % N]; 00267 } 00268 } 00269 } 00270 00271 } 00272 00273 // SPACE_COLOR_SPIN -> FLOATN (Chiral -> non-relativistic) 00274 template <int Nc, int N, typename Float, typename FloatN> 00275 inline void unpackNonRelQLASpinorField(Float* a, FloatN *b, int V) { 00276 int s1[4] = {1, 2, 3, 0}; 00277 int s2[4] = {3, 0, 1, 2}; 00278 Float K1[4] = {-kU, kU, kU, kU}; 00279 Float K2[4] = {-kU, kU, -kU, -kU}; 00280 00281 for (int s=0; s<4; s++) { 00282 for (int c=0; c<Nc; c++) { 00283 for (int z=0; z<2; z++) { 00284 a[(c*4+s)*2+z] = 00285 K1[s]*(b+(((s1[s]*Nc+c)*2+z)/N)*V*N )[((s1[s]*Nc+c)*2+z) % N] + 00286 K2[s]*(b+(((s2[s]*Nc+c)*2+z)/N)*V*N )[((s2[s]*Nc+c)*2+z) % N]; 00287 } 00288 } 00289 } 00290 00291 } 00292 00293 // Standard spinor unpacking, colour inside spin 00294 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00295 void unpackParitySpinor(Float *dest, FloatN *src, int Vh, int pad, 00296 QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00297 if (destBasis==srcBasis) { 00298 for (int i = 0; i < Vh; i++) { 00299 unpackSpinorField<Nc, Ns, N>(dest+2*Nc*Ns*i, src+N*i, Vh+pad); 00300 } 00301 } else if (srcBasis == QUDA_UKQCD_GAMMA_BASIS && destBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00302 if (Ns != 4) errorQuda("Can only change basis with Nspin = 4, not Nspin = %d", Ns); 00303 for (int i = 0; i < Vh; i++) { 00304 unpackNonRelSpinorField<Nc, N>(dest+2*Nc*Ns*i, src+N*i, Vh+pad); 00305 } 00306 } else { 00307 errorQuda("Basis change from %d to %d not supported", srcBasis, destBasis); 00308 } 00309 } 00310 00311 // QLA spinor unpacking, spin inside colour 00312 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00313 void unpackQLAParitySpinor(Float *dest, FloatN *src, int Vh, int pad, 00314 QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00315 if (destBasis==srcBasis) { 00316 for (int i = 0; i < Vh; i++) { 00317 unpackQLASpinorField<Nc, Ns, N>(dest+2*Nc*Ns*i, src+N*i, Vh+pad); 00318 } 00319 } else if (srcBasis == QUDA_UKQCD_GAMMA_BASIS && destBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00320 if (Ns != 4) errorQuda("Can only change basus with Nspin = 4, not Nspin = %d", Ns); 00321 for (int i = 0; i < Vh; i++) { 00322 unpackNonRelQLASpinorField<Nc, N>(dest+2*Nc*Ns*i, src+N*i, Vh+pad); 00323 } 00324 } else { 00325 errorQuda("Basis change from %d to %d not supported", srcBasis, destBasis); 00326 } 00327 } 00328 00329 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00330 void unpackFullSpinor(Float *dest, FloatN *src, int V, int pad, const int x[], 00331 int srcLength, QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00332 00333 int Vh = V/2; 00334 if (destBasis==srcBasis) { 00335 for (int i=0; i<V/2; i++) { 00336 00337 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00338 00339 { // even sites 00340 int k = 2*i + boundaryCrossings%2; 00341 unpackSpinorField<Nc,Ns,N>(dest+2*Ns*Nc*k, src+N*i, Vh+pad); 00342 } 00343 00344 { // odd sites 00345 int k = 2*i + (boundaryCrossings+1)%2; 00346 unpackSpinorField<Nc,Ns,N>(dest+2*Ns*Nc*k, src+srcLength/2+N*i, Vh+pad); 00347 } 00348 } 00349 } else if (srcBasis == QUDA_UKQCD_GAMMA_BASIS && destBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00350 if (Ns != 4) errorQuda("Can only change basis with Nspin = 4, not Nspin = %d", Ns); 00351 for (int i=0; i<V/2; i++) { 00352 00353 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00354 00355 { // even sites 00356 int k = 2*i + boundaryCrossings%2; 00357 unpackNonRelSpinorField<Nc,N>(dest+2*Ns*Nc*k, src+N*i, Vh+pad); 00358 } 00359 00360 { // odd sites 00361 int k = 2*i + (boundaryCrossings+1)%2; 00362 unpackNonRelSpinorField<Nc,N>(dest+2*Ns*Nc*k, src+srcLength/2+N*i, Vh+pad); 00363 } 00364 } 00365 } else { 00366 errorQuda("Basis change not supported"); 00367 } 00368 } 00369 00370 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00371 void unpackQLAFullSpinor(Float *dest, FloatN *src, int V, int pad, const int x[], 00372 int srcLength, QudaGammaBasis destBasis, QudaGammaBasis srcBasis) { 00373 00374 int Vh = V/2; 00375 if (destBasis==srcBasis) { 00376 for (int i=0; i<V/2; i++) { 00377 00378 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00379 00380 { // even sites 00381 int k = 2*i + boundaryCrossings%2; 00382 unpackQLASpinorField<Nc,Ns,N>(dest+2*Nc*Ns*k, src+N*i, Vh+pad); 00383 } 00384 00385 { // odd sites 00386 int k = 2*i + (boundaryCrossings+1)%2; 00387 unpackQLASpinorField<Nc,Ns,N>(dest+2*Nc*Ns*k, src+srcLength/2+N*i, Vh+pad); 00388 } 00389 } 00390 } else if (srcBasis == QUDA_UKQCD_GAMMA_BASIS && destBasis == QUDA_DEGRAND_ROSSI_GAMMA_BASIS) { 00391 for (int i=0; i<V/2; i++) { 00392 00393 int boundaryCrossings = i/(x[0]/2) + i/(x[1]*(x[0]/2)) + i/(x[2]*x[1]*(x[0]/2)); 00394 00395 { // even sites 00396 int k = 2*i + boundaryCrossings%2; 00397 unpackNonRelQLASpinorField<Nc,N>(dest+2*Ns*Nc*k, src+N*i, Vh+pad); 00398 } 00399 00400 { // odd sites 00401 int k = 2*i + (boundaryCrossings+1)%2; 00402 unpackNonRelQLASpinorField<Nc,N>(dest+2*Ns*Nc*k, src+srcLength/2+N*i, Vh+pad); 00403 } 00404 } 00405 } else { 00406 errorQuda("Basis change not supported"); 00407 } 00408 } 00409 00410 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00411 void packSpinor(FloatN *dest, Float *src, int V, int pad, const int x[], int destLength, 00412 int srcLength, QudaSiteSubset srcSubset, QudaSiteOrder siteOrder, 00413 QudaGammaBasis destBasis, QudaGammaBasis srcBasis, QudaFieldOrder srcOrder) { 00414 00415 // printf("%d %d %d %d %d %d %d %d %d %d %d\n", Nc, Ns, N, V, pad, length, srcSubset, subsetOrder, destBasis, srcBasis, srcOrder); 00416 00417 if (srcSubset == QUDA_FULL_SITE_SUBSET) { 00418 if (siteOrder == QUDA_LEXICOGRAPHIC_SITE_ORDER) { 00419 // We are copying from a full spinor field that is not parity ordered 00420 if (srcOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00421 packFullSpinor<Nc,Ns,N>(dest, src, V, pad, x, destLength, destBasis, srcBasis); 00422 } else if (srcOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00423 packQLAFullSpinor<Nc,Ns,N>(dest, src, V, pad, x, destLength, destBasis, srcBasis); 00424 } else { 00425 errorQuda("Source field order not supported"); 00426 } 00427 } else { 00428 // We are copying a parity ordered field 00429 00430 // check what src parity ordering is 00431 unsigned int evenOff, oddOff; 00432 if (siteOrder == QUDA_EVEN_ODD_SITE_ORDER) { 00433 evenOff = 0; 00434 oddOff = srcLength/2; 00435 } else { 00436 oddOff = 0; 00437 evenOff = srcLength/2; 00438 } 00439 00440 if (srcOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00441 packParitySpinor<Nc,Ns,N>(dest, src+evenOff, V/2, pad, destBasis, srcBasis); 00442 packParitySpinor<Nc,Ns,N>(dest + destLength/2, src+oddOff, V/2, pad, destBasis, srcBasis); 00443 } else if (srcOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00444 packQLAParitySpinor<Nc,Ns,N>(dest, src+evenOff, V/2, pad, destBasis, srcBasis); 00445 packQLAParitySpinor<Nc,Ns,N>(dest + destLength/2, src+oddOff, V/2, pad, destBasis, srcBasis); 00446 } else { 00447 errorQuda("Source field order not supported"); 00448 } 00449 } 00450 } else { 00451 // src is defined on a single parity only 00452 if (srcOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00453 packParitySpinor<Nc,Ns,N>(dest, src, V, pad, destBasis, srcBasis); 00454 } else if (srcOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00455 packQLAParitySpinor<Nc,Ns,N>(dest, src, V, pad, destBasis, srcBasis); 00456 } else { 00457 errorQuda("Source field order not supported"); 00458 } 00459 } 00460 00461 } 00462 00463 template <int Nc, int Ns, int N, typename Float, typename FloatN> 00464 void unpackSpinor(Float *dest, FloatN *src, int V, int pad, const int x[], int destLength, 00465 int srcLength, QudaSiteSubset destSubset, QudaSiteOrder siteOrder, 00466 QudaGammaBasis destBasis, QudaGammaBasis srcBasis, QudaFieldOrder destOrder) { 00467 00468 if (destSubset == QUDA_FULL_SITE_SUBSET) { 00469 if (siteOrder == QUDA_LEXICOGRAPHIC_SITE_ORDER) { 00470 // We are copying from a full spinor field that is not parity ordered 00471 if (destOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00472 unpackFullSpinor<Nc,Ns,N>(dest, src, V, pad, x, srcLength, destBasis, srcBasis); 00473 } else if (destOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00474 unpackQLAFullSpinor<Nc,Ns,N>(dest, src, V, pad, x, srcLength, destBasis, srcBasis); 00475 } else { 00476 errorQuda("Source field order not supported"); 00477 } 00478 } else { 00479 // We are copying a parity ordered field 00480 00481 // check what src parity ordering is 00482 unsigned int evenOff, oddOff; 00483 if (siteOrder == QUDA_EVEN_ODD_SITE_ORDER) { 00484 evenOff = 0; 00485 oddOff = srcLength/2; 00486 } else { 00487 oddOff = 0; 00488 evenOff = srcLength/2; 00489 } 00490 00491 if (destOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00492 unpackParitySpinor<Nc,Ns,N>(dest, src+evenOff, V/2, pad, destBasis, srcBasis); 00493 unpackParitySpinor<Nc,Ns,N>(dest + destLength/2, src+oddOff, V/2, pad, destBasis, srcBasis); 00494 } else if (destOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00495 unpackQLAParitySpinor<Nc,Ns,N>(dest, src+evenOff, V/2, pad, destBasis, srcBasis); 00496 unpackQLAParitySpinor<Nc,Ns,N>(dest + destLength/2, src+oddOff, V/2, pad, destBasis, srcBasis); 00497 } else { 00498 errorQuda("Source field order not supported"); 00499 } 00500 } 00501 } else { 00502 // src is defined on a single parity only 00503 if (destOrder == QUDA_SPACE_SPIN_COLOR_FIELD_ORDER) { 00504 unpackParitySpinor<Nc,Ns,N>(dest, src, V, pad, destBasis, srcBasis); 00505 } else if (destOrder == QUDA_SPACE_COLOR_SPIN_FIELD_ORDER) { 00506 unpackQLAParitySpinor<Nc,Ns,N>(dest, src, V, pad, destBasis, srcBasis); 00507 } else { 00508 errorQuda("Source field order not supported"); 00509 } 00510 } 00511 00512 } 00513