/*
    GNU Octave level-set package.
    Copyright (C) 2014-2015  Daniel Kraft <d@domob.eu>

    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 3 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, see <http://www.gnu.org/licenses/>.
*/

#ifndef UTILS_HPP
#define UTILS_HPP

/* Some basic utility routines shared between the .oct files.  */

#include "FastMarching.hpp"

#include <octave/oct.h>

#include <cassert>
#include <sstream>
#include <stdexcept>
#include <string>

/**
 * Check and possibly return dimensions of an array.  If d1 and d2 are
 * both given as positive numbers, check that the array has the given size.
 * If one of them is negative (-1), return the dimension along this
 * dimension and check only the other one.  Throw if mismatch.
 * @param var The array to check.
 * @param d1 Row dimension.
 * @param d2 Column dimension.
 * @return Possibly the -1 dimension size.
 */
#define getDimension(var, d1, d2) \
  getDimensionReal (var, #var, d1, d2)
template<typename Arr>
  unsigned getDimensionReal (const Arr& var, const std::string& name,
                             int d1, int d2);

/**
 * Convert an IndexTuple to an index suitable to Octave as the
 * used type Array<octave_idx_type>.
 * @param ind IndexTuple representing the coordinate.
 * @return The same index suitable for Octave.
 */
Array<octave_idx_type> getOctaveIdx (const fastMarching::IndexTuple& ind);

/**
 * Convert a generic container to an Octave ColumnVector.
 * @param cont Generic container (e. g., std::vector<double>).
 * @return ColumnVector with the container's content.
 */
template<typename C>
  ColumnVector convertToColumnVector (const C& cont);

/**
 * Given two phi values with differing signs, calculate the approximate
 * fraction along the edge connecting both where the zero lies.  This
 * function in particular also handles infinities well.
 * @param my Phi value at the "current point" (corresponding to fraction 0).
 * @param other Other phi value, correspondig to fraction 1.
 * @return Fraction of the zero level-set intersection.
 */
double getZeroFraction (double my, double other);

/* Include template implementations.  */
#include "Utils.tpp"

#endif /* Header guard.  */
