#include "./fpe.hpp"

#include <stdexcept>

#include <cassert>

#include <fenv.h>

using cruft::debug::fpe::scoped_reset;


///////////////////////////////////////////////////////////////////////////////
static constexpr int EXCEPTION_MASK = FE_INVALID | FE_DIVBYZERO;


//-----------------------------------------------------------------------------
void
cruft::debug::fpe::enable (void)
{
    feenableexcept (EXCEPTION_MASK);
}


//-----------------------------------------------------------------------------
void
cruft::debug::fpe::disable (void)
{
    fedisableexcept (EXCEPTION_MASK);
}


//-----------------------------------------------------------------------------
bool cruft::debug::fpe::value (void)
{
    return feenableexcept (0) & EXCEPTION_MASK;
}


//-----------------------------------------------------------------------------
bool cruft::debug::fpe::value (bool val)
{
    if (val)
        enable ();
    else
        disable ();
    return val;
}


///////////////////////////////////////////////////////////////////////////////
scoped_reset::scoped_reset ()
    : m_prev (value ())
{ }


//-----------------------------------------------------------------------------
scoped_reset::scoped_reset (bool _value)
    : scoped_reset ()
{
    value (_value);
}


//-----------------------------------------------------------------------------
scoped_reset::~scoped_reset ()
{
    value (m_prev);
}