stafield_cuda.h
1 /*#############################################################################
2  *
3  * Copyright 2011 by Henrik Skibbe and Marco Reisert
4  *
5  *
6  * This file is part of the STA-ImageAnalysisToolbox
7  *
8  * STA-ImageAnalysisToolbox is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * STA-ImageAnalysisToolbox is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with STA-ImageAnalysisToolbox.
20  * If not, see <http://www.gnu.org/licenses/>.
21  *
22  *
23 *#############################################################################*/
24 
25 #ifndef STA_FIELD_CLASS_CUDA_H
26 #define STA_FIELD_CLASS_CUDA_H
27 
28 #include "stafield.h"
29 #include "stensorcuda.h"
30 #include "cuda_runtime.h"
31 #include <stdio.h>
32 
33 
34 
35 
36 namespace hanalysis
37 {
38 
39 
40 
41 
43 template<typename T>
44 class stafieldGPU : public _stafield<T>
45 {
46 private:
47 
48  T * data;
49 public:
50 
51 
55  T * getData() {
56  return this->data;
57  };
58 
62  const T * getDataConst() const {
63  return this->data;
64  };
65 
66 
67 
68  stafieldGPU() : _stafield<T>(), data(NULL) {};
69 
70  stafieldGPU(const stafieldGPU & field) : _stafield<T>(), data(NULL)
71  {
72  (*this)=field;
73  }
74 
75 
76 
77 
78  stafieldGPU(const std::size_t shape[],
79  int L,
82  : _stafield<T>(), data(NULL)
83  {
85  throw (hanalysis::STAError("error STA_FIELD_STORAGE_C is not supported by stafieldGPU!"));
86 
87  if (L<0)
88  throw STAError("L must be >= 0");
90  this->field_type=field_type;
91  this->shape[0]=shape[0];
92  this->shape[1]=shape[1];
93  this->shape[2]=shape[2];
94  this->L=L;
95  int numcomponents=hanalysis::order2numComponents(field_storage,field_type,L);
96  int numVoxel=shape[0]*shape[1]*shape[2];
97  if (hanalysis::verbose>0)
98  printf("L: %d , (%i,%i,%i) , // %i\n",L,shape[0],shape[1],shape[2],numcomponents);
99  if (hanalysis::verbose>0)
100  printf("allocating %i bytes\n",numcomponents*numVoxel*sizeof(std::complex<T>));
101 
102  hanalysis_cuda::gpu_malloc<T>(this->data,numcomponents*numVoxel*2*sizeof(T));
103  //cudaMalloc((void **) &this->data, numcomponents*numVoxel*2*sizeof(float));
104  //this->data=new std::complex<T>[numcomponents*numVoxel];
105  }
106 
107 
114  stafieldGPU(const std::size_t shape[],
115  int L,
118  T * data) : _stafield<T>() , data(NULL)
119  {
120  if (field_storage==hanalysis::STA_FIELD_STORAGE_C)
121  throw (hanalysis::STAError("error STA_FIELD_STORAGE_C is not supported by stafieldGPU!"));
122 
123  if (L<0)
124  throw (hanalysis::STAError("L must be >= 0"));
125  if (data==NULL)
126  throw ( hanalysis::STAError("data is NULL-pointer"));
127  this->field_storage=field_storage;
128  this->field_type=field_type;
129  this->shape[0]=shape[0];
130  this->shape[1]=shape[1];
131  this->shape[2]=shape[2];
132  this->data=data;
133  this->own_memory=false;
134  this->L=L;
135  }
136 
137 
138 
139 
140  stafieldGPU & operator=(const stafieldGPU & f)
141  {
142  if (this==&f)
143  return *this;
144 
145  if ((this->L==-1)&&(f.L==-1))
146  return *this;
147 
148  if ((f.object_is_dead_soon==1)
149  &&(this->own_memory)
150  )
151  {
152  if (f.object_is_dead_soon>1)
153  throw STAError("error: something went wrong with the memory managemant \n");
154 
155  if (this->own_memory && (this->data!=NULL) && (this->object_is_dead_soon<2))
156  delete [] this->data;
157 
158  this->set_death(&f);
159  this->data=f.data;
160 
162  this->field_type=f.field_type;
163 
164  this->shape[0]=f.shape[0];
165  this->shape[1]=f.shape[1];
166  this->shape[2]=f.shape[2];
167 
168  this->setElementSize(f.getElementSize());
169 
170  this->L=f.L;
171 
172  this->stride=f.stride;
173  this->own_memory=f.own_memory;
174  return *this;
175  }
176 
177 
178  int check=0;
179 
180  if ((*this)!=f)
181  {
182  if (this->stride!=0)
183  throw STAError("warning: operator= (stride!=0) shared memory block but alocating new (own) memory would be nrequired \n");
184 
185  if (!this->own_memory)
186  throw STAError("warning: operator= (!own_memory): shared memory block but alocating new (own) memory would be nrequired \n");
187 
188 
189 
190  if (this->own_memory && (this->data!=NULL))
191  cudaFree(this->data);
192 
194  this->field_type=f.field_type;
195  this->shape[0]=f.shape[0];
196  this->shape[1]=f.shape[1];
197  this->shape[2]=f.shape[2];
198 
199  this->setElementSize(f.getElementSize());
200 
201  this->data=NULL;
202  this->stride=0;
203  this->own_memory=true;
204  this->L=f.L;
205  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
206  int numVoxel=this->shape[0]*this->shape[1]*this->shape[2];
207  hanalysis_cuda::gpu_malloc(this->data,numcomponents*numVoxel*sizeof(std::complex<T>));
208  check=1;
209  }
210 
211  if ((f.stride==0)&&(this->stride==0))
212  {
213  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
214  this->setElementSize(f.getElementSize());
215  hanalysis_cuda::gpu_memcpy_d2d(f.data,this->data,this->shape[0]*this->shape[1]*this->shape[2]*numcomponents*sizeof(std::complex<T>));
216  }
217  else
218  {
219  this->setElementSize(f.getElementSize());
220  if (check==1)
221  throw STAError("BullShit");
222 
224  (this->field_type!=hanalysis::STA_OFIELD_SINGLE))
225  throw STAError("operator= this cannot happen ! the input field must be STA_OFIELD_SINGLE");
226  // view -> copy
227  int numcomponents_new=this->L+1;
229  numcomponents_new=2*this->L+1;
230  numcomponents_new*=2;
231 
232 
233  try
234  {
235  hanalysis_cuda::copySubfield2Subfield(f.data,
236  this->data,
237  this->getNumVoxel(),
238  2*f.getStride(),
239  2*this->getStride(),
240  numcomponents_new);
241  } catch (hanalysis::STAError & error)
242  {
243  throw error;
244  }
245  }
246 
247  return *this;
248  }
249 
250 
251  stafield<T> gpu2cpu() const
252  {
253  try
254  {
255  stafield<T> result;
256  this->set_death(&result);
257  result=(*this);
258  return result;
259  }
260  catch (hanalysis::STAError & error)
261  {
262  throw error;
263  }
264  }
265 
266  stafieldGPU & operator=(const stafield<T> & f)
267  {
268 
269 
270  if (f.getStorage()==hanalysis::STA_FIELD_STORAGE_C)
271  throw (hanalysis::STAError("error STA_FIELD_STORAGE_C is not supported by stafieldGPU!"));
272 
273  if ((this->L==-1)&&(f.getRank()==-1))
274  return *this;
275  if (!f.oneBlockMem())
276  throw (hanalysis::STAError("error copying host memory to device memory, the host memory must be alignd in one single block!"));
277 
278  if ((*this)!=f)
279  {
280  if (this->stride!=0)
281  throw STAError("warning: operator= (stride!=0) shared memory block but alocating new (own) memory would be nrequired \n");
282 
283  if (!this->own_memory)
284  throw STAError("warning: operator= (!own_memory): shared memory block but alocating new (own) memory would be nrequired \n");
285 
286  if (this->own_memory && (this->data!=NULL))
287  cudaFree(this->data);
288 
289  this->field_storage=f.getStorage();
290  this->field_type=f.getType();
291  this->shape[0]=f.getShape()[0];
292  this->shape[1]=f.getShape()[1];
293  this->shape[2]=f.getShape()[2];
294 
295  this->setElementSize(f.getElementSize());
296 
297  this->data=NULL;
298  this->stride=0;
299  this->own_memory=true;
300  this->L=f.getRank();
301  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
302  hanalysis_cuda::gpu_malloc(this->data,numcomponents*this->getNumVoxel()*sizeof(std::complex<T>));
303  }
304 
305  if (this->stride==0)
306  {
307  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
308  this->setElementSize(f.getElementSize());
309  T * const src=( T* const)(f.getDataConst());
310  hanalysis_cuda::gpu_memcpy_h2d(src,this->data,this->getNumVoxel()*numcomponents*sizeof(std::complex<T>));
311  } else
312  throw (hanalysis::STAError("error copying host memory to device memory, the (existing) device memory must be alignd in one single block!"));
313  return *this;
314  }
315 
316 
317 
318 
319 
320 
321 
322 
323 
328  stafieldGPU get(int l) const
329  {
330  if (l<0)
331  throw (hanalysis::STAError("error retrieving (sub) field l, l must be >= 0"));
332  if (l>this->L)
333  throw (hanalysis::STAError("error retrieving (sub) field l, l must be <= L"));
334 
335  if ((this->field_type==STA_OFIELD_ODD)&&(l%2==0))
336  throw (hanalysis::STAError("error retrieving (sub) field l, l must be odd"));
337 
338  if ((this->field_type==STA_OFIELD_EVEN)&&(l%2!=0))
339  throw (hanalysis::STAError("error retrieving (sub) field l, l must be even"));
340 
341  if ((this->field_type==STA_OFIELD_SINGLE)&&(l!=this->L))
342  throw (hanalysis::STAError("error retrieving (sub) field l, l must be equal to L"));
343 
344 
345  T * component_data;
346  int offset=hanalysis::getComponentOffset(this->field_storage,this->field_type,l);
347  int numcomponents=hanalysis::order2numComponents(this->field_storage,this->field_type,this->L);
348 
349  component_data=this->data+2*offset;
350 
351  stafieldGPU view(this->shape,
352  l,
353  this->field_storage,
355  component_data);
356  this->set_death(&view);
357  view.stride=numcomponents;
358 
359  view.setElementSize(this->getElementSize());
360  return view;
361  }
362 
363 
368  stafieldGPU operator[](int l) const
369  {
370  try
371  {
372  return this->get(l);
373  }
374  catch (hanalysis::STAError & error)
375  {
376  throw error;
377  }
378  }
379 
380 
381 
382  ~stafieldGPU()
383  {
384  if (this->own_memory && (this->data!=NULL))
385  {
386  if (do_classcount)
387  printf("destroying stafieldGPU %i / remaining: %i [own]",this->classcount_id,--classcount);
388 
389  if (this->object_is_dead_soon<2)
390  {
391  if (do_classcount)
392  printf(" (deleting data)\n");
393 
394  if (hanalysis::verbose>0)
395  printf("field destrucor -> deleting data\n");
396  cudaFree(this->data);
397  }
398  else
399  if (do_classcount)
400  printf(" (not deleting data, still having references)\n");
401  } else
402  {
403  if (do_classcount)
404  {
405  if (this->L==-1)
406  printf("destroying stafieldGPU %i / remaining: %i [empty]\n",this->classcount_id,--classcount);
407  else
408  printf("destroying stafieldGPU %i / remaining: %i [view]\n",this->classcount_id,--classcount);
409  }
410  if (hanalysis::verbose>0)
411  printf("field destrucor -> --\n");
412  }
413  }
414 
415 
416 
417 
418  static void Prod(const stafieldGPU & stIn1,
419  const stafieldGPU & stIn2,
420  stafieldGPU & stOut,
421  int J,
422  bool normalize=false,
423  std::complex<T> alpha= T( 1 ),
424  bool clear_result = false)
425  {
426  if ( ( std::abs ( stIn1.getRank()-stIn2.getRank() ) >J ) ||
427  ( J>std::abs ( stIn1.getRank()+stIn2.getRank() ) ) )
428  throw (hanalysis::STAError("Prod: ensure that |l1-l2|<=J && |l1+l2|<=J"));
429  if ( ( ( stIn1.getRank()+stIn2.getRank()+J ) %2!=0 ) && ( normalize ) )
430  throw (hanalysis::STAError("Prod: ensure that l1+l2+J even"));
431 
432  if (stOut.getRank()!=J)
433  throw (hanalysis::STAError("Prod: ensure that stOut has wrong Rank!"));
434 
435 
436  if ((!stafieldGPU::equalShape(stIn1,stOut))||(!stafieldGPU::equalShape(stIn2,stOut)))
437  throw (hanalysis::STAError("Prod: shapes differ!"));
438  if ((stIn1.getStorage()!=stOut.getStorage())||(stIn2.getStorage()!=stOut.getStorage()))
439  throw (hanalysis::STAError("Prod: storage type must be the same"));
440  if (stIn1.getType()!=hanalysis::STA_OFIELD_SINGLE)
441  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE"));
442  if (stIn1.getType()!=stIn2.getType())
443  throw (hanalysis::STAError("Prod: first input field type must be STA_OFIELD_SINGLE"));
444  if (stOut.getType()!=stIn1.getType())
445  throw (hanalysis::STAError("Prod: stOut field type must be STA_OFIELD_SINGLE"));
446 
447  int stride_in1 = stIn1.getStride();
448  int stride_in2 = stIn2.getStride();
449  int stride_out = stOut.getStride();
450 
451  if (hanalysis::verbose>0)
452  printf("Prod: stride_in1: %i,stride_in2: %i stride_out %i\n",stride_in1,stride_in2,stride_out);
453  try
454  {
455  hanalysis_cuda::sta_product(
456  stIn1.getDataConst(),
457  stIn2.getDataConst(),
458  stOut.getData(),
459  stIn1.getShape(),
460  stIn1.getRank(),
461  stIn2.getRank(),
462  stOut.getRank(),
463  alpha,
464  normalize,
465  stIn1.getStorage(),
466  2*stride_in1,
467  2*stride_in2,
468  2*stride_out,
469  clear_result);
470  } catch (hanalysis::STAError & error)
471  {
472  throw error;
473  }
474 // int err=hanalysis::sta_product(
475 // stIn1.getDataConst(),
476 // stIn2.getDataConst(),
477 // stOut.getData(),
478 // stIn1.getShape(),
479 // stIn1.getRank(),
480 // stIn2.getRank(),
481 // stOut.getRank(),
482 // alpha,
483 // normalize,
484 // stIn1.getStorage(),
485 // stride_in1,
486 // stride_in2,
487 // stride_out,
488 // clear_result);
489  /*
490  if (err==-1)
491  {
492  throw (hanalysis::STAError("Prod: error!"));
493  }*/
494  }
495 
496 
497  static void Deriv(const stafieldGPU & stIn,
498  stafieldGPU & stOut,
499  int Jupdown,
500  bool conjugate=false,
501  std::complex<T> alpha= T( 1 ),
502  bool clear_result = false,
503  int accuracy=0
504  )
505  {
506  if (!stafieldGPU::equalShape(stIn,stOut))
507  throw (hanalysis::STAError("Deriv: shapes differ!"));
508  if (stIn.getStorage()!=stOut.getStorage())
509  throw (hanalysis::STAError("Deriv: storage type must be the same"));
510  if (stIn.getType()!=hanalysis::STA_OFIELD_SINGLE)
511  throw (hanalysis::STAError("Deriv: first input field type must be STA_OFIELD_SINGLE"));
512  if (stOut.getType()!=stIn.getType())
513  throw (hanalysis::STAError("Deriv: stOut field type must be STA_OFIELD_SINGLE"));
514  if (stOut.getRank()!=stIn.getRank()+Jupdown)
515  throw (hanalysis::STAError("Deriv: stOut rank must be input rank+Jupdown"));
516 
517  int stride_in = stIn.getStride();
518  int stride_out = stOut.getStride();
519 
520  if (hanalysis::verbose>0)
521  printf("Deriv: stride_in: %i stride_out %i\n",stride_in,stride_out);
522 
523  try {
524  hanalysis_cuda::sta_derivatives(
525  stIn.getDataConst(),
526  stOut.getData(),
527  stIn.getShape(),
528  stIn.getRank(),
529  Jupdown,
530  conjugate,
531  alpha,
532  stIn.getStorage(),
533  stIn.getElementSize(),
534  2*stride_in,
535  2*stride_out,
536  clear_result,
537  accuracy);
538  } catch (hanalysis::STAError & error)
539  {
540  throw error;
541  }
542 
543 // int err=hanalysis::sta_derivatives(
544 // stIn.getDataConst(),
545 // stOut.getData(),
546 // stIn.getShape(),
547 // stIn.getRank(),
548 // Jupdown,
549 // conjugate,
550 // alpha,
551 // stIn.getStorage(),
552 // stIn.getElementSize(),
553 // stride_in,
554 // stride_out,
555 // clear_result,
556 // accuracy);
557  /*
558  if (err==-1)
559  throw (hanalysis::STAError("Deriv: error!"));*/
560  }
561 
562 
563 
564  static void FFT(const stafieldGPU & stIn,
565  stafieldGPU & stOut,
566  bool forward,
567  bool conjugate=false,
568  T alpha= T( 1 ))
569  {
570  if ((!stafieldGPU::equalShape(stIn,stOut))||
571  (stIn.field_type!=stOut.field_type)||
572  (stIn.L!=stOut.L)||
573  (((stIn.field_storage==STA_FIELD_STORAGE_C)||
574  (stOut.field_storage==STA_FIELD_STORAGE_C))&&
575  (stIn.field_storage!=stOut.field_storage)))
576  throw (hanalysis::STAError("FFT: shapes differ!"));
577 
578  std::size_t ncomponents_in=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
579  std::size_t ncomponents_out=hanalysis::order2numComponents(stOut.getStorage(),stOut.getType(),stOut.L);
580  if (((stIn.stride!=0)&&(ncomponents_in!=stIn.stride))||((stOut.stride!=0)&&(ncomponents_out!=stOut.stride)))
581  throw (hanalysis::STAError("FFT: doesn't work on this kind of views!"));
582  if ((stIn.data==stOut.data))
583  throw (hanalysis::STAError("FFT: inplace not supported!"));
584 
585 
586  hanalysis::STA_FIELD_STORAGE new_field_storage=stIn.getStorage();
587  if (new_field_storage==hanalysis::STA_FIELD_STORAGE_R)
588  new_field_storage=hanalysis::STA_FIELD_STORAGE_RF;
589  else
590  if (new_field_storage==hanalysis::STA_FIELD_STORAGE_RF)
591  new_field_storage=hanalysis::STA_FIELD_STORAGE_R;
592  stOut.field_storage=new_field_storage;
593 
594  if ((stIn.getStorage()==STA_FIELD_STORAGE_C)&&(stOut.getStorage()!=STA_FIELD_STORAGE_C))
595  throw (hanalysis::STAError("FFT: storage type must be the same"));
596 
597 
598 
599 
600  int stride_in = stIn.getStride();
601  int stride_out = stOut.getStride();
602  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
603 
604  if (hanalysis::verbose>0)
605  printf("FFT: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
606  try {
607  hanalysis_cuda::sta_fft(
608  stIn.getDataConst(),
609  stOut.getData(),
610  stIn.getShape(),
611  ncomponents,
612  forward,
613  conjugate,
614  alpha);
615  } catch (hanalysis::STAError & error)
616  {
617  throw error;
618  }
619  }
620 
621 
622 
623  static void Lap(const stafieldGPU & stIn,
624  stafieldGPU & stOut,
625  T alpha= T( 1 ),
626  bool clear_result = false)
627  {
628  if (stIn!=stOut)
629  throw (hanalysis::STAError("Lap: shapes differ!"));
630  if (stIn.getStorage()!=stOut.getStorage())
631  throw (hanalysis::STAError("Lap: storage type must be the same"));
632  int stride_in = stIn.getStride();
633  int stride_out = stOut.getStride();
634  int ncomponents=hanalysis::order2numComponents(stIn.getStorage(),stIn.getType(),stIn.L);
635 
636 
637  if (hanalysis::verbose>0)
638  printf("Lap: stride_in: %i stride_out %i , ncomp: %i\n",stride_in,stride_out,ncomponents);
639 
640 
641  try {
642  hanalysis_cuda::sta_laplace (
643  stIn.getDataConst(),
644  stOut.getData(),
645  stIn.getShape(),
646  ncomponents,
647  alpha,
648  stride_in,
649  stride_out,
650  clear_result);
651  } catch (hanalysis::STAError & error)
652  {
653  throw error;
654  }
655 
656 
657  }
658 
659 
661  stafieldGPU lap(T alpha= T( 1 )) const
662  {
663 
664  try
665  {
666  stafieldGPU result(this->shape,this->L,this->field_storage,this->field_type);
667  this->set_death(&result);
668  Lap(*this,result,alpha,true);
669  return result;
670  }
671  catch (hanalysis::STAError & error)
672  {
673  throw error;
674  }
675  }
676 
677 
679  stafieldGPU fft(bool forward,
680  bool conjugate=false,
681  T alpha= T( 1 )) const
682  {
683  try
684  {
685  stafieldGPU result(this->shape,this->L,this->field_storage,this->field_type);
686  this->set_death(&result);
687  FFT(*this,result,forward,conjugate,alpha);
688  return result;
689  }
690  catch (hanalysis::STAError & error)
691  {
692  throw error;
693  }
694  }
695 
696 
699  bool conjugate=false,
700  std::complex<T> alpha= T( 1 ),
701  int accuracy=0
702  ) const
703  {
704  try
705  {
706  stafieldGPU result(this->shape,this->L+J,this->field_storage,this->field_type);
707  this->set_death(&result);
708  Deriv(*this,result,J,conjugate,alpha,true,accuracy);
709 
710  return result;
711  }
712  catch (hanalysis::STAError & error)
713  {
714 
715  throw error;
716  }
717 
718  }
719 
722  int J,
723  bool normalize=false,
724  std::complex<T> alpha= T( 1 )) const
725  {
726  try
727  {
728  stafieldGPU result(this->shape,J,this->field_storage,this->field_type);
729  this->set_death(&result);
730  //printf("prod prod\n");
731  //printf("%d %d %d \n",this->getRank(),b.getRank(),result.getRank());
732  Prod(*this,b,result,J,normalize,alpha,true);
733  return result;
734  }
735  catch (hanalysis::STAError & error)
736  {
737  throw error;
738  }
739  }
740 
741 
742  //void printf(const char* arg1, int arg2);
743 
744 };
745 
746 
747 }
748 
749 
750 
751 #endif
752 
STA_FIELD_STORAGE
tensor field data storage
Definition: stensor.h:5163
tensor field has all components of even ranks :
Definition: stensor.h:5184
hanalysis::STA_FIELD_STORAGE field_storage
must be either STA_FIELD_STORAGE_C, STA_FIELD_STORAGE_R or STA_FIELD_STORAGE_RF
Definition: stafield.h:78
the STA error class
Definition: sta_error.h:68
stafieldGPU(const std::size_t shape[], int L, hanalysis::STA_FIELD_STORAGE field_storage, hanalysis::STA_FIELD_TYPE field_type, T *data)
Definition: stafield_cuda.h:114
represents spherical tensor fields (GPU version)
Definition: stafield_cuda.h:44
tensor field has one single component of rank :
Definition: stensor.h:5180
STA_FIELD_TYPE
tensor field data interpretations according to certain symmetries
Definition: stensor.h:5177
int L
tensor rank
Definition: stafield.h:82
std::size_t shape[3]
image shape
Definition: stafield.h:74
stafieldGPU fft(bool forward, bool conjugate=false, T alpha=T(1)) const
see FFT
Definition: stafield_cuda.h:679
stafieldGPU lap(T alpha=T(1)) const
see Lap
Definition: stafield_cuda.h:661
stafieldGPU deriv(int J, bool conjugate=false, std::complex< T > alpha=T(1), int accuracy=0) const
see Deriv
Definition: stafield_cuda.h:698
Definition: stensor.h:5173
hanalysis::STA_FIELD_TYPE field_type
must be either STA_OFIELD_SINGLE, STA_OFIELD_FULL, STA_OFIELD_EVEN or STA_OFIELD_ODD ...
Definition: stafield.h:80
Definition: stensor.h:5167
const T * getDataConst() const
Definition: stafield_cuda.h:62
The STA-ImageAnalysisToolkit namespace.
Definition: stafield.h:55
tensor field has all components of odd ranks :
Definition: stensor.h:5186
T * getData()
Definition: stafield_cuda.h:55
stafieldGPU prod(const stafieldGPU &b, int J, bool normalize=false, std::complex< T > alpha=T(1)) const
see Prod
Definition: stafield_cuda.h:721
stafieldGPU operator[](int l) const
Definition: stafield_cuda.h:368
represents spherical tensor fields
Definition: stafield.h:62
Definition: stensor.h:5170