#include "autodiff.h"

gctl::affvar::affvar(double v)
{
    der_ = 0.0;
    set(v);
}

void gctl::affvar::set(double v)
{
    val_ = v;
    return;
}

double gctl::affvar::val() const
{
    return val_;
}

double gctl::affvar::der() const
{
    return der_;
}

void gctl::affvar::var(std::initializer_list<affvar*> l, affvar &x) const
{
    for (affvar *a: l)
    {
        a->der_ = 0.0;
    }
    x.der_ = 1.0;
    return;
}

gctl::affvar gctl::affvar::operator = (double v) const
{
    affvar y(v);
    return y;
}

gctl::affvar gctl::affvar::operator + (const affvar &x) const
{
    affvar y;
    y.val_ = val_ + x.val_;
    y.der_ = der_ + x.der_;
    return y;
}

gctl::affvar gctl::affvar::operator - (const affvar &x) const
{
    affvar y;
    y.val_ = val_ - x.val_;
    y.der_ = der_ - x.der_;
    return y;
}

gctl::affvar gctl::affvar::operator * (const affvar &x) const
{
    affvar y;
    y.val_ = val_ * x.val_;
    y.der_ = val_ * x.der_ + der_ * x.val_;
    return y;
}

gctl::affvar gctl::operator * (double s, const gctl::affvar &x)
{
    gctl::affvar y;
    y.val_ = s * x.val_;
    y.der_ = s * x.der_;
    return y;
}

gctl::affvar gctl::sin(const gctl::affvar &x)
{
    gctl::affvar y;
    y.val_ = std::sin(x.val_);
    y.der_ = std::cos(x.val_) * x.der_;
    return y;
}

gctl::affvar gctl::cos(const gctl::affvar &x)
{
    gctl::affvar y;
    y.val_ = std::cos(x.val_);
    y.der_ = -1.0 * std::sin(x.val_) * x.der_;
    return y;
}