/*---------------------------------------------------------------------------*\

    geophase: A C++ template library for geometrical operations on non-convex
    polyhedra with non-planar faces
     
    Copyright (C) 2019 Tomislav Maric, TU Darmstadt 

    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/>.

Application
    geophaseTestPerturb

Description
    Test geometry perturbation by a small epsilon. 

Authors
    Tomislav Maric maric@mma.tu-darmstadt.de

\*---------------------------------------------------------------------------*/

#include "gtest/gtest.h" 
#include "Vector.hpp"
#include "Perturb.hpp"
#include "Equal.hpp"

using namespace geophase;

// Smoke test for the point perturbation.
TEST(perturbPoint, ulpEqual)
{
    std::random_device rd;  
    std::mt19937 gen(rd()); 
    std::uniform_real_distribution<> dis(-1., 1.);

    for (std::size_t testI = 0; testI < 100000; ++testI)
    {
        vector v1 = {dis(gen),dis(gen), dis(gen)}; 
        auto v2 = ulp_perturbed(v1, 10); 
        ASSERT_NE(v1, v2)
            << std::setprecision(20) << v1 << std::endl
            << v2 << std::endl;
        ASSERT_TRUE(equal_by_ulp(v1, v2, 10))
            << std::setprecision(20) << v1 << std::endl
            << v2 << std::endl;
    }
}

TEST(perturbPoint, toleranceEqual)
{
    std::random_device rd;  
    std::mt19937 gen(rd()); 
    std::uniform_real_distribution<> dis(-1., 1.);

    for (std::size_t testI = 0; testI < 100000; ++testI)
    {
        vector v1 = {dis(gen),dis(gen), dis(gen)}; 
        auto v2 = tolerance_perturbed(v1, EPSILON); 
        ASSERT_NE(v1, v2)
            << std::setprecision(20) << v1 << std::endl
            << v2 << std::endl;
        ASSERT_TRUE(equal_by_tolerance(v1, v2, EPSILON))
            << std::setprecision(20) << v1 << std::endl
            << v2 << std::endl;
    }
}

int mainArgc; 
char** mainArgv; 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:

int main(int argc, char *argv[])
{
    ::testing::InitGoogleTest(&argc, argv);
   
    mainArgc = argc; 
    mainArgv = argv;

    return RUN_ALL_TESTS();
}


// ************************************************************************* //
