change based on code review

This commit is contained in:
Li-Ta Lo 2021-12-17 09:49:04 -07:00
parent a3c4460077
commit 3720006d0b
6 changed files with 92 additions and 57 deletions

@ -109,6 +109,14 @@ public:
std::forward<Args>(args)...);
}
/// \brief Call a functor using the underlying array type with a float cast fallback.
///
/// `CastAndCallWithFloatFallback` attempts to cast the held array to a specific value type,
/// and then calls the given functor with the cast array. If the underlying array
/// does not match any of the requested array types, the array is copied to a new
/// `ArrayHandleBasic` with `FloatDefault` components in its value and attempts to
/// cast to those types.
///
template <typename Functor, typename... Args>
VTKM_CONT void CastAndCallWithFloatFallback(Functor&& functor, Args&&... args) const
{

@ -826,7 +826,19 @@ public:
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
VTKM_CONT void CastAndCallForTypes(Functor&& functor, Args&&... args) const;
/// TODO: Doxygen
/// \brief Call a functor using the underlying array type with a float cast fallback.
///
/// `CastAndCallForTypesWithFloatFallback` attempts to cast the held array to a specific
/// value type, and then calls the given functor with the cast array. You must specify
/// the `TypeList` and `StorageList` as template arguments.
///
/// After the functor argument you may add any number of arguments that will be
/// passed to the functor after the converted `ArrayHandle`.
///
/// If the underlying array does not match any of the requested array types, the
/// array is copied to a new `ArrayHandleBasic` with `FloatDefault` components
/// in its value and attempts to cast to those types.
///
template <typename TypeList, typename StorageList, typename Functor, typename... Args>
VTKM_CONT void CastAndCallForTypesWithFloatFallback(Functor&& functor, Args&&... args) const;
@ -1079,17 +1091,32 @@ template <typename TypeList, typename StorageTagList, typename Functor, typename
VTKM_CONT void UnknownArrayHandle::CastAndCallForTypesWithFloatFallback(Functor&& functor,
Args&&... args) const
{
try
{
this->template CastAndCallForTypes<TypeList, StorageTagList>(std::forward<Functor>(functor),
std::forward<Args>(args)...);
}
catch (vtkm::cont::ErrorBadType&)
using crossProduct = internal::ListAllArrayTypes<TypeList, StorageTagList>;
bool called = false;
vtkm::ListForEach(detail::UnknownArrayHandleTry{},
crossProduct{},
std::forward<Functor>(functor),
called,
*this,
std::forward<Args>(args)...);
if (!called)
{
// Copy to a float array and try again
vtkm::cont::UnknownArrayHandle floatArray = this->NewInstanceFloatBasic();
floatArray.DeepCopyFrom(*this);
floatArray.template CastAndCallForTypes<TypeList, StorageTagList>(
std::forward<Functor>(functor), std::forward<Args>(args)...);
vtkm::ListForEach(detail::UnknownArrayHandleTry{},
crossProduct{},
std::forward<Functor>(functor),
called,
floatArray,
std::forward<Args>(args)...);
}
if (!called)
{
// throw an exception
VTKM_LOG_CAST_FAIL(*this, TypeList);
internal::ThrowCastAndCallException(*this, typeid(TypeList));
}
}

@ -146,7 +146,7 @@ namespace filter
/// auto outputField = ... // Business logic for mapping input field to output field
/// output.AddField(outputField);
/// };
/// MapFieldsOntoOutput(input, output, mapper);
/// this->MapFieldsOntoOutput(input, output, mapper);
///
/// return output;
/// }
@ -193,7 +193,7 @@ namespace filter
/// auto outputField = ... // Use `states` for mapping input field to output field
/// output.AddField(outputField);
/// };
/// MapFieldsOntoOutput(input, output, mapper);
/// this->MapFieldsOntoOutput(input, output, mapper);
///
/// return output;
/// }
@ -331,7 +331,7 @@ protected:
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)
{
MapFieldsOntoOutput(input, output, defaultMapper);
this->MapFieldsOntoOutput(input, output, defaultMapper);
}
private:

@ -73,7 +73,7 @@ public:
void SetUseCoordinateSystemAsField(vtkm::IdComponent index, bool val)
{
auto index_st = static_cast<std::size_t>(index);
ResizeIfNeeded(index_st);
this->ResizeIfNeeded(index_st);
this->UseCoordinateSystemAsField[index] = val;
}
@ -90,7 +90,7 @@ protected:
VTKM_CONT
const vtkm::cont::Field& GetFieldFromDataSet(const vtkm::cont::DataSet& input) const
{
return GetFieldFromDataSet(0, input);
return this->GetFieldFromDataSet(0, input);
}
VTKM_CONT
@ -111,16 +111,16 @@ protected:
private:
void ResizeIfNeeded(size_t index_st)
{
if (ActiveFieldNames.size() <= index_st)
if (this->ActiveFieldNames.size() <= index_st)
{
auto oldSize = ActiveFieldNames.size();
ActiveFieldNames.resize(index_st + 1);
ActiveFieldAssociation.resize(index_st + 1);
UseCoordinateSystemAsField.resize(index_st + 1);
auto oldSize = this->ActiveFieldNames.size();
this->ActiveFieldNames.resize(index_st + 1);
this->ActiveFieldAssociation.resize(index_st + 1);
this->UseCoordinateSystemAsField.resize(index_st + 1);
for (std::size_t i = oldSize; i <= index_st; ++i)
{
ActiveFieldAssociation[i] = cont::Field::Association::ANY;
UseCoordinateSystemAsField[i] = false;
this->ActiveFieldAssociation[i] = cont::Field::Association::ANY;
this->UseCoordinateSystemAsField[i] = false;
}
}
}

@ -56,7 +56,7 @@ vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input)
output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells()));
}
MapFieldsOntoOutput(input, output);
this->MapFieldsOntoOutput(input, output);
return output;
}

@ -49,54 +49,54 @@ VTKM_CONT DotProduct::DotProduct()
this->SetOutputFieldName("dotproduct");
}
struct ResolveTypeFunctor
{
template <typename T, typename Storage>
void operator()(const vtkm::cont::ArrayHandle<T, Storage>& primary,
const DotProduct& filter,
const vtkm::cont::DataSet& input,
vtkm::cont::UnknownArrayHandle& output) const
{
const auto& secondaryField = [&]() -> const vtkm::cont::Field& {
if (filter.GetUseCoordinateSystemAsSecondaryField())
{
return input.GetCoordinateSystem(filter.GetSecondaryCoordinateSystemIndex());
}
else
{
return input.GetField(filter.GetSecondaryFieldName(),
filter.GetSecondaryFieldAssociation());
}
}();
vtkm::cont::UnknownArrayHandle secondary = vtkm::cont::ArrayHandle<T>{};
secondary.CopyShallowIfPossible(secondaryField.GetData());
vtkm::cont::ArrayHandle<typename vtkm::VecTraits<T>::ComponentType> result;
vtkm::cont::Invoker invoker;
invoker(::worklet::DotProduct{},
primary,
secondary.template AsArrayHandle<vtkm::cont::ArrayHandle<T>>(),
result);
output = result;
}
};
VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
const auto& primaryArray = this->GetFieldFromDataSet(inDataSet).GetData();
vtkm::cont::UnknownArrayHandle outArray;
// We are using a C++14 auto lambda here. The advantage over a Functor is obvious, we don't
// need to explicitly pass filter, input/output DataSets etc. thus reduce the impact to
// the legacy code. The lambda can also access the private part of the filter thus reducing
// filter's public interface profile. CastAndCall tries to cast primaryArray of unknown value
// type and storage to a concrete ArrayHandle<T, S> with T from the `TypeList` and S from
// `StorageList`. It then passes the concrete array to the lambda as the first argument.
// We can later recover the concrete ValueType, T, from the concrete array.
auto ResolveType = [&, this](const auto& concrete) {
// use std::decay to remove const ref from the decltype of concrete.
using T = typename std::decay_t<decltype(concrete)>::ValueType;
const auto& secondaryField = [&]() -> const vtkm::cont::Field& {
if (this->GetUseCoordinateSystemAsSecondaryField())
{
return inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex());
}
else
{
return inDataSet.GetField(this->GetSecondaryFieldName(),
this->GetSecondaryFieldAssociation());
}
}();
vtkm::cont::UnknownArrayHandle secondary = vtkm::cont::ArrayHandle<T>{};
secondary.CopyShallowIfPossible(secondaryField.GetData());
vtkm::cont::ArrayHandle<typename vtkm::VecTraits<T>::ComponentType> result;
this->Invoke(::worklet::DotProduct{},
concrete,
secondary.template AsArrayHandle<vtkm::cont::ArrayHandle<T>>(),
result);
outArray = result;
};
primaryArray
.CastAndCallForTypesWithFloatFallback<VTKM_DEFAULT_TYPE_LIST, VTKM_DEFAULT_STORAGE_LIST>(
ResolveTypeFunctor{}, *this, inDataSet, outArray);
ResolveType);
vtkm::cont::DataSet outDataSet = inDataSet; // copy
outDataSet.AddField({ this->GetOutputFieldName(),
this->GetFieldFromDataSet(inDataSet).GetAssociation(),
outArray });
MapFieldsOntoOutput(inDataSet, outDataSet);
this->MapFieldsOntoOutput(inDataSet, outDataSet);
return outDataSet;
}