/* enoki/array_masked.h -- Helper classes for masked assignments and in-place operators Enoki is a C++ template library that enables transparent vectorization of numerical kernels using ENOKI instruction sets available on current processor architectures. Copyright (c) 2019 Wenzel Jakob All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #pragma once NAMESPACE_BEGIN(enoki) // ----------------------------------------------------------------------- //! @{ \name Masked array helper classes // ----------------------------------------------------------------------- NAMESPACE_BEGIN(detail) template struct MaskedValue { MaskedValue(T &d, bool m) : d(d), m(m) { } template ENOKI_INLINE void operator =(const T2 &value) { if (m) d = value; } template ENOKI_INLINE void operator+=(const T2 &value) { if (m) d += value; } template ENOKI_INLINE void operator-=(const T2 &value) { if (m) d -= value; } template ENOKI_INLINE void operator*=(const T2 &value) { if (m) d *= value; } template ENOKI_INLINE void operator/=(const T2 &value) { if (m) d /= value; } template ENOKI_INLINE void operator|=(const T2 &value) { if (m) d |= value; } template ENOKI_INLINE void operator&=(const T2 &value) { if (m) d &= value; } template ENOKI_INLINE void operator^=(const T2 &value) { if (m) d ^= value; } T &d; bool m; }; template struct MaskedArray : ArrayBase, MaskedArray> { using Mask = mask_t; using Scalar = MaskedValue>; using MaskType = MaskedArray; using Value = std::conditional_t>, MaskedValue>, MaskedArray>>; using UnderlyingValue = value_t; static constexpr size_t Size = array_size_v; static constexpr bool IsMaskedArray = true; MaskedArray(T &d, const Mask &m) : d(d), m(m) { } template ENOKI_INLINE void operator =(const T2 &value) { d.massign_(value, m); } template ENOKI_INLINE void operator+=(const T2 &value) { d.madd_(value, m); } template ENOKI_INLINE void operator-=(const T2 &value) { d.msub_(value, m); } template ENOKI_INLINE void operator*=(const T2 &value) { d.mmul_(value, m); } template ENOKI_INLINE void operator/=(const T2 &value) { d.mdiv_(value, m); } template ENOKI_INLINE void operator|=(const T2 &value) { d.mor_(value, m); } template ENOKI_INLINE void operator&=(const T2 &value) { d.mand_(value, m); } template ENOKI_INLINE void operator^=(const T2 &value) { d.mxor_(value, m); } /// Type alias for a similar-shaped array over a different type template using ReplaceValue = MaskedArray>; T &d; Mask m; }; NAMESPACE_END(detail) template struct Array, Size_> : detail::MaskedArray> { using Base = detail::MaskedArray>; using Base::Base; using Base::operator=; Array(const Base &b) : Base(b) { } }; template ENOKI_INLINE auto masked(T &value, const Mask &mask) { if constexpr (std::is_same_v) return detail::MaskedValue{ value, mask }; else return struct_support_t::masked(value, mask); } //! @} // ----------------------------------------------------------------------- NAMESPACE_END(enoki)