/********************************************************
 *  ██████╗  ██████╗████████╗██╗
 * ██╔════╝ ██╔════╝╚══██╔══╝██║
 * ██║  ███╗██║        ██║   ██║
 * ██║   ██║██║        ██║   ██║
 * ╚██████╔╝╚██████╗   ██║   ███████╗
 *  ╚═════╝  ╚═════╝   ╚═╝   ╚══════╝
 * Geophysical Computational Tools & Library (GCTL)
 *
 * Copyright (c) 2023  Yi Zhang (yizhang-geo@zju.edu.cn)
 *
 * GCTL is distributed under a dual licensing scheme. You can redistribute 
 * it and/or modify it under the terms of the GNU Lesser General Public 
 * License as published by the Free Software Foundation, either version 2 
 * of the License, or (at your option) any later version. You should have 
 * received a copy of the GNU Lesser General Public License along with this 
 * program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * If the terms and conditions of the LGPL v.2. would prevent you from using 
 * the GCTL, please consider the option to obtain a commercial license for a 
 * fee. These licenses are offered by the GCTL's original author. As a rule, 
 * licenses are provided "as-is", unlimited in time for a one time fee. Please 
 * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget 
 * to include some description of your company and the realm of its activities. 
 * Also add information on how to contact you by electronic and paper mail.
 ******************************************************/

#ifndef _VARIOGRAM_H
#define _VARIOGRAM_H

#include "../core/macro.h"

namespace gctl
{
    /**
     * @brief      variogram function type
     */
    enum variogram_type_e
    {
        SPHERICAL,
        EXPONENTIAL,
        GAUSSIAN,
        WAVE,
        RATIONAL_Q,
        CIRCULAR,
        LINEAR,
    };

    /**
     * @brief      variogram model structure
     */
    struct variogram_model
    {
        double nugget;
        double sill;
        double range;
        bool valid();
    };

    /**
     * @brief      Spherical Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double spherical_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Exponential Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double exponential_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Gaussian Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double gaussian_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Wave Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double wave_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Rational Quadratic Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double rational_quadratic_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Circular Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double circular_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Linear Semi-variogram Model based on http://spatial-analyst.net/ILWIS/htm/ilwisapp/sec/semivar_models_sec.html
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     *
     * @return     Semi-variogram value
     */
    double linear_variogram(const double &d, const variogram_model &vm);

    /**
     * @brief      Integral variogram function
     *
     * @param[in]  d     distance between points to covariant
     * @param[in]  vm    variogram model
     * @param[in]  type  variogram function type
     *
     * @return     Semi-variogram value
     */
    double variogram(const double &d, const variogram_model &vm, variogram_type_e type);
};

#endif // _VARIOGRAM_H