composition.hpp memory type_traits utility vector serif/geometry/deformation/actions.hpp src/compile_time_checks/serif/geometry/deformation.cpp src/include/serif/geometry/deformation/computations.hpp serif::geometry::deformation::ComposedDeformation serif::geometry::deformation::ComposedDeformation::CurvatureWorkspace serif::geometry::deformation::ComposedDeformation::Workspace serif serif::geometry serif::geometry::deformation #pragmaonce #include<memory> #include<type_traits> #include<utility> #include<vector> #include"serif/geometry/deformation/actions.hpp" namespaceserif::geometry::deformation { template<DeformationMapSurfaceMap,DeformationMapExtensionMap> requiresstd::same_as<typenameSurfaceMap::OutputSpace,typenameExtensionMap::InputSpace> classComposedDeformation { public: usingInputSpace=typenameSurfaceMap::InputSpace; usingOutputSpace=typenameExtensionMap::OutputSpace; staticconstexprboolis_linear=is_linear_deformation<SurfaceMap>&&is_linear_deformation<ExtensionMap>; staticconstexprbooluses_linear_actions=LinearDeformationMap<SurfaceMap>&&LinearDeformationMap<ExtensionMap>; structCurvatureWorkspace { std::vector<double>surface_direction; std::vector<double>surface_dual; std::vector<double>parameter_pullback; }; structWorkspace { DeformationWorkspace<SurfaceMap>surface_workspace; DeformationWorkspace<ExtensionMap>extension_workspace; std::vector<double>surface_displacement; std::conditional_t<uses_linear_actions,EmptyDeformationWorkspace,CurvatureWorkspace>curvature; }; [[nodiscard]]std::size_tinput_size()constnoexcept { returnm_surface->input_size(); } [[nodiscard]]std::size_toutput_size()constnoexcept { returnm_extension->output_size(); } [[nodiscard]]Workspacemake_workspace()const { Workspaceworkspace{ .surface_workspace=make_deformation_workspace(*m_surface), .extension_workspace=make_deformation_workspace(*m_extension), .surface_displacement=std::vector<double>(m_surface->output_size()), .curvature={}}; ifconstexpr(!uses_linear_actions) { workspace.curvature={ .surface_direction=std::vector<double>(m_surface->output_size()), .surface_dual=std::vector<double>(m_surface->output_size()), .parameter_pullback=std::vector<double>(input_size())}; } returnworkspace; } [[nodiscard]]DeformationStatusapply(std::span<constdouble>input,std::span<double>output,Workspace&workspace)const requiresuses_linear_actions { returnbuild_displacement(input,output,workspace); } [[nodiscard]]DeformationStatusapply_transpose(std::span<constdouble>dual,std::span<double>output,Workspace&workspace)const requiresuses_linear_actions { if(constDeformationStatusstatus=detail::validate_disjoint_output(output,{dual});!status) { returnstatus; } if(constDeformationStatusstatus=m_extension->apply_transpose(dual,workspace.surface_displacement,workspace.extension_workspace);!status) { returnstatus; } returnm_surface->apply_transpose(workspace.surface_displacement,output,workspace.surface_workspace); } [[nodiscard]]DeformationStatusbuild_displacement(std::span<constdouble>parameters,std::span<double>displacement,Workspace&workspace)const { if(constautostatus=detail::validate_disjoint_output(displacement,{parameters});!status) { returnstatus; } if(constautostatus=deformation::build_displacement(*m_surface,parameters,workspace.surface_displacement,workspace.surface_workspace);!status) { returnstatus; } returndeformation::build_displacement(*m_extension,workspace.surface_displacement,displacement,workspace.extension_workspace); } [[nodiscard]]DeformationStatusapply_jacobian(std::span<constdouble>parameters,std::span<constdouble>direction,std::span<double>displacement_direction,Workspace&workspace)const requires(!uses_linear_actions) { if(constautostatus=detail::validate_disjoint_output(displacement_direction,{parameters,direction});!status) { returnstatus; } if(constautostatus=deformation::build_displacement(*m_surface,parameters,workspace.surface_displacement,workspace.surface_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_jacobian(*m_surface,parameters,direction,workspace.curvature.surface_direction,workspace.surface_workspace);!status) { returnstatus; } returndeformation::apply_jacobian(*m_extension,workspace.surface_displacement,workspace.curvature.surface_direction,displacement_direction,workspace.extension_workspace); } [[nodiscard]]DeformationStatusapply_jacobian_transpose(std::span<constdouble>parameters,std::span<constdouble>displacement_dual,std::span<double>parameter_dual,Workspace&workspace)const requires(!uses_linear_actions) { if(constautostatus=detail::validate_disjoint_output(parameter_dual,{parameters,displacement_dual});!status) { returnstatus; } if(constautostatus=deformation::build_displacement(*m_surface,parameters,workspace.surface_displacement,workspace.surface_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_jacobian_transpose(*m_extension,workspace.surface_displacement,displacement_dual,workspace.curvature.surface_dual,workspace.extension_workspace);!status) { returnstatus; } returndeformation::apply_jacobian_transpose(*m_surface,parameters,workspace.curvature.surface_dual,parameter_dual,workspace.surface_workspace); } [[nodiscard]]DeformationStatusapply_pullback_derivative(std::span<constdouble>parameters,std::span<constdouble>direction,std::span<constdouble>displacement_dual,std::span<double>parameter_dual,Workspace&workspace)const requires(!uses_linear_actions) { if(constautostatus=detail::validate_disjoint_output(parameter_dual,{parameters,direction,displacement_dual});!status) { returnstatus; } if(constautostatus=deformation::build_displacement(*m_surface,parameters,workspace.surface_displacement,workspace.surface_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_jacobian(*m_surface,parameters,direction,workspace.curvature.surface_direction,workspace.surface_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_pullback_derivative(*m_extension,workspace.surface_displacement,workspace.curvature.surface_direction,displacement_dual,workspace.curvature.surface_dual,workspace.extension_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_jacobian_transpose(*m_surface,parameters,workspace.curvature.surface_dual,parameter_dual,workspace.surface_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_jacobian_transpose(*m_extension,workspace.surface_displacement,displacement_dual,workspace.curvature.surface_dual,workspace.extension_workspace);!status) { returnstatus; } if(constautostatus=deformation::apply_pullback_derivative(*m_surface,parameters,direction,workspace.curvature.surface_dual,workspace.curvature.parameter_pullback,workspace.surface_workspace);!status) { returnstatus; } for(std::size_tparameter=0;parameter<parameter_dual.size();++parameter) { parameter_dual[parameter]+=workspace.curvature.parameter_pullback[parameter]; } returnvalidate_deformation_values(parameter_dual,input_size()); } [[nodiscard]]constSurfaceMap&surface_map()constnoexcept { return*m_surface; } private: ComposedDeformation(std::shared_ptr<constSurfaceMap>surface,std::shared_ptr<constExtensionMap>extension):m_surface(std::move(surface)),m_extension(std::move(extension)) { } template<DeformationMapFirst,DeformationMapSecond> requiresstd::same_as<typenameFirst::OutputSpace,typenameSecond::InputSpace> friendstd::expected<ComposedDeformation<First,Second>,DeformationFailure>compose_deformation(std::shared_ptr<constFirst>,std::shared_ptr<constSecond>); std::shared_ptr<constSurfaceMap>m_surface; std::shared_ptr<constExtensionMap>m_extension; }; template<DeformationMapSurfaceMap,DeformationMapExtensionMap> requiresstd::same_as<typenameSurfaceMap::OutputSpace,typenameExtensionMap::InputSpace> [[nodiscard]]std::expected<ComposedDeformation<SurfaceMap,ExtensionMap>,DeformationFailure>compose_deformation(std::shared_ptr<constSurfaceMap>surface,std::shared_ptr<constExtensionMap>extension) { if(!surface||!extension||surface->output_size()!=extension->input_size()) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::invalid_size,.message="Surfaceandvolumeextensionmustsharethesamedisplacementtracesize."}); } returnComposedDeformation<SurfaceMap, ExtensionMap>(std::move(surface),std::move(extension)); } }//namespaceserif::geometry::deformation