Functions: add generic functions that output constants

This commit is contained in:
Jacques Lucke 2020-07-07 19:34:35 +02:00
parent f4633cf46c
commit 22158162ef
4 changed files with 148 additions and 0 deletions

View File

@ -30,6 +30,7 @@ set(SRC
intern/attributes_ref.cc
intern/cpp_types.cc
intern/multi_function.cc
intern/multi_function_builder.cc
intern/multi_function_network.cc
intern/multi_function_network_evaluation.cc

View File

@ -225,6 +225,33 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
}
};
/**
* A multi-function that outputs the same value every time. The value is not owned by an instance
* of this function. The caller is responsible for destructing and freeing the value.
*/
class CustomMF_GenericConstant : public MultiFunction {
private:
const CPPType &type_;
const void *value_;
public:
CustomMF_GenericConstant(const CPPType &type, const void *value);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
/**
* A multi-function that outputs the same array every time. The array is not owned by in instance
* of this function. The caller is responsible for destructing and freeing the values.
*/
class CustomMF_GenericConstantArray : public MultiFunction {
private:
GSpan array_;
public:
CustomMF_GenericConstantArray(GSpan array);
void call(IndexMask mask, MFParams params, MFContext context) const override;
};
} // namespace blender::fn
#endif /* __FN_MULTI_FUNCTION_BUILDER_HH__ */

View File

@ -0,0 +1,71 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "FN_multi_function_builder.hh"
namespace blender::fn {
CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type, const void *value)
: type_(type), value_(value)
{
MFSignatureBuilder signature = this->get_builder("Constant " + type.name());
std::stringstream ss;
type.debug_print(value, ss);
signature.single_output(ss.str(), type);
}
void CustomMF_GenericConstant::call(IndexMask mask,
MFParams params,
MFContext UNUSED(context)) const
{
GMutableSpan output = params.uninitialized_single_output(0);
type_.fill_uninitialized_indices(value_, output.buffer(), mask);
}
static std::string gspan_to_string(GSpan array)
{
std::stringstream ss;
ss << "[";
uint max_amount = 5;
for (uint i : IndexRange(std::min(max_amount, array.size()))) {
array.type().debug_print(array[i], ss);
ss << ", ";
}
if (max_amount < array.size()) {
ss << "...";
}
ss << "]";
return ss.str();
}
CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array)
{
const CPPType &type = array.type();
MFSignatureBuilder signature = this->get_builder("Constant " + type.name() + " Vector");
signature.vector_output(gspan_to_string(array), type);
}
void CustomMF_GenericConstantArray::call(IndexMask mask,
MFParams params,
MFContext UNUSED(context)) const
{
GVectorArray &vectors = params.vector_output(0);
for (uint i : mask) {
vectors.extend(i, array_);
}
}
} // namespace blender::fn

View File

@ -329,4 +329,53 @@ TEST(multi_function, CustomMF_Constant)
EXPECT_EQ(outputs[3], 42);
}
TEST(multi_function, CustomMF_GenericConstant)
{
int value = 42;
CustomMF_GenericConstant fn{CPPType_int32, (const void *)&value};
EXPECT_EQ(fn.param_name(0), "42");
Array<int> outputs(4, 0);
MFParamsBuilder params(fn, outputs.size());
params.add_uninitialized_single_output(outputs.as_mutable_span());
MFContextBuilder context;
fn.call({0, 1, 2}, params, context);
EXPECT_EQ(outputs[0], 42);
EXPECT_EQ(outputs[1], 42);
EXPECT_EQ(outputs[2], 42);
EXPECT_EQ(outputs[3], 0);
}
TEST(multi_function, CustomMF_GenericConstantArray)
{
std::array<int, 4> values = {3, 4, 5, 6};
CustomMF_GenericConstantArray fn{GSpan(Span(values))};
EXPECT_EQ(fn.param_name(0), "[3, 4, 5, 6, ]");
GVectorArray g_vector_array{CPPType_int32, 4};
GVectorArrayRef<int> vector_array = g_vector_array;
MFParamsBuilder params(fn, g_vector_array.size());
params.add_vector_output(g_vector_array);
MFContextBuilder context;
fn.call({1, 2, 3}, params, context);
EXPECT_EQ(vector_array[0].size(), 0);
EXPECT_EQ(vector_array[1].size(), 4);
EXPECT_EQ(vector_array[2].size(), 4);
EXPECT_EQ(vector_array[3].size(), 4);
for (uint i = 1; i < 4; i++) {
EXPECT_EQ(vector_array[i][0], 3);
EXPECT_EQ(vector_array[i][1], 4);
EXPECT_EQ(vector_array[i][2], 5);
EXPECT_EQ(vector_array[i][3], 6);
}
}
} // namespace blender::fn