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