// Ceres Solver - A fast non-linear least squares minimizer // Copyright 2023 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Google Inc. nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // Author: jodebo_beck@gmx.de (Johannes Beck) // sergiu.deitsch@gmail.com (Sergiu Deitsch) // // Algorithms to be used together with integer_sequence, like computing the sum // or the exclusive scan (sometimes called exclusive prefix sum) at compile // time. #ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_ #define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_ #include #include "ceres/jet_fwd.h" namespace ceres::internal { // Implementation of calculating an exclusive scan (exclusive prefix sum) of an // integer sequence. Exclusive means that the i-th input element is not included // in the i-th sum. Calculating the exclusive scan for an input array I results // in the following output R: // // R[0] = 0 // R[1] = I[0]; // R[2] = I[0] + I[1]; // R[3] = I[0] + I[1] + I[2]; // ... // // In C++17 std::exclusive_scan does the same operation at runtime (but // cannot be used to calculate the prefix sum at compile time). See // https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more // detailed description. // // Example for integer_sequence (seq := integer_sequence): // T , Sum, Ns... , Rs... // ExclusiveScanImpl, seq> // ExclusiveScanImpl, seq> // ExclusiveScanImpl, seq> // ExclusiveScanImpl, seq> // ^^^^^^^^^^^^^^^^^ // resulting sequence template struct ExclusiveScanImpl; template struct ExclusiveScanImpl, std::integer_sequence> { using Type = typename ExclusiveScanImpl, std::integer_sequence>::Type; }; // End of 'recursion'. The resulting type is SeqOut. template struct ExclusiveScanImpl, SeqOut> { using Type = SeqOut; }; // Calculates the exclusive scan of the specified integer sequence. The last // element (the total) is not included in the resulting sequence so they have // same length. This means the exclusive scan of integer_sequence // will be integer_sequence. template class ExclusiveScanT { using T = typename Seq::value_type; public: using Type = typename ExclusiveScanImpl>::Type; }; // Helper to use exclusive scan without typename. template using ExclusiveScan = typename ExclusiveScanT::Type; // Removes all elements from a integer sequence corresponding to specified // ValueToRemove. // // This type should not be used directly but instead RemoveValue. template struct RemoveValueImpl; // Final filtered sequence template struct RemoveValueImpl, std::integer_sequence> { using type = std::integer_sequence; }; // Found a matching value template struct RemoveValueImpl, std::integer_sequence> : RemoveValueImpl, std::integer_sequence> {}; // Move one element from the tail to the head template struct RemoveValueImpl, std::integer_sequence> : RemoveValueImpl, std::integer_sequence> {}; // Start recursion by splitting the integer sequence into two separate ones template struct RemoveValueImpl> : RemoveValueImpl, std::integer_sequence> {}; // RemoveValue takes an integer Sequence of arbitrary type and removes all // elements matching ValueToRemove. // // In contrast to RemoveValueImpl, this implementation deduces the value type // eliminating the need to specify it explicitly. // // As an example, RemoveValue, 4>::type will // not transform the type of the original sequence. However, // RemoveValue, 2>::type will generate a new // sequence of type std::integer_sequence by removing the value 2. template struct RemoveValue : RemoveValueImpl { }; // Convenience template alias for RemoveValue. template using RemoveValue_t = typename RemoveValue::type; // Returns true if all elements of Values are equal to HeadValue. // // Returns true if Values is empty. template inline constexpr bool AreAllEqual_v = ((HeadValue == Values) && ...); // Predicate determining whether an integer sequence is either empty or all // values are equal. template struct IsEmptyOrAreAllEqual; // Empty case. template struct IsEmptyOrAreAllEqual> : std::true_type {}; // General case for sequences containing at least one value. template struct IsEmptyOrAreAllEqual> : std::integral_constant> {}; // Convenience variable template for IsEmptyOrAreAllEqual. template inline constexpr bool IsEmptyOrAreAllEqual_v = IsEmptyOrAreAllEqual::value; } // namespace ceres::internal #endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_