//This file is part of Bertini 2.
//
//differentiate_test.cpp 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.
//
//differentiate_test.cpp 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 differentiate_test.cpp. If not, see .
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin eau claire
//
// Created by Collins, James B. on 4/30/15.
// Copyright (c) 2015 West Texas A&M University. All rights reserved.
#include
#include
#include
#include
#include "bertini2/function_tree.hpp"
#include "bertini2/system/system.hpp"
#include "bertini2/io/parsing/system_parsers.hpp"
#include
#include
#include
#include "externs.hpp"
BOOST_AUTO_TEST_SUITE(differentiate)
using bertini::DefaultPrecision;
using dbl = std::complex;
using Variable = bertini::node::Variable;
using Node = bertini::node::Node;
using Function = bertini::node::Function;
using Jacobian = bertini::node::Jacobian;
using dbl = bertini::dbl;
using mpfr = bertini::mpfr_complex;
using mpfr_float = bertini::mpfr_float;
/////////// Basic Operations Alone ///////////////////
BOOST_AUTO_TEST_CASE(just_diff_a_function){
std::string str = "function f; variable_group x,y,z; f = x*y +y^2 - z*x + 9;";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
for(auto vv : vars)
{
JFunc->EvalJ(vv);
JFunc->EvalJ(vv);
}
std::vector multidegree{1,2,1};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 2);
}
BOOST_AUTO_TEST_CASE(diff_3xyz){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = 3*x*y*z;";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
BOOST_CHECK_EQUAL(func->Degree(),3);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),1);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),1);
std::vector multidegree{1,1,1};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 3);
std::vector exact_dbl = {3.0*ynum_dbl*znum_dbl, 3.0*xnum_dbl*znum_dbl, 3.0*ynum_dbl*xnum_dbl};
std::vector exact_mpfr = {mpfr("3.0")*ynum_mpfr*znum_mpfr,mpfr("3.0")*xnum_mpfr*znum_mpfr,mpfr("3.0")*ynum_mpfr*xnum_mpfr};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() / exact_dbl[0].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() / exact_dbl[0].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() / exact_mpfr[0].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() / exact_mpfr[0].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() / exact_dbl[1].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() / exact_dbl[1].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() / exact_mpfr[1].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() / exact_mpfr[1].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() / exact_dbl[2].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() / exact_dbl[2].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() / exact_mpfr[2].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() / exact_mpfr[2].imag() -1) < threshold_clearance_mp);
var_mpfr << bertini::multiprecision::rand(),bertini::multiprecision::rand(),bertini::multiprecision::rand();
sys.SetVariables(var_mpfr);
exact_mpfr[0] = 3*var_mpfr(1)*var_mpfr(2);
exact_mpfr[1] = 3*var_mpfr(0)*var_mpfr(2);
exact_mpfr[2] = 3*var_mpfr(0)*var_mpfr(1);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() / exact_mpfr[0].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() / exact_mpfr[0].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() / exact_mpfr[1].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() / exact_mpfr[1].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() / exact_mpfr[2].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() / exact_mpfr[2].imag() -1) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_constant){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = 4.5 + i*8.2;";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{0,0,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 0);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {0.0, 0.0, 0.0};
std::vector exact_mpfr = {mpfr("0.0"),mpfr("0.0"),mpfr("0.0")};
for(int ii = 0; ii < vars.size(); ++ii)
{
BOOST_CHECK(fabs(JFunc->EvalJ(vars[ii]).real() - exact_dbl[ii].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[ii]).imag() - exact_dbl[ii].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[ii]).real() - exact_mpfr[ii].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[ii]).imag() - exact_mpfr[ii].imag() ) < threshold_clearance_mp);
}
}
BOOST_AUTO_TEST_CASE(diff_sum_xyz_constant){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = x-y+z-4.5+i*7.3;";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{1,1,1};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 1);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),1);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),1);
std::vector exact_dbl = {1.0, -1.0, 1.0};
std::vector exact_mpfr = {mpfr("1.0"),mpfr("-1.0"),mpfr("1.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_x_squared_times_z_cubed){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = (x^2)*(y^3);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{2,3,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 5);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),2);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),3);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {2.0*xnum_dbl*pow(ynum_dbl,3.0), 3.0*pow(ynum_dbl*xnum_dbl,2.0), 0.0};
std::vector exact_mpfr = {mpfr("2.0")*xnum_mpfr*pow(ynum_mpfr,3),mpfr("3.0")*pow(ynum_mpfr,2)*pow(xnum_mpfr,2),mpfr("0.0")};
JFunc->Reset();
sys.SetVariables(var_dbl);
auto J_val_0_d = JFunc->EvalJ(vars[0]);
JFunc->Reset();
sys.SetVariables(var_dbl);
auto J_val_1_d = JFunc->EvalJ(vars[1]);
JFunc->Reset();
sys.SetVariables(var_dbl);
auto J_val_2_d = JFunc->EvalJ(vars[2]);
JFunc->Reset();
sys.SetVariables(var_mpfr);
auto J_val_0_mp = JFunc->EvalJ(vars[0]);
JFunc->Reset();
sys.SetVariables(var_mpfr);
auto J_val_1_mp = JFunc->EvalJ(vars[1]);
JFunc->Reset();
sys.SetVariables(var_mpfr);
auto J_val_2_mp = JFunc->EvalJ(vars[2]);
BOOST_CHECK(fabs(J_val_0_d.real() / exact_dbl[0].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_0_d.imag() / exact_dbl[0].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_0_mp.real()/exact_mpfr[0].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(J_val_0_mp.imag()/exact_mpfr[0].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(J_val_1_d.real() / exact_dbl[1].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_1_d.imag() / exact_dbl[1].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_1_mp.real()/exact_mpfr[1].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(J_val_1_mp.imag()/exact_mpfr[1].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(J_val_2_d.real() - exact_dbl[2].real()) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_2_d.imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(J_val_2_mp.real()-exact_mpfr[2].real()) < threshold_clearance_mp);
BOOST_CHECK(fabs(J_val_2_mp.imag()-exact_mpfr[2].imag()) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_x_squared_over_y_cubed){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = (x^2)/(y^3);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{2,-1,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),2);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {2.0*xnum_dbl/pow(ynum_dbl,3.0), -3.0*pow(xnum_dbl,2.0)/pow(ynum_dbl,4.0), 0.0};
std::vector exact_mpfr = {mpfr("2.0")*xnum_mpfr/pow(ynum_mpfr,3),mpfr("-3.0")*pow(xnum_mpfr,2)/pow(ynum_mpfr,4),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_x_squared_times_lx_plus_numl){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = (x^2)*(x+3);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{3,0,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), 3);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),3);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {3.0*pow(xnum_dbl,2.0) + 6.0*xnum_dbl, 0.0, 0.0};
std::vector exact_mpfr = {mpfr("3.0")*pow(xnum_mpfr,mpfr("2.0")) + mpfr("6.0")*xnum_mpfr,mpfr("0.0"),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() / exact_dbl[0].real() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() / exact_dbl[0].imag() -1) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() / exact_mpfr[0].real() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() / exact_mpfr[0].imag() -1) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_2y_over_ly_squared_minus_numl){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = y/(y+1);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{0,-1,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {0.0, pow(ynum_dbl+1.0,-2.0), 0.0};
std::vector exact_mpfr = {mpfr("0.0"),pow(ynum_mpfr+mpfr("1.0"),mpfr("-2.0")),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_sin_x){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = sin(x);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{-1,0,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {cos(xnum_dbl), 0.0, 0.0};
std::vector exact_mpfr = {cos(xnum_mpfr),mpfr("0.0"),mpfr("0.0")};
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[0]).real(), exact_dbl[0].real(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[0]).imag(), exact_dbl[0].imag(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[0]).real(), exact_mpfr[0].real(), threshold_clearance_mp);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[0]).imag(), exact_mpfr[0].imag(), threshold_clearance_mp);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[1]).real(), exact_dbl[1].real(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[1]).imag(), exact_dbl[1].imag(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[1]).real(), exact_mpfr[1].real(), threshold_clearance_mp);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[1]).imag(), exact_mpfr[1].imag(), threshold_clearance_mp);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[2]).real(), exact_dbl[2].real(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[2]).imag(), exact_dbl[2].imag(), threshold_clearance_d);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[2]).real(), exact_mpfr[2].real(), threshold_clearance_mp);
BOOST_CHECK_CLOSE( JFunc->EvalJ(vars[2]).imag(), exact_mpfr[2].imag(), threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_cos_y){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = cos(y);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
std::vector multidegree{0,-1,0};
bool multidegree_ok = multidegree==func->MultiDegree(vars);
BOOST_CHECK(multidegree_ok);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
BOOST_CHECK_EQUAL(func->Degree(vars[0]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
std::vector exact_dbl = {0.0, -1.0*sin(ynum_dbl), 0.0};
std::vector exact_mpfr = {mpfr("0.0"),-sin(ynum_mpfr),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_tan_z){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = tan(z);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
BOOST_CHECK_EQUAL(func->Degree(vars[0]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
std::vector exact_dbl = {0.0,0.0, (1.0/cos(znum_dbl))*(1.0/cos(znum_dbl))};
std::vector exact_mpfr = {mpfr("0.0"),mpfr("0.0"),(mpfr("1.0")/cos(znum_mpfr))*(mpfr("1.0")/cos(znum_mpfr))};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_exp_x){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = exp(x);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
BOOST_CHECK_EQUAL(func->Degree(vars[0]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
std::vector exact_dbl = {exp(xnum_dbl), 0.0, 0.0};
std::vector exact_mpfr = {exp(xnum_mpfr),mpfr("0.0"),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_log_x){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = log(x^2+y);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
sys.Differentiate();
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
BOOST_CHECK_EQUAL(func->Degree(vars[0]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
std::vector exact_dbl = {2.0*xnum_dbl/(xnum_dbl*xnum_dbl+ynum_dbl), 1.0/(xnum_dbl*xnum_dbl+ynum_dbl), 0.0};
std::vector exact_mpfr = {mpfr(2.0)*xnum_mpfr/(xnum_mpfr*xnum_mpfr+ynum_mpfr), mpfr(1.0)/(xnum_mpfr*xnum_mpfr+ynum_mpfr),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
BOOST_AUTO_TEST_CASE(diff_sqrt_y){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = sqrt(y);";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables(var_dbl);
sys.SetVariables(var_mpfr);
auto func = sys.Function(0);
auto vars = sys.Variables();
auto JFunc = Jacobian::Make(func->Differentiate());
BOOST_CHECK_EQUAL(func->Degree(vars[0]),0);
BOOST_CHECK_EQUAL(func->Degree(vars[1]),-1);
BOOST_CHECK_EQUAL(func->Degree(vars[2]),0);
BOOST_CHECK_EQUAL(func->Degree(vars), -1);
std::vector exact_dbl = {0.0, 0.5/sqrt(ynum_dbl), 0.0};
std::vector exact_mpfr = {mpfr("0.0"),mpfr("0.5")/sqrt(ynum_mpfr),mpfr("0.0")};
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_dbl[0].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_dbl[0].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).real() - exact_mpfr[0].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[0]).imag() - exact_mpfr[0].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_dbl[1].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_dbl[1].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).real() - exact_mpfr[1].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[1]).imag() - exact_mpfr[1].imag() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_dbl[2].real() ) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_dbl[2].imag()) < threshold_clearance_d);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).real() - exact_mpfr[2].real() ) < threshold_clearance_mp);
BOOST_CHECK(fabs(JFunc->EvalJ(vars[2]).imag() - exact_mpfr[2].imag() ) < threshold_clearance_mp);
}
/////////// Chain Rule ///////////////////
BOOST_AUTO_TEST_CASE(diff_lz_plus_3l_cubed){
bertini::DefaultPrecision(CLASS_TEST_MPFR_DEFAULT_DIGITS);
std::string str = "function f; variable_group x,y,z; f = (z+3)^3;";
bertini::System sys;
bertini::parsing::classic::parse(str.begin(), str.end(), sys);
sys.SetEvalMethod(bertini::EvalMethod::FunctionTree);
Eigen::Matrix var_dbl;
Eigen::Matrix var_mpfr;
var_dbl << xnum_dbl, ynum_dbl, znum_dbl;
var_mpfr << xnum_mpfr, ynum_mpfr, znum_mpfr;
sys.SetVariables