#ifndef __opt1d_h__
#define __opt1d_h__

#include "topotypes.h"

namespace toposmooth
{
    // Given a 1d sequence of values 'original_values' with 'num_values' elements,
    // returns a modified sequence in 'new_values_out' guaranteed to be monotonically decreasing,
    // and yet smooth and close to 'original_values'.
    //
    // The array 'values_spacing' is an array of length 'num_values' - 1,
    // where each element i is the finite element spacing between the
    // i and i+1 elements in 'original_values'.
    //
    // The gradient at the start and end of the sequence are given by 'gradient0' and 'gradientN'.
    //
    // NOTE: The gradient at the end should point *away* from the sequence, in the same direction
    //       as it would point if there were an additional value.
    // TODO Q: Can we allow one or both of the gradients to be free?
    //
    // The optional parameter 'stay_close_to_original_values_weight' determines how strongly
    // the output should try to stay close to the original values.
    // A value <= 0. means that they should not try to stay close at all, and the resulting
    // values will be purely smoothed.
    // The default value is 0.
    //
    // The optional parameter 'smooth_deformation_not_smooth_function', if true, means that
    // the smoothing term attempts to find a smooth deformation of the original values to
    // make them monotonic, rather than finding actually smooth values.
    // The default value is false.
    template< typename floating_type >
    void smooth1d_monotonically_decreasing(
        const size_t num_values,
        const floating_type* original_values,
        floating_type* new_values_out,
        const floating_type* values_spacing,
        const floating_type gradient0,
        const floating_type gradientN,
        const floating_type stay_close_to_original_values_weight = 0.,
        bool smooth_deformation_not_smooth_function = false
        );
}

#endif /* __opt1d_h__ */
