//
///////////////////////////////////////////////////////////////////////
// This file was generated by gen_basic_funcs.py on Thu Mar 12 12:57:50 2020
///////////////////////////////////////////////////////////////////////
// Copyright 2015 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

/****************************************************************************
 * This file is autogenerated! Any manual changes in here will be
 * overwritten by calling nocscript_gen_basic_funcs.py!
 ***************************************************************************/

#include "expression.hpp"
#include "function_table.hpp"
#include <uhd/exception.hpp>
#include <boost/format.hpp>
#include <boost/assign/list_of.hpp>

#include <boost/math/special_functions/round.hpp>
#include <chrono>
#include <thread>


#ifndef INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP
#define INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP

namespace uhd { namespace rfnoc { namespace nocscript {


expression_literal ADD__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() + args[1]->eval().get_int());
}

expression_literal ADD__DOUBLE__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_double() + args[1]->eval().get_double());
}

expression_literal MULT__DOUBLE__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_double() * args[1]->eval().get_double());
}

expression_literal MULT__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() * args[1]->eval().get_int());
}

expression_literal DIV__DOUBLE__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_double() / args[1]->eval().get_double());
}

expression_literal LE__BOOL__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_int() <= args[1]->eval().get_int()));
}

expression_literal LE__BOOL__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_double() <= args[1]->eval().get_double()));
}

expression_literal GE__BOOL__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_int() >= args[1]->eval().get_int()));
}

expression_literal GE__BOOL__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_double() >= args[1]->eval().get_double()));
}

expression_literal LT__BOOL__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_int() < args[1]->eval().get_int()));
}

expression_literal GT__BOOL__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_int() > args[1]->eval().get_int()));
}

expression_literal LT__BOOL__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_double() < args[1]->eval().get_double()));
}

expression_literal GT__BOOL__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_double() > args[1]->eval().get_double()));
}

expression_literal IROUND__INT__DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(int(boost::math::iround(args[0]->eval().get_double())));
}

expression_literal IS_PWR_OF_2__BOOL__INT(expression_container::expr_list_type &args)
{
    if (args[0]->eval().get_int() < 0) return expression_literal(false);
    int i = args[0]->eval().get_int();
    while ( (i & 1) == 0 and (i > 1) ) {
        i >>= 1;
    }
    return expression_literal(bool(i == 1));
}

expression_literal LOG2__INT__INT(expression_container::expr_list_type &args)
{
    if (args[0]->eval().get_int() < 0) {
        throw uhd::runtime_error(str(
            boost::format("In NocScript function LOG2__INT__INT: Cannot calculate log2() of negative number.")
        ));
    }

    int power_value = args[0]->eval().get_int();
    int log2_value = 0;
    while ( (power_value & 1) == 0 and (power_value > 1) ) {
        power_value >>= 1;
        log2_value++;
    }
    return expression_literal(log2_value);
}

expression_literal MODULO__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() % args[1]->eval().get_int());
}

expression_literal EQUAL__BOOL__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_int() == args[1]->eval().get_int()));
}

expression_literal EQUAL__BOOL__DOUBLE_DOUBLE(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_double() == args[1]->eval().get_double()));
}

expression_literal EQUAL__BOOL__STRING_STRING(expression_container::expr_list_type &args)
{
    return expression_literal(bool(args[0]->eval().get_string() == args[1]->eval().get_string()));
}

expression_literal SHIFT_RIGHT__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() >> args[1]->eval().get_int());
}

expression_literal SHIFT_LEFT__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() << args[1]->eval().get_int());
}

expression_literal BITWISE_AND__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() & args[1]->eval().get_int());
}

expression_literal BITWISE_OR__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() | args[1]->eval().get_int());
}

expression_literal BITWISE_XOR__INT__INT_INT(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_int() ^ args[1]->eval().get_int());
}

expression_literal XOR__BOOL__BOOL_BOOL(expression_container::expr_list_type &args)
{
    return expression_literal(args[0]->eval().get_bool() xor args[1]->eval().get_bool());
}

expression_literal NOT__BOOL__BOOL(expression_container::expr_list_type &args)
{
    return expression_literal(not args[0]->eval().get_bool());
}

expression_literal TRUE__BOOL__(expression_container::expr_list_type &)
{
    return expression_literal(true);
}

expression_literal FALSE__BOOL__(expression_container::expr_list_type &)
{
    return expression_literal(false);
}

expression_literal IF__BOOL__BOOL_BOOL(expression_container::expr_list_type &args)
{
    if (args[0]->eval().get_bool()) {
        args[1]->eval().get_bool();
        return expression_literal(true);
    }
    return expression_literal(false);
}

expression_literal IF_ELSE__BOOL__BOOL_BOOL_BOOL(expression_container::expr_list_type &args)
{
    if (args[0]->eval().get_bool()) {
        args[1]->eval().get_bool();
        return expression_literal(true);
    } else {
        args[2]->eval().get_bool();
    }
    return expression_literal(false);
}

expression_literal SLEEP__BOOL__DOUBLE(expression_container::expr_list_type &args)
{
    int ms = args[0]->eval().get_double() / 1000;
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    return expression_literal(true);
}

#define _REGISTER_ALL_FUNCS() \
    expression_function::argtype_list_type ADD__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "ADD", \
            boost::bind(&ADD__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            ADD__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type ADD__DOUBLE__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "ADD", \
            boost::bind(&ADD__DOUBLE__DOUBLE_DOUBLE, _1), \
            expression::TYPE_DOUBLE, \
            ADD__DOUBLE__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type MULT__DOUBLE__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "MULT", \
            boost::bind(&MULT__DOUBLE__DOUBLE_DOUBLE, _1), \
            expression::TYPE_DOUBLE, \
            MULT__DOUBLE__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type MULT__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "MULT", \
            boost::bind(&MULT__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            MULT__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type DIV__DOUBLE__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "DIV", \
            boost::bind(&DIV__DOUBLE__DOUBLE_DOUBLE, _1), \
            expression::TYPE_DOUBLE, \
            DIV__DOUBLE__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type LE__BOOL__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "LE", \
            boost::bind(&LE__BOOL__INT_INT, _1), \
            expression::TYPE_BOOL, \
            LE__BOOL__INT_INT_args \
    ); \
    expression_function::argtype_list_type LE__BOOL__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "LE", \
            boost::bind(&LE__BOOL__DOUBLE_DOUBLE, _1), \
            expression::TYPE_BOOL, \
            LE__BOOL__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type GE__BOOL__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "GE", \
            boost::bind(&GE__BOOL__INT_INT, _1), \
            expression::TYPE_BOOL, \
            GE__BOOL__INT_INT_args \
    ); \
    expression_function::argtype_list_type GE__BOOL__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "GE", \
            boost::bind(&GE__BOOL__DOUBLE_DOUBLE, _1), \
            expression::TYPE_BOOL, \
            GE__BOOL__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type LT__BOOL__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "LT", \
            boost::bind(&LT__BOOL__INT_INT, _1), \
            expression::TYPE_BOOL, \
            LT__BOOL__INT_INT_args \
    ); \
    expression_function::argtype_list_type GT__BOOL__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "GT", \
            boost::bind(&GT__BOOL__INT_INT, _1), \
            expression::TYPE_BOOL, \
            GT__BOOL__INT_INT_args \
    ); \
    expression_function::argtype_list_type LT__BOOL__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "LT", \
            boost::bind(&LT__BOOL__DOUBLE_DOUBLE, _1), \
            expression::TYPE_BOOL, \
            LT__BOOL__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type GT__BOOL__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "GT", \
            boost::bind(&GT__BOOL__DOUBLE_DOUBLE, _1), \
            expression::TYPE_BOOL, \
            GT__BOOL__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type IROUND__INT__DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "IROUND", \
            boost::bind(&IROUND__INT__DOUBLE, _1), \
            expression::TYPE_INT, \
            IROUND__INT__DOUBLE_args \
    ); \
    expression_function::argtype_list_type IS_PWR_OF_2__BOOL__INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "IS_PWR_OF_2", \
            boost::bind(&IS_PWR_OF_2__BOOL__INT, _1), \
            expression::TYPE_BOOL, \
            IS_PWR_OF_2__BOOL__INT_args \
    ); \
    expression_function::argtype_list_type LOG2__INT__INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "LOG2", \
            boost::bind(&LOG2__INT__INT, _1), \
            expression::TYPE_INT, \
            LOG2__INT__INT_args \
    ); \
    expression_function::argtype_list_type MODULO__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "MODULO", \
            boost::bind(&MODULO__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            MODULO__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type EQUAL__BOOL__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "EQUAL", \
            boost::bind(&EQUAL__BOOL__INT_INT, _1), \
            expression::TYPE_BOOL, \
            EQUAL__BOOL__INT_INT_args \
    ); \
    expression_function::argtype_list_type EQUAL__BOOL__DOUBLE_DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "EQUAL", \
            boost::bind(&EQUAL__BOOL__DOUBLE_DOUBLE, _1), \
            expression::TYPE_BOOL, \
            EQUAL__BOOL__DOUBLE_DOUBLE_args \
    ); \
    expression_function::argtype_list_type EQUAL__BOOL__STRING_STRING_args = boost::assign::list_of \
        (expression::TYPE_STRING) \
        (expression::TYPE_STRING) \
    ; \
    register_function( \
            "EQUAL", \
            boost::bind(&EQUAL__BOOL__STRING_STRING, _1), \
            expression::TYPE_BOOL, \
            EQUAL__BOOL__STRING_STRING_args \
    ); \
    expression_function::argtype_list_type SHIFT_RIGHT__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "SHIFT_RIGHT", \
            boost::bind(&SHIFT_RIGHT__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            SHIFT_RIGHT__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type SHIFT_LEFT__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "SHIFT_LEFT", \
            boost::bind(&SHIFT_LEFT__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            SHIFT_LEFT__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type BITWISE_AND__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "BITWISE_AND", \
            boost::bind(&BITWISE_AND__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            BITWISE_AND__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type BITWISE_OR__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "BITWISE_OR", \
            boost::bind(&BITWISE_OR__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            BITWISE_OR__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type BITWISE_XOR__INT__INT_INT_args = boost::assign::list_of \
        (expression::TYPE_INT) \
        (expression::TYPE_INT) \
    ; \
    register_function( \
            "BITWISE_XOR", \
            boost::bind(&BITWISE_XOR__INT__INT_INT, _1), \
            expression::TYPE_INT, \
            BITWISE_XOR__INT__INT_INT_args \
    ); \
    expression_function::argtype_list_type XOR__BOOL__BOOL_BOOL_args = boost::assign::list_of \
        (expression::TYPE_BOOL) \
        (expression::TYPE_BOOL) \
    ; \
    register_function( \
            "XOR", \
            boost::bind(&XOR__BOOL__BOOL_BOOL, _1), \
            expression::TYPE_BOOL, \
            XOR__BOOL__BOOL_BOOL_args \
    ); \
    expression_function::argtype_list_type NOT__BOOL__BOOL_args = boost::assign::list_of \
        (expression::TYPE_BOOL) \
    ; \
    register_function( \
            "NOT", \
            boost::bind(&NOT__BOOL__BOOL, _1), \
            expression::TYPE_BOOL, \
            NOT__BOOL__BOOL_args \
    ); \
    expression_function::argtype_list_type TRUE__BOOL___args; \
    register_function( \
            "TRUE", \
            boost::bind(&TRUE__BOOL__, _1), \
            expression::TYPE_BOOL, \
            TRUE__BOOL___args \
    ); \
    expression_function::argtype_list_type FALSE__BOOL___args; \
    register_function( \
            "FALSE", \
            boost::bind(&FALSE__BOOL__, _1), \
            expression::TYPE_BOOL, \
            FALSE__BOOL___args \
    ); \
    expression_function::argtype_list_type IF__BOOL__BOOL_BOOL_args = boost::assign::list_of \
        (expression::TYPE_BOOL) \
        (expression::TYPE_BOOL) \
    ; \
    register_function( \
            "IF", \
            boost::bind(&IF__BOOL__BOOL_BOOL, _1), \
            expression::TYPE_BOOL, \
            IF__BOOL__BOOL_BOOL_args \
    ); \
    expression_function::argtype_list_type IF_ELSE__BOOL__BOOL_BOOL_BOOL_args = boost::assign::list_of \
        (expression::TYPE_BOOL) \
        (expression::TYPE_BOOL) \
        (expression::TYPE_BOOL) \
    ; \
    register_function( \
            "IF_ELSE", \
            boost::bind(&IF_ELSE__BOOL__BOOL_BOOL_BOOL, _1), \
            expression::TYPE_BOOL, \
            IF_ELSE__BOOL__BOOL_BOOL_BOOL_args \
    ); \
    expression_function::argtype_list_type SLEEP__BOOL__DOUBLE_args = boost::assign::list_of \
        (expression::TYPE_DOUBLE) \
    ; \
    register_function( \
            "SLEEP", \
            boost::bind(&SLEEP__BOOL__DOUBLE, _1), \
            expression::TYPE_BOOL, \
            SLEEP__BOOL__DOUBLE_args \
    ); \


}}} /* namespace uhd::rfnoc::nocscript */

#endif /* INCLUDED_LIBUHD_RFNOC_NOCSCRIPT_BASICFUNCS_HPP */
