| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 09:50:34 +02:00
										 |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup fn | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file contains several utilities to create multi-functions with less redundant code. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <functional>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "FN_multi_function.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:25:20 +02:00
										 |  |  | namespace blender::fn { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function with the following parameters: | 
					
						
							|  |  |  |  * 1. single input (SI) of type In1 | 
					
						
							|  |  |  |  * 2. single output (SO) of type Out1 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This example creates a function that adds 10 to the incoming values: | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |  *  CustomMF_SI_SO<int, int> fn("add 10", [](int value) { return value + 10; }); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  | template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunction { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   using FunctionT = std::function<void(IndexMask, const VArray<In1> &, MutableSpan<Out1>)>; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   FunctionT function_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   CustomMF_SI_SO(StringRef name, FunctionT function) : function_(std::move(function)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{name}; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     signature.single_input<In1>("In1"); | 
					
						
							|  |  |  |     signature.single_output<Out1>("Out1"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   CustomMF_SI_SO(StringRef name, ElementFuncT element_fn) | 
					
						
							|  |  |  |       : CustomMF_SI_SO(name, CustomMF_SI_SO::create_function(element_fn)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return [=](IndexMask mask, const VArray<In1> &in1, MutableSpan<Out1> out1) { | 
					
						
							| 
									
										
										
										
											2021-03-22 17:06:02 +01:00
										 |  |  |       /* Devirtualization results in a 2-3x speedup for some simple functions. */ | 
					
						
							|  |  |  |       devirtualize_varray(in1, [&](const auto &in1) { | 
					
						
							|  |  |  |         mask.foreach_index( | 
					
						
							|  |  |  |             [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i])); }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     const VArray<In1> &in1 = params.readonly_single_input<In1>(0); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(1); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     function_(mask, in1, out1); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function with the following parameters: | 
					
						
							|  |  |  |  * 1. single input (SI) of type In1 | 
					
						
							|  |  |  |  * 2. single input (SI) of type In2 | 
					
						
							|  |  |  |  * 3. single output (SO) of type Out1 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename In1, typename In2, typename Out1> | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  | class CustomMF_SI_SI_SO : public MultiFunction { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   using FunctionT = | 
					
						
							|  |  |  |       std::function<void(IndexMask, const VArray<In1> &, const VArray<In2> &, MutableSpan<Out1>)>; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   FunctionT function_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   CustomMF_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{name}; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     signature.single_input<In1>("In1"); | 
					
						
							|  |  |  |     signature.single_input<In2>("In2"); | 
					
						
							|  |  |  |     signature.single_output<Out1>("Out1"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   CustomMF_SI_SI_SO(StringRef name, ElementFuncT element_fn) | 
					
						
							|  |  |  |       : CustomMF_SI_SI_SO(name, CustomMF_SI_SI_SO::create_function(element_fn)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     return [=](IndexMask mask, | 
					
						
							|  |  |  |                const VArray<In1> &in1, | 
					
						
							|  |  |  |                const VArray<In2> &in2, | 
					
						
							|  |  |  |                MutableSpan<Out1> out1) { | 
					
						
							| 
									
										
										
										
											2021-03-22 17:06:02 +01:00
										 |  |  |       /* Devirtualization results in a 2-3x speedup for some simple functions. */ | 
					
						
							|  |  |  |       devirtualize_varray2(in1, in2, [&](const auto &in1, const auto &in2) { | 
					
						
							|  |  |  |         mask.foreach_index( | 
					
						
							|  |  |  |             [&](int i) { new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i])); }); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     const VArray<In1> &in1 = params.readonly_single_input<In1>(0); | 
					
						
							|  |  |  |     const VArray<In2> &in2 = params.readonly_single_input<In2>(1); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(2); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     function_(mask, in1, in2, out1); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function with the following parameters: | 
					
						
							|  |  |  |  * 1. single input (SI) of type In1 | 
					
						
							|  |  |  |  * 2. single input (SI) of type In2 | 
					
						
							|  |  |  |  * 3. single input (SI) of type In3 | 
					
						
							|  |  |  |  * 4. single output (SO) of type Out1 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename In1, typename In2, typename In3, typename Out1> | 
					
						
							|  |  |  | class CustomMF_SI_SI_SI_SO : public MultiFunction { | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   using FunctionT = std::function<void(IndexMask, | 
					
						
							|  |  |  |                                        const VArray<In1> &, | 
					
						
							|  |  |  |                                        const VArray<In2> &, | 
					
						
							|  |  |  |                                        const VArray<In3> &, | 
					
						
							|  |  |  |                                        MutableSpan<Out1>)>; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   FunctionT function_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   CustomMF_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function)) | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{name}; | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |     signature.single_input<In1>("In1"); | 
					
						
							|  |  |  |     signature.single_input<In2>("In2"); | 
					
						
							|  |  |  |     signature.single_input<In3>("In3"); | 
					
						
							|  |  |  |     signature.single_output<Out1>("Out1"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> | 
					
						
							|  |  |  |   CustomMF_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn) | 
					
						
							|  |  |  |       : CustomMF_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SO::create_function(element_fn)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return [=](IndexMask mask, | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |                const VArray<In1> &in1, | 
					
						
							|  |  |  |                const VArray<In2> &in2, | 
					
						
							|  |  |  |                const VArray<In3> &in3, | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |                MutableSpan<Out1> out1) { | 
					
						
							| 
									
										
										
										
											2020-08-07 18:24:59 +02:00
										 |  |  |       mask.foreach_index([&](int i) { | 
					
						
							|  |  |  |         new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i])); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     const VArray<In1> &in1 = params.readonly_single_input<In1>(0); | 
					
						
							|  |  |  |     const VArray<In2> &in2 = params.readonly_single_input<In2>(1); | 
					
						
							|  |  |  |     const VArray<In3> &in3 = params.readonly_single_input<In3>(2); | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |     MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(3); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     function_(mask, in1, in2, in3, out1); | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function with the following parameters: | 
					
						
							|  |  |  |  * 1. single input (SI) of type In1 | 
					
						
							|  |  |  |  * 2. single input (SI) of type In2 | 
					
						
							|  |  |  |  * 3. single input (SI) of type In3 | 
					
						
							|  |  |  |  * 4. single input (SI) of type In4 | 
					
						
							|  |  |  |  * 5. single output (SO) of type Out1 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename In1, typename In2, typename In3, typename In4, typename Out1> | 
					
						
							|  |  |  | class CustomMF_SI_SI_SI_SI_SO : public MultiFunction { | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |   using FunctionT = std::function<void(IndexMask, | 
					
						
							|  |  |  |                                        const VArray<In1> &, | 
					
						
							|  |  |  |                                        const VArray<In2> &, | 
					
						
							|  |  |  |                                        const VArray<In3> &, | 
					
						
							|  |  |  |                                        const VArray<In4> &, | 
					
						
							|  |  |  |                                        MutableSpan<Out1>)>; | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  |   FunctionT function_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   CustomMF_SI_SI_SI_SI_SO(StringRef name, FunctionT function) : function_(std::move(function)) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{name}; | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  |     signature.single_input<In1>("In1"); | 
					
						
							|  |  |  |     signature.single_input<In2>("In2"); | 
					
						
							|  |  |  |     signature.single_input<In3>("In3"); | 
					
						
							|  |  |  |     signature.single_input<In4>("In4"); | 
					
						
							|  |  |  |     signature.single_output<Out1>("Out1"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> | 
					
						
							|  |  |  |   CustomMF_SI_SI_SI_SI_SO(StringRef name, ElementFuncT element_fn) | 
					
						
							|  |  |  |       : CustomMF_SI_SI_SI_SI_SO(name, CustomMF_SI_SI_SI_SI_SO::create_function(element_fn)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return [=](IndexMask mask, | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |                const VArray<In1> &in1, | 
					
						
							|  |  |  |                const VArray<In2> &in2, | 
					
						
							|  |  |  |                const VArray<In3> &in3, | 
					
						
							|  |  |  |                const VArray<In4> &in4, | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  |                MutableSpan<Out1> out1) { | 
					
						
							|  |  |  |       mask.foreach_index([&](int i) { | 
					
						
							|  |  |  |         new (static_cast<void *>(&out1[i])) Out1(element_fn(in1[i], in2[i], in3[i], in4[i])); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     const VArray<In1> &in1 = params.readonly_single_input<In1>(0); | 
					
						
							|  |  |  |     const VArray<In2> &in2 = params.readonly_single_input<In2>(1); | 
					
						
							|  |  |  |     const VArray<In3> &in3 = params.readonly_single_input<In3>(2); | 
					
						
							|  |  |  |     const VArray<In4> &in4 = params.readonly_single_input<In4>(3); | 
					
						
							| 
									
										
										
										
											2021-03-08 11:37:37 +01:00
										 |  |  |     MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(4); | 
					
						
							|  |  |  |     function_(mask, in1, in2, in3, in4, out1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function with the following parameters: | 
					
						
							|  |  |  |  * 1. single mutable (SM) of type Mut1 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  | template<typename Mut1> class CustomMF_SM : public MultiFunction { | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |  private: | 
					
						
							|  |  |  |   using FunctionT = std::function<void(IndexMask, MutableSpan<Mut1>)>; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   FunctionT function_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |   CustomMF_SM(StringRef name, FunctionT function) : function_(std::move(function)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{name}; | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     signature.single_mutable<Mut1>("Mut1"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> | 
					
						
							| 
									
										
										
										
											2020-06-30 17:59:33 +02:00
										 |  |  |   CustomMF_SM(StringRef name, ElementFuncT element_fn) | 
					
						
							|  |  |  |       : CustomMF_SM(name, CustomMF_SM::create_function(element_fn)) | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return [=](IndexMask mask, MutableSpan<Mut1> mut1) { | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |       mask.foreach_index([&](int i) { element_fn(mut1[i]); }); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     MutableSpan<Mut1> mut1 = params.single_mutable<Mut1>(0); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:42 +02:00
										 |  |  |     function_(mask, mut1); | 
					
						
							| 
									
										
										
										
											2020-06-22 15:50:08 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function that converts between two types. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename From, typename To> class CustomMF_Convert : public MultiFunction { | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   CustomMF_Convert() | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   { | 
					
						
							|  |  |  |     static MFSignature signature = create_signature(); | 
					
						
							|  |  |  |     this->set_signature(&signature); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static MFSignature create_signature() | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     std::string name = CPPType::get<From>().name() + " to " + CPPType::get<To>().name(); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{std::move(name)}; | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  |     signature.single_input<From>("Input"); | 
					
						
							|  |  |  |     signature.single_output<To>("Output"); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     return signature.build(); | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-21 19:31:24 +01:00
										 |  |  |     const VArray<From> &inputs = params.readonly_single_input<From>(0); | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  |     MutableSpan<To> outputs = params.uninitialized_single_output<To>(1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |     for (int64_t i : mask) { | 
					
						
							| 
									
										
										
										
											2020-08-07 18:24:59 +02:00
										 |  |  |       new (static_cast<void *>(&outputs[i])) To(inputs[i]); | 
					
						
							| 
									
										
										
										
											2020-07-11 18:02:06 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 19:34:35 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * 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_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-07-07 19:34:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   template<typename T> friend class CustomMF_Constant; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-07 19:34:35 +02:00
										 |  |  |  public: | 
					
						
							|  |  |  |   CustomMF_GenericConstant(const CPPType &type, const void *value); | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext context) const override; | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   uint64_t hash() const override; | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   bool equals(const MultiFunction &other) const override; | 
					
						
							| 
									
										
										
										
											2020-07-07 19:34:35 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * 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_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-07-07 19:34:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   CustomMF_GenericConstantArray(GSpan array); | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext context) const override; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Generates a multi-function that outputs a constant value. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | template<typename T> class CustomMF_Constant : public MultiFunction { | 
					
						
							|  |  |  |  private: | 
					
						
							|  |  |  |   T value_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   template<typename U> CustomMF_Constant(U &&value) : value_(std::forward<U>(value)) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     MFSignatureBuilder signature{"Constant"}; | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |     std::stringstream ss; | 
					
						
							|  |  |  |     ss << value_; | 
					
						
							|  |  |  |     signature.single_output<T>(ss.str()); | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |     signature_ = signature.build(); | 
					
						
							|  |  |  |     this->set_signature(&signature_); | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     MutableSpan<T> output = params.uninitialized_single_output<T>(0); | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |     mask.foreach_index([&](int i) { new (&output[i]) T(value_); }); | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   uint64_t hash() const override | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-03-25 16:01:28 +01:00
										 |  |  |     return get_default_hash(value_); | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool equals(const MultiFunction &other) const override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const CustomMF_Constant *other1 = dynamic_cast<const CustomMF_Constant *>(&other); | 
					
						
							|  |  |  |     if (other1 != nullptr) { | 
					
						
							|  |  |  |       return value_ == other1->value_; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const CustomMF_GenericConstant *other2 = dynamic_cast<const CustomMF_GenericConstant *>( | 
					
						
							|  |  |  |         &other); | 
					
						
							|  |  |  |     if (other2 != nullptr) { | 
					
						
							| 
									
										
										
										
											2020-07-10 12:56:57 +02:00
										 |  |  |       const CPPType &type = CPPType::get<T>(); | 
					
						
							|  |  |  |       if (type == other2->type_) { | 
					
						
							| 
									
										
										
										
											2020-08-07 18:24:59 +02:00
										 |  |  |         return type.is_equal(static_cast<const void *>(&value_), other2->value_); | 
					
						
							| 
									
										
										
										
											2020-07-08 15:04:28 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 13:38:23 +02:00
										 |  |  | class CustomMF_DefaultOutput : public MultiFunction { | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2020-07-20 12:16:20 +02:00
										 |  |  |   int output_amount_; | 
					
						
							| 
									
										
										
										
											2021-03-22 11:57:24 +01:00
										 |  |  |   MFSignature signature_; | 
					
						
							| 
									
										
										
										
											2020-07-16 13:38:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							|  |  |  |   CustomMF_DefaultOutput(StringRef name, | 
					
						
							|  |  |  |                          Span<MFDataType> input_types, | 
					
						
							|  |  |  |                          Span<MFDataType> output_types); | 
					
						
							|  |  |  |   void call(IndexMask mask, MFParams params, MFContext context) const override; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:25:20 +02:00
										 |  |  | }  // namespace blender::fn
 |