Hi Dirk,

Dirk Reiners wrote:
> Carsten Neumann wrote:
>> For "arbitrary" type access there are still member template access
>> functions in GeoVectorProperty:
[snip]
> 
> The idea was to have the two conversion one as a last resort that would 
> always work. Whenever sensible it would be overridden by faster version. 
> But they all have the same names so that no matter what the user does, 
> it will work, and work as fast as it can.
> 
> I would like to keep this property, if possible at all, the question is how.

Agreed. The only case I can see that right now is more efficient than
with the changed interface is, if the user calls the MaxType
get/setValue methods from the GeoVectorProperty level (i.e. not
TypedGeoVectorProperty), because it avoids the second conversion done in
 the template member functions.
We can get rid of that by making some changes to the GeoConvert structs
(to some degree these are needed anyway, see below), using partial
template specialization (or do we need to support some crummy compiler
that still can not handle that ? [1]). I've attached a draft  of what I
mean.

>> Actually, now that I'm writing this, set/getGenericValue probably
>> could/should be protected.
>>   
> Probably true, as they're not really necessary.
>> This unfortunately gives the more efficient interface a longer name.
>>   
> Hm, true. :(
> 
> I was hoping to get to the point mentioned above by introducing a dummy 
> type that holds a Vec4d for conversion, and have an interface based on 
> that. That would avoid the dual function problem for Vec4d, at the cost 
> of an additional type. But given that there are temporary objects in the 
> loop anyway, that might not be an issue.

Ugh, let's just think real hard and hopefully come up with something
that gets us there without this, please ?

BTW, have you tried to use the ...fx types  with GeoConvert ? Unless I
miss something the implementation special cases these by using template
member partial specialization, which unfortunately is not allowed, only
class templates can be partially specialized (I've just begun reading
Modern C++ by Alexandrescu, and he mentions it in one of the early
chapters ;) ).

        Carsten

[1] For compilers that can not handle partial specialization we could
disable that optimization.
// this is only a draft - it never faced a compiler...

// hide away the implementation in a namespace.
// it can NOT be unnamed because that can lead to violations of the 
// "One Definition Rule" -- not my idea, but read it on the boost mailing list
// and those guys usually know what they talk about...
namespace detail
{

// primary template -- just what we have now
template <class ExternalTypeT, class StoredTypeT>
struct GeoConvertImpl
{
    typedef ExternalTypeT ExternalType;
    typedef StoredTypeT   StoredType;

    inline static void convertIn(StoredType& dest, const ExternalType& src,
                                 Real64 scale = 1, Real64 offset = 0)
    {
        if(ExternalType::_uiSize >= StoredType::_uiSize)
        {
            UInt32 i;
            for(i = 0; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename StoredType::ValueType>(src[i]);
        }
        else
        {
            UInt32 i;
            for(i = 0; i < ExternalType::_uiSize; ++i)
                dest[i] = static_cast<typename StoredType::ValueType>(src[i]);
            for(; i < StoredType::_uiSize; ++i)
                dest[i] = StoredType::Null[i];
        }
    }

    inline static void convertOut(ExternalType& dest, const StoredType& src,
                                  Real64 scale = 1, Real64 offset = 0)
    {
        if(StoredType::_uiSize >= ExternalType::_uiSize)
        {
            UInt32 i;
            for(i = 0; i < ExternalType::_uiSize; ++i)
                dest[i] = static_cast<typename ExternalType::ValueType>(src[i]);
        }
        else
        {
            UInt32 i;
            for(i = 0; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename ExternalType::ValueType>(src[i]);
            for(; i < ExternalType::_uiSize; ++i)
                dest[i] = ExternalType::Null[i];
        }
    }
};

// partial specialization for "conversion" between identical types
template <class StoredTypeT>
struct GeoConvertImpl<StoredTypeT, StoredTypeT>
{
    typedef StoredTypeT ExternalType;
    typedef StoredTypeT StoredType;

    inline static void convertIn(StoredType& dest, const ExternalType& src,
                                 Real64 scale = 1, Real64 offset = 0)
    {
        dest = src;
    }
    
    inline static void convertOut(ExternalType& dest, const StoredType& src,
                                  Real64 scale = 1, Real64 offset = 0)
    {
        dest = src;
    }
};

// specializations for ...fx types go here.

// primary template -- just what we have now
template <class ExternalTypeT, class StoredTypeT>
struct GeoConvertNormalizeImpl
{
    typedef ExternalTypeT ExternalType;
    typedef StoredTypeT   StoredType;
    
    static void convertIn(StoredType& dest, const ExternalType& src,
                          Real64 scale = 1, Real64 offset = 0)
    {
        if(ExternalType::_uiSize >= StoredType::_uiSize)
        {
            UInt32 i;
            for(i = 0; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename StoredType::ValueType>(
                            src[i] * scale + offset);
        }
        else
        {
            UInt32 i;
            for(i = 0; i < ExternalType::_uiSize; ++i)
                dest[i] = static_cast<typename StoredType::ValueType>(
                            src[i] * scale + offset);
            for(; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename StoredType::ValueType>(
                            StoredType::Null[i] * scale + offset);
        }
    }
    
    static void convertOut(ExternalType& dest, const StoredType& src,
                                 Real64 scale = 1, Real64 offset = 0)
    {
        if(StoredType::_uiSize >= ExternalType::_uiSize)
        {
            UInt32 i;
            for(i = 0; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename ExternalType::ValueType>(
                            (src[i] - offset) / scale);
        }
        else
        {
            UInt32 i;
            for(i = 0; i < StoredType::_uiSize; ++i)
                dest[i] = static_cast<typename ExternalType::ValueType>(
                            (src[i] - offset) / scale);
            for(; i < ExternalType::_uiSize; ++i)
                dest[i] = static_cast<typename ExternalType::ValueType>(
                            (StoredType::Null[i] - offset) / scale);
        }
    }
};

// partial specialization for "conversion" between identical types
template <class StoredTypeT>
struct GeoConvertNormalizeImpl
{
    typedef StoredTypeT ExternalType;
    typedef StoredTypeT StoredType;
    
    static void convertIn(StoredType& dest, const ExternalType& src,
                          Real64 scale = 1, Real64 offset = 0)
    {
        // StoredType::One is not available... -- alternatives ??
        dest = (scale * src) + (offset * StoredType::One);
    }
    
    static void convertOut(ExternalType& dest, const StoredType& src,
                                 Real64 scale = 1, Real64 offset = 0)
    {
        // StoredType::One is not available... -- alternatives ??
        dest = (src - offset * StoredType::One) / scale;
    }
};

// specializations for ...fx types.

} // namespace detail

// now a nice interface that uses argument deduction to avoid typing all those
// types

struct GeoConvert
{
    template <class ExternalTypeT, class StoredTypeT>
    static void convertIn(StoredTypeT& dest, const ExternalType& src,
                          Real64 scale = 1,  Real64 offset = 0)
    {
        detail::GeoConvertImpl<ExternalTypeT, StoredTypeT>::convertIn(dest, src, scale, offset);
    }
    
    template <class ExternalTypeT, class StoredTypeT>
    static void convertOut(ExternalTypeT& dest, const StoredTypeT& src,
                           Real64 scale = 1, Real64 offset = 0)
    {
        detail::GeoConvertImpl<ExternalTypeT, StoredTypeT>::convertOut(dest, src, scale, offset);
    }
};

struct GeoConvertNormalize
{
    template <class ExternalTypeT, class StoredTypeT>
    static void convertIn(StoredTypeT& dest, const ExternalType& src,
                          Real64 scale = 1,  Real64 offset = 0)
    {
        detail::GeoConvertNormalizeImpl<ExternalTypeT, StoredTypeT>::convertIn(dest, src, scale, offset);
    }
    
    template <class ExternalTypeT, class StoredTypeT>
    static void convertOut(ExternalTypeT& dest, const StoredTypeT& src,
                           Real64 scale = 1, Real64 offset = 0)
    {
        detail::GeoConvertNormalizeImpl<ExternalTypeT, StoredTypeT>::convertOut(dest, src, scale, offset);
    }
};
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core

Reply via email to