SCI Home Software Documentation Installation User's Guide Developer's Guide

CIBC:Development:Virtual:Datatypes

From SCIRun Documentation Wiki

Jump to: navigation, search

Contents

How to deal with different datatypes in SCIRun Fields?

The basic interface

The SCIRun Fields allow for a whole set of different data types to be used as the storage for data. These data types include : char, unsigned char, short, unsigned short, int, unsigned int, float, double, Vector and Tensor. And in the future we probably expand these with more datatypes. My proposal is to include complex, CVector, and CTensor at some point for additional support.

Current the virtual interface does not have a pluriform object that represents all of these datatypes. The current mechanism requires users to cast the data to a specified format, after which it can be processed in the algorithm. The most useful functions for obtaining and storing data are:

 VField {
   ...
   template<class T>
   void get_value(T& val, VMesh::index_type idx);
   
   template<class T>
   void set_value(const T& val, VMesh::index_type idx);
   ...
 };


Both the set and get method are templated and allow any of the following types to be used to set data: char, unsigned char, short, unsigned short, int, unsigned int, long long, unsigned long long, fload, double, Vector, and Tensor. The basic mode of operation for these functions is that they take a type and internally cast to or from the format in which the data is stored. Internally the VField class has a long list of virtual functions that do the casting for the different datatypes. These are all exposed through the same get_value and set_value interface.

Hence one can process an input field of type short and an output field of type long, using doubles as intermediates:

e.g. :

 VField* short_field = input->vfield();
 VField* long_field  = output->vfield();
 
 VField::size_type nv = short_field->num_values();
  
 for (VField::index_type i=0; i< nv; i++) 
 {
   double val;
   short_field->get_value(val,i);
   long_field->set_value(val*2,i); 
 }

The only exceptions are Vectors or Tensors which cannot be casted easily to a double (The latter will result in a value zero, when one tries to cast them implicity). Hence to deal with multiple datatypes one should implement the code at least for double, Vector and Tensor. At least there where Vectors and Tensors can be considered proper field datatypes.

e.g:


 VField* ifield = input->vfield();
 VField* ofield  = output->vfield();
 
 VField::size_type nv = ifield->num_values();
 
 if (ifield->is_scalar())
 { 
   for (VField::index_type i=0; i< nv; i++) 
   {
     double val;
     ifield->get_value(val,i);
     ofield->set_value(val*2,i); 
   }
 }
 if (ifield->is_vector())
 {
   for (VField::index_type i=0; i< nv; i++) 
   {
     Vector val;
     ifield->get_value(val,i);
     ofield->set_value(val*2,i); 
   }
 }
 
 ....


Using templates to implement multiple datatypes

At some point if one decides for for instance efficiency reasons to handle all data types. It often becomes more easy to template that part of the code that deals with the datatypes:


 template<class DATA>
 void HandleData(VField* ifield, VField* ofield)
 {
   VField::size_type nv = ifield->num_values();
   for (VField::index_type i=0; i< nv; i++) 
   {
     DATA val;
     ifield->get_value(val,i);
     ofield->set_value(val*2,i); 
   }    
 }

 ...
 
 if (ifield->is_short()) HandleData<short>(ifield,ofield);
 if (ifield->is_int()) HandleData<int>(ifield,ofield);
 if (ifield->is_vector()) HandleData<Vector>(ifield,ofield);

This requires less coding if data needs to be processed.


Copying data only

When one wants to copy data. A lot of geometric processing requires only copying data one can use the following function call in VField

 VField {
   ...
   void copy_value(VField*, VField::index_type, VField::index_type);
   ...
 };

This function copies the data from the container specified in the parameters to the container from which the function is called. If the data needs casting the function will cast the data. This way one does not even need to query the data it is transported directly from source to destination. If the data needs to be casted, data is casted automatically. Note that casting from Tensor to Vector for example will result in empty Vectors

e.g.:

 VField* ifield = input->vfield();
 VField* ofield  = output->vfield();
 
 VField::size_type nv = ifield->num_values();
  
 for (VField::index_type i=0; i< nv; i++) 
 {
   ofield->copy_value(ifield,i,i);
 }


If the number of entries is the same like in the above example it can be done even easier:


 VField* ifield = input->vfield();
 VField* ofield  = output->vfield();
 
 ofield->copy_values(ifield);
Personal tools