double ivar[] vs. float ivar[]

David Gobbi dgobbi at irus.rri.on.ca
Fri Apr 28 01:42:49 EDT 2000


Hi All,

There is a marked lack of consistency in VTK whether floating-point
ivars are double or float.  Or rather, there is some consistency...
new classes generally use double, older classes use float.

My guess is that most people would prefer that all of the 
float[] ivars were converted to double[], but this hasn't been
done because changing all of those 'float *GetIvar()' methods to
'double *GetIvar()' would break compatibility with many applications
that use VTK.


There is a way around this!  By using proxy classes you can (as far
as the users are concerned) define both of the following:

float  *GetIvar();
double *GetIvar();


Here's how to do it:  first, we create a proxy class such as the
following:

class vtkdouble3
{
public:
  vtkdouble3(double *dp) { 
    this->fdata[0] = this->ddata[0] = dp[0]; 
    this->fdata[1] = this->ddata[1] = dp[1]; 
    this->fdata[2] = this->ddata[2] = dp[2]; }; 
  operator double *() { return this->ddata; };
  operator float *() { return this->fdata; };
  double operator[](int i) { return this->ddata[i]; };
  double operator*() { return this->ddata[0]; };

private:
  double ddata[3];
  float  fdata[3];
  vtkdouble3();
};


Then, we define a VTK class that uses this proxy class:

class vtkClass : public vtkObject
{
public:
  vtkdouble3 GetIvar() { return vtkdouble3(this->Ivar); }; 
 
protected:
  double Ivar[3];
}


Now, in our VTK code we can do this:

vtkClass *myClass = vtkClass::New();

float  *fp = myClass->GetIvar();
double *dp = myClass->GetIvar();


Here's how it works:  the GetIvar() method creates a vtkdouble3
object and returns it on the stack.  The vtkdouble3 object consists
of an array of 3 doubles and another array of 3 floats.  The 
vtkdouble3 array class also has type-conversion methods that will
allow it to be converted to either float * (i.e. return a pointer
to its float array) or double * (i.e. return a pointer to its
double array).


There is an added advantage to using a proxy class.  Because the
use of the proxy class involves passing the contents of the Ivar
array on the stack, instead of simply passing a pointer to the
Ivar array, using a proxy class guarantees that the GetIvar() method
is thread safe.  


There is a downside, when you use proxy classes the method

double *dp = myClass->GetIvar();

is slightly less efficient than

double dp[3];
myClass->GetIvar(dp);

whereas it used to be more efficient.  Of course, everybody should
have been using myClass->GetIvar(dp) most of the time, anyway, because
of thread safety and related issues.


So, finally, here is my proposal:  

Most of those float Ivar[]'s really should be converted to 
double Ivar[], but we don't want to break people's VTK
applications.  So, we convert the Ivar[]'s to double 
but at the same time we write a special 
vtkGetVectorDoubleNMacro(Ivar) method that returns the
proxy class instead of a pointer, and that also supports
GetIvar(float a[N]) and GetIvar(float *a1, float *a2, float *a3).
A special vtkSetVectorDoubleNMacro(Ivar) would be required, as well.

Because the majority of the changes would occur within these
Set and Get macros they could be achieved without an immense
amount of effort. There are many classes that have float
*GetIvar() methods that don't use the vtkGet macros, and these
would have to be handled individually.  Also, the tcl/python/java
wrappers would have to be modified to recognize the new macros
and the new proxy classes.

 - David

--
  David Gobbi, MSc                    dgobbi at irus.rri.on.ca
  Advanced Imaging Research Group
  Robarts Research Institute, University of Western Ontario




More information about the vtk-developers mailing list