text:
/*
 * GraphBLAS Template Library (GBTL), Version 3.0
 *
 * Copyright 2020 Carnegie Mellon University, Battelle Memorial Institute, and
 * Authors.
 *
 * THIS MATERIAL WAS PREPARED AS AN ACCOUNT OF WORK SPONSORED BY AN AGENCY OF
 * THE UNITED STATES GOVERNMENT.  NEITHER THE UNITED STATES GOVERNMENT NOR THE
 * UNITED STATES DEPARTMENT OF ENERGY, NOR THE UNITED STATES DEPARTMENT OF
 * DEFENSE, NOR CARNEGIE MELLON UNIVERSITY, NOR BATTELLE, NOR ANY OF THEIR
 * EMPLOYEES, NOR ANY JURISDICTION OR ORGANIZATION THAT HAS COOPERATED IN THE
 * DEVELOPMENT OF THESE MATERIALS, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
 * ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS,
 * OR USEFULNESS OR ANY INFORMATION, APPARATUS, PRODUCT, SOFTWARE, OR PROCESS
 * DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED
 * RIGHTS.
 *
 * Released under a BSD-style license, please see LICENSE file or contact
 * permission@sei.cmu.edu for full terms.
 *
 * [DISTRIBUTION STATEMENT A] This material has been approved for public release
 * and unlimited distribution.  Please see Copyright notice for non-US
 * Government use and distribution.
 *
 * This Software includes and/or makes use of the following Third-Party Software
 * subject to its own license:
 *
 * 1. Boost Unit Test Framework
 * (https://www.boost.org/doc/libs/1_45_0/libs/test/doc/html/utf.html)
 * Copyright 2001 Boost software license, Gennadiy Rozental.
 *
 * DM20-0442
 */

#include <functional>
#include <iostream>
#include <vector>

#include <graphblas/graphblas.hpp>

using namespace grb;

#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE algebra_unary_test_suite

#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE)

//****************************************************************************
// Summary
//****************************************************************************
BOOST_AUTO_TEST_CASE(misc_math_tests)
{
    /// @todo Boost Test Framework does not handle commas in template
    ///       parameter lists without extra parentheses
    BOOST_CHECK_EQUAL((Identity<float, int>()(2.5)), 2);

    BOOST_CHECK_EQUAL(Abs<float>()(-2.5), 2.5);
    BOOST_CHECK_EQUAL(Abs<int>()(-2), 2);
    BOOST_CHECK_EQUAL(AdditiveInverse<double>()(-10), 10);
    BOOST_CHECK_EQUAL(AdditiveInverse<double>()(500), -500);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<double>()(5), 1./5);
    BOOST_CHECK_EQUAL(LogicalNot<int>()(1), false);
    BOOST_CHECK_EQUAL(BitwiseNot<unsigned int>()(1), 0xfffffffe);
    //BOOST_CHECK_EQUAL(BitwiseNot<float>()(1.0), 0xfffffffe);  // does not compile

    BOOST_CHECK_EQUAL(LogicalOr<bool>()(true, false), true);
    BOOST_CHECK_EQUAL(LogicalAnd<bool>()(false, true), false);
    BOOST_CHECK_EQUAL(LogicalXor<bool>()(false, true), true);
    BOOST_CHECK_EQUAL(LogicalXnor<bool>()(false, true), false);

    BOOST_CHECK_EQUAL(BitwiseOr<unsigned short>()(0x00ff, 0x0f0f), 0x0fff);
    BOOST_CHECK_EQUAL(BitwiseAnd<unsigned short>()(0x00ff, 0x0f0f), 0x000f);
    BOOST_CHECK_EQUAL(BitwiseXor<unsigned short>()(0x00ff, 0x0f0f), 0x0ff0);
    BOOST_CHECK_EQUAL(BitwiseXnor<unsigned short>()(0x00ff, 0x0f0f), 0xf00f);
}

//****************************************************************************
// Test Unary Operators
//****************************************************************************

//****************************************************************************
BOOST_AUTO_TEST_CASE(Identity_test)
{
    int8_t  i8  = 3;
    int16_t i16 = -400;
    int32_t i32 = -1001000;
    int64_t i64 = 5123123123;
    BOOST_CHECK_EQUAL(Identity<int8_t>()(i8),  i8);
    BOOST_CHECK_EQUAL(Identity<int16_t>()(i8),  i8);
    BOOST_CHECK_EQUAL(Identity<int32_t>()(i8),  i8);
    BOOST_CHECK_EQUAL(Identity<int64_t>()(i8),  i8);

    BOOST_CHECK_EQUAL(Identity<int16_t>()(i16), i16);
    BOOST_CHECK_EQUAL(Identity<int32_t>()(i32), i32);
    BOOST_CHECK_EQUAL(Identity<int64_t>()(i64), i64);

    uint8_t  ui8  = 3;
    uint16_t ui16 = 400;
    uint32_t ui32 = 1001000;
    uint64_t ui64 = 5123123123;
    BOOST_CHECK_EQUAL(Identity<uint8_t>()(ui8),  ui8);
    BOOST_CHECK_EQUAL(Identity<uint16_t>()(ui16), ui16);
    BOOST_CHECK_EQUAL(Identity<uint32_t>()(ui32), ui32);
    BOOST_CHECK_EQUAL(Identity<uint64_t>()(ui64), ui64);

    float   f32 = 3.14159;
    double  f64 = 2.718832654;
    BOOST_CHECK_EQUAL(Identity<float>()(f32), f32);
    BOOST_CHECK_EQUAL(Identity<double>()(f64), f64);

    BOOST_CHECK_EQUAL(Identity<uint32_t>()(f32), 3U);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(identity_same_domain_test)
{
    BOOST_CHECK_EQUAL(Identity<double>()(2.2), 2.2);
    BOOST_CHECK_EQUAL(Identity<float>()(2.2f), 2.2f);

    BOOST_CHECK_EQUAL(Identity<uint64_t>()(2UL), 2UL);
    BOOST_CHECK_EQUAL(Identity<uint32_t>()(2U), 2U);
    BOOST_CHECK_EQUAL(Identity<uint16_t>()(2), 2);
    BOOST_CHECK_EQUAL(Identity<uint8_t>()(2), 2);

    BOOST_CHECK_EQUAL(Identity<int64_t>()(-2L), -2L);
    BOOST_CHECK_EQUAL(Identity<int32_t>()(-2), -2);
    BOOST_CHECK_EQUAL(Identity<int16_t>()(-2), -2);
    BOOST_CHECK_EQUAL(Identity<int8_t>()(-2), -2);

    BOOST_CHECK_EQUAL(Identity<bool>()(false), false);
    BOOST_CHECK_EQUAL(Identity<bool>()(true), true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(identity_different_domain_test)
{
    /// @todo this is an incomplete set of pairs and does not cover the
    /// corner cases at the numeric limits that actually vary by platform
    BOOST_CHECK_EQUAL((Identity<double,float>()(2.2)), 2.2f);
    BOOST_CHECK_EQUAL((Identity<double,uint64_t>()(2.2)), 2UL);
    BOOST_CHECK_EQUAL((Identity<double,int64_t>()(-2.2)), -2UL);
    BOOST_CHECK_EQUAL((Identity<double,bool>()(2.2)), true);
    BOOST_CHECK_EQUAL((Identity<double,bool>()(0.0)), false);

    BOOST_CHECK_EQUAL((Identity<float,double>()(2.2f)), static_cast<double>(2.2f));
    BOOST_CHECK_EQUAL((Identity<float,uint32_t>()(2.2f)), 2U);
    BOOST_CHECK_EQUAL((Identity<float,int32_t>()(-2.2f)), -2);
    BOOST_CHECK_EQUAL((Identity<float,bool>()(2.2f)), true);
    BOOST_CHECK_EQUAL((Identity<float,bool>()(0.0f)), false);

    BOOST_CHECK_EQUAL((Identity<uint64_t, double>()(2UL)), 2.0);
    BOOST_CHECK_EQUAL((Identity<uint64_t, float>()(2UL)), 2.0f);
    BOOST_CHECK_EQUAL((Identity<uint64_t, int64_t>()(2UL)), 2UL);
    BOOST_CHECK_EQUAL((Identity<uint64_t,uint32_t>()(2UL)), 2UL);
    BOOST_CHECK_EQUAL((Identity<uint64_t,bool>()(2UL)), true);
    BOOST_CHECK_EQUAL((Identity<uint64_t,bool>()(0UL)), false);

    BOOST_CHECK_EQUAL((Identity<uint32_t, double>()(2U)), 2.0);
    BOOST_CHECK_EQUAL((Identity<uint32_t, float>()(2U)), 2.0f);
    BOOST_CHECK_EQUAL((Identity<uint32_t,uint64_t>()(2U)), 2UL);
    BOOST_CHECK_EQUAL((Identity<uint32_t, int64_t>()(2U)), 2L);
    BOOST_CHECK_EQUAL((Identity<uint32_t, int32_t>()(2U)), 2U);
    BOOST_CHECK_EQUAL((Identity<uint32_t,uint16_t>()(2U)), 2U);
    BOOST_CHECK_EQUAL((Identity<uint32_t, int16_t>()(2U)), 2);
    BOOST_CHECK_EQUAL((Identity<uint32_t,bool>()(2U)), true);
    BOOST_CHECK_EQUAL((Identity<uint32_t,bool>()(0U)), false);

    BOOST_CHECK_EQUAL((Identity<uint16_t, double>()(2U)), 2.0);
    BOOST_CHECK_EQUAL((Identity<uint16_t, float>()(2U)), 2.0f);
    BOOST_CHECK_EQUAL((Identity<uint16_t,uint32_t>()(2U)), 2U);
    BOOST_CHECK_EQUAL((Identity<uint16_t, int32_t>()(2U)), 2);
    BOOST_CHECK_EQUAL((Identity<uint16_t, int16_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint16_t,uint8_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint16_t, int8_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint16_t,bool>()(2U)), true);
    BOOST_CHECK_EQUAL((Identity<uint16_t,bool>()(0U)), false);

    BOOST_CHECK_EQUAL((Identity<uint8_t,double>()(2U)), 2.0);
    BOOST_CHECK_EQUAL((Identity<uint8_t,float>()(2U)), 2.0f);
    BOOST_CHECK_EQUAL((Identity<uint8_t,int8_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint8_t,uint16_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint8_t,int16_t>()(2)), 2);
    BOOST_CHECK_EQUAL((Identity<uint8_t,bool>()(2U)), true);
    BOOST_CHECK_EQUAL((Identity<uint8_t,bool>()(0U)), false);

    BOOST_CHECK_EQUAL((Identity<int64_t,double>()(-2L)), -2.0);
    BOOST_CHECK_EQUAL((Identity<int64_t,float>()(-2L)), -2.0f);
    BOOST_CHECK_EQUAL((Identity<int64_t,int32_t>()(-2L)), -2);
    BOOST_CHECK_EQUAL((Identity<int64_t,int16_t>()(-2L)), -2);
    BOOST_CHECK_EQUAL((Identity<int64_t,bool>()(-2L)), true);
    BOOST_CHECK_EQUAL((Identity<int64_t,bool>()(0L)), false);

    BOOST_CHECK_EQUAL((Identity<int32_t,double>()(-2)), -2.0);
    BOOST_CHECK_EQUAL((Identity<int32_t,float>()(-2)), -2.0f);
    BOOST_CHECK_EQUAL((Identity<int32_t,int64_t>()(-2)), -2);
    BOOST_CHECK_EQUAL((Identity<int32_t,int16_t>()(-2)), -2);
    BOOST_CHECK_EQUAL((Identity<int32_t,bool>()(-2)), true);
    BOOST_CHECK_EQUAL((Identity<int32_t,bool>()(0)), false);

    BOOST_CHECK_EQUAL((Identity<int16_t,double>()(-2)), -2.0);
    BOOST_CHECK_EQUAL((Identity<int16_t,float>()(-2)), -2.0f);
    BOOST_CHECK_EQUAL((Identity<int16_t,int32_t>()(-2)), -2);
    BOOST_CHECK_EQUAL((Identity<int16_t,int8_t>()(-2)), -2);
    BOOST_CHECK_EQUAL((Identity<int16_t,bool>()(-2)), true);
    BOOST_CHECK_EQUAL((Identity<int16_t,bool>()(0)), false);

    BOOST_CHECK_EQUAL((Identity<int8_t,double>()(-2)), -2.0);
    BOOST_CHECK_EQUAL((Identity<int8_t,float>()(-2)), -2.0f);
    BOOST_CHECK_EQUAL((Identity<int8_t,int16_t>()(-2)), -2);
    BOOST_CHECK_EQUAL((Identity<int8_t,bool>()(-2)), true);
    BOOST_CHECK_EQUAL((Identity<int8_t,bool>()(0)), false);

    BOOST_CHECK_EQUAL((Identity<bool,double>()(false)), 0.0);
    BOOST_CHECK_EQUAL((Identity<bool,double>()(true)), 1.0);
    BOOST_CHECK_EQUAL((Identity<bool,float>()(false)), 0.0f);
    BOOST_CHECK_EQUAL((Identity<bool,float>()(true)), 1.0f);
    BOOST_CHECK_EQUAL((Identity<bool,uint32_t>()(false)), 0U);
    BOOST_CHECK_EQUAL((Identity<bool,uint32_t>()(true)), 1U);
    BOOST_CHECK_EQUAL((Identity<bool,int32_t>()(false)), 0);
    BOOST_CHECK_EQUAL((Identity<bool,int32_t>()(true)), 1);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(Abs_test)
{
    int8_t  i8  = -8;
    int16_t i16 = -16;
    int32_t i32 = -32;
    int64_t i64 = -64;

    signed char   ci  = -64;
    short         si  = -128;
    int           i   = -256;
    long int      li  = -512;

    uint8_t  ui8  = 8;
    uint16_t ui16 = 16;
    uint32_t ui32 = 32;
    uint64_t ui64 = 64;

    unsigned char     uci  = 64;
    unsigned short    usi  = 128;
    unsigned int      ui   = 256;
    unsigned long int uli  = 512;

    float f = -45.45f;
    double d = -1048.36;

    BOOST_CHECK_EQUAL(Abs<int8_t>()(i8),   abs(i8));
    BOOST_CHECK_EQUAL(Abs<int16_t>()(i16), abs(i16));
    BOOST_CHECK_EQUAL(Abs<int32_t>()(i32), abs(i32));
    BOOST_CHECK_EQUAL(Abs<int64_t>()(i64), labs(i64));

    BOOST_CHECK_EQUAL(Abs<char>()(ci),     abs(ci));
    BOOST_CHECK_EQUAL(Abs<short>()(si),    abs(si));
    BOOST_CHECK_EQUAL(Abs<int>()(i),       abs(i));
    BOOST_CHECK_EQUAL(Abs<long int>()(li), labs(li));

    BOOST_CHECK_EQUAL(Abs<uint8_t>()(ui8),   ui8);
    BOOST_CHECK_EQUAL(Abs<uint16_t>()(ui16), ui16);
    BOOST_CHECK_EQUAL(Abs<uint32_t>()(ui32), ui32);
    BOOST_CHECK_EQUAL(Abs<uint64_t>()(ui64), ui64);

    BOOST_CHECK_EQUAL(Abs<bool>()(true), true);

    BOOST_CHECK_EQUAL(Abs<unsigned char>()(uci),  uci);
    BOOST_CHECK_EQUAL(Abs<unsigned short>()(usi), usi);
    BOOST_CHECK_EQUAL(Abs<unsigned int>()(ui),    ui);
    BOOST_CHECK_EQUAL(Abs<unsigned long>()(uli),  uli);

    BOOST_CHECK_EQUAL(Abs<unsigned int>()(ui),   ui);

    BOOST_CHECK_EQUAL(Abs<float>()(f), fabsf(f));
    BOOST_CHECK_EQUAL(Abs<double>()(d), fabs(d));
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(additive_inverse_test)
{
    BOOST_CHECK_EQUAL(AdditiveInverse<double>()(2.2), -2.2);
    BOOST_CHECK_EQUAL(AdditiveInverse<double>()(0.0), 0.0);
    BOOST_CHECK_EQUAL(AdditiveInverse<double>()(-2.0), 2.0);

    BOOST_CHECK_EQUAL(AdditiveInverse<float>()(2.2f), -2.2f);
    BOOST_CHECK_EQUAL(AdditiveInverse<float>()(0.0f), 0.0f);
    BOOST_CHECK_EQUAL(AdditiveInverse<float>()(-2.2f), 2.2f);

    BOOST_CHECK_EQUAL(AdditiveInverse<uint64_t>()(2UL), static_cast<uint64_t>(-2L));
    BOOST_CHECK_EQUAL(AdditiveInverse<uint64_t>()(0UL), 0UL);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint64_t>()(-2), 2UL);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint32_t>()(2U), static_cast<uint32_t>(-2));
    BOOST_CHECK_EQUAL(AdditiveInverse<uint32_t>()(0U), 0U);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint32_t>()(-2), 2U);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint16_t>()(2), static_cast<uint16_t>(-2));
    BOOST_CHECK_EQUAL(AdditiveInverse<uint16_t>()(0), 0);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint16_t>()(-2), 2);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint8_t>()(2), static_cast<uint8_t>(-2));
    BOOST_CHECK_EQUAL(AdditiveInverse<uint8_t>()(0), 0);
    BOOST_CHECK_EQUAL(AdditiveInverse<uint8_t>()(-2), 2);

    BOOST_CHECK_EQUAL(AdditiveInverse<int64_t>()(-2L), 2L);
    BOOST_CHECK_EQUAL(AdditiveInverse<int64_t>()(0L), 0L);
    BOOST_CHECK_EQUAL(AdditiveInverse<int64_t>()(2L), -2L);
    BOOST_CHECK_EQUAL(AdditiveInverse<int32_t>()(-2), 2);
    BOOST_CHECK_EQUAL(AdditiveInverse<int32_t>()(0), 0);
    BOOST_CHECK_EQUAL(AdditiveInverse<int32_t>()(2), -2);
    BOOST_CHECK_EQUAL(AdditiveInverse<int16_t>()(-2), 2);
    BOOST_CHECK_EQUAL(AdditiveInverse<int16_t>()(0), 0);
    BOOST_CHECK_EQUAL(AdditiveInverse<int16_t>()(2), -2);
    BOOST_CHECK_EQUAL(AdditiveInverse<int8_t>()(-2), 2);
    BOOST_CHECK_EQUAL(AdditiveInverse<int8_t>()(0), 0);
    BOOST_CHECK_EQUAL(AdditiveInverse<int8_t>()(2), -2);

    BOOST_CHECK_EQUAL(AdditiveInverse<bool>()(false), false);
    BOOST_CHECK_EQUAL(AdditiveInverse<bool>()(true), true);

    // different domain tests

    BOOST_CHECK_EQUAL((AdditiveInverse<double, int>()(2.2)), -2);
    BOOST_CHECK_EQUAL((AdditiveInverse<double, int>()(0.0)),  0);
    BOOST_CHECK_EQUAL((AdditiveInverse<double, int>()(-2.0)), 2);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(multiplicative_inverse_same_domain_test)
{
    BOOST_CHECK_EQUAL(MultiplicativeInverse<double>()(2.2), 1./2.2);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<double>()(-2.2), -1./2.2);

    BOOST_CHECK_EQUAL(MultiplicativeInverse<float>()(2.2f), 1.f/2.2f);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<float>()(-2.2f), -1.f/2.2f);

    BOOST_CHECK_EQUAL(MultiplicativeInverse<uint64_t>()(2UL), 0UL);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<uint32_t>()(2U), 0U);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<uint16_t>()(2), 0);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<uint8_t>()(2), 0);

    BOOST_CHECK_EQUAL(MultiplicativeInverse<int64_t>()(-2L), 0L);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<int32_t>()(-2), 0);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<int16_t>()(-2), 0);
    BOOST_CHECK_EQUAL(MultiplicativeInverse<int8_t>()(-2), 0);

    BOOST_CHECK_EQUAL(MultiplicativeInverse<bool>()(true), true);

    // divide by zero exception:
    //BOOST_CHECK_EQUAL(MultiplicativeInverse<bool>()(false), false);

    // different domain tests

    BOOST_CHECK_EQUAL((MultiplicativeInverse<int,double>()(2)),   0.5);
    BOOST_CHECK_EQUAL((MultiplicativeInverse<int,double>()(1)),   1.0);
    BOOST_CHECK_EQUAL((MultiplicativeInverse<int,double>()(-3)), -1./3.);

    BOOST_CHECK_EQUAL((MultiplicativeInverse<double,int>()(0.5)),      2);
    BOOST_CHECK_EQUAL((MultiplicativeInverse<double,int>()(1.)),       1);
    BOOST_CHECK_EQUAL((MultiplicativeInverse<double,int>()(-0.3333)), -3);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_not_same_domain_test)
{
    BOOST_CHECK_EQUAL(LogicalNot<double>()(2.2), 0.0);
    BOOST_CHECK_EQUAL(LogicalNot<double>()(0.0), 1.0);

    BOOST_CHECK_EQUAL(LogicalNot<float>()(2.2f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalNot<float>()(1.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalNot<float>()(0.0f), 1.0f);

    BOOST_CHECK_EQUAL(LogicalNot<uint64_t>()(2UL), 0UL);
    BOOST_CHECK_EQUAL(LogicalNot<uint64_t>()(0UL), 1UL);
    BOOST_CHECK_EQUAL(LogicalNot<uint32_t>()(2U), 0U);
    BOOST_CHECK_EQUAL(LogicalNot<uint32_t>()(0U), 1U);
    BOOST_CHECK_EQUAL(LogicalNot<uint16_t>()(2), 0);
    BOOST_CHECK_EQUAL(LogicalNot<uint16_t>()(0), 1);
    BOOST_CHECK_EQUAL(LogicalNot<uint8_t>()(2), 0);
    BOOST_CHECK_EQUAL(LogicalNot<uint8_t>()(0), 1);

    BOOST_CHECK_EQUAL(LogicalNot<int64_t>()(-2L), 0L);
    BOOST_CHECK_EQUAL(LogicalNot<int64_t>()(0L), 1L);
    BOOST_CHECK_EQUAL(LogicalNot<int32_t>()(-2), 0);
    BOOST_CHECK_EQUAL(LogicalNot<int32_t>()(0), 1);
    BOOST_CHECK_EQUAL(LogicalNot<int16_t>()(-2), 0);
    BOOST_CHECK_EQUAL(LogicalNot<int16_t>()(0), 1);
    BOOST_CHECK_EQUAL(LogicalNot<int8_t>()(-2), 0);
    BOOST_CHECK_EQUAL(LogicalNot<int8_t>()(0), 1);

    BOOST_CHECK_EQUAL(LogicalNot<int>()(1), 0);
    BOOST_CHECK_EQUAL(LogicalNot<int>()(0), 1);

    BOOST_CHECK_EQUAL(LogicalNot<bool>()(false), true);
    BOOST_CHECK_EQUAL(LogicalNot<bool>()(true), false);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_not_different_domain_test)
{
    /// @todo this is an incomplete set of pairs and does not cover the
    /// corner cases at the numeric limits that actually vary by platform
    BOOST_CHECK_EQUAL((LogicalNot<double,float>()(2.2)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<double,float>()(0.0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<double,uint64_t>()(2.2)), 0UL);
    BOOST_CHECK_EQUAL((LogicalNot<double,uint64_t>()(0.0)), 1UL);
    BOOST_CHECK_EQUAL((LogicalNot<double,int64_t>()(-2.2)), 0L);
    BOOST_CHECK_EQUAL((LogicalNot<double,int64_t>()(0.0)), 1L);
    BOOST_CHECK_EQUAL((LogicalNot<double,bool>()(2.2)), false);
    BOOST_CHECK_EQUAL((LogicalNot<double,bool>()(0.0)), true);

    BOOST_CHECK_EQUAL((LogicalNot<float,double>()(2.2f)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<float,double>()(0.0f)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<float,uint32_t>()(2.2f)), 0U);
    BOOST_CHECK_EQUAL((LogicalNot<float,uint32_t>()(0.0f)), 1U);
    BOOST_CHECK_EQUAL((LogicalNot<float,int32_t>()(-2.2f)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<float,int32_t>()( 0.0f)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<float,bool>()(2.2f)), false);
    BOOST_CHECK_EQUAL((LogicalNot<float,bool>()(0.0f)), true);

    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, double>()(2UL)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, double>()(0UL)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, float>()(2UL)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, float>()(0UL)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, int64_t>()(2UL)), 0L);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t, int64_t>()(0UL)), 1L);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t,uint32_t>()(2UL)), 0UL);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t,uint32_t>()(0UL)), 1UL);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t,bool>()(2UL)), false);
    BOOST_CHECK_EQUAL((LogicalNot<uint64_t,bool>()(0UL)), true);

    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, double>()(2U)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, double>()(0U)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, float>()(2U)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, float>()(0U)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,uint64_t>()(2U)), 0UL);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,uint64_t>()(0U)), 1UL);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int64_t>()(2U)), 0L);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int64_t>()(0U)), 1L);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int32_t>()(2U)), 0U);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int32_t>()(0U)), 1U);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,uint16_t>()(2U)), 0U);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,uint16_t>()(0U)), 1U);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int16_t>()(2U)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t, int16_t>()(0U)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,bool>()(2U)), false);
    BOOST_CHECK_EQUAL((LogicalNot<uint32_t,bool>()(0U)), true);

    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, double>()(2U)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, double>()(0U)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, float>()(2U)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, float>()(0U)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,uint32_t>()(2U)), 0U);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,uint32_t>()(0U)), 1U);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int32_t>()(2U)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int32_t>()(0U)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int16_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int16_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,uint8_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,uint8_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int8_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t, int8_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,bool>()(2U)), false);
    BOOST_CHECK_EQUAL((LogicalNot<uint16_t,bool>()(0U)), true);

    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,double>()(2U)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,double>()(0U)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,float>()(2U)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,float>()(0U)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,int8_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,int8_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,uint16_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,uint16_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,int16_t>()(2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,int16_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,bool>()(2U)), false);
    BOOST_CHECK_EQUAL((LogicalNot<uint8_t,bool>()(0U)), true);

    BOOST_CHECK_EQUAL((LogicalNot<int64_t,double>()(-2L)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,double>()(0L)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,float>()(-2L)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,float>()(0L)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,int32_t>()(-2L)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,int32_t>()(0L)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,int16_t>()(-2L)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,int16_t>()(0L)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,bool>()(-2L)), false);
    BOOST_CHECK_EQUAL((LogicalNot<int64_t,bool>()(0L)), true);

    BOOST_CHECK_EQUAL((LogicalNot<int32_t,double>()(-2)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,double>()(0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,float>()(-2)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,float>()(0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,int64_t>()(-2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,int64_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,int16_t>()(-2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,int16_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,bool>()(-2)), false);
    BOOST_CHECK_EQUAL((LogicalNot<int32_t,bool>()(0)), true);

    BOOST_CHECK_EQUAL((LogicalNot<int16_t,double>()(-2)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,double>()(0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,float>()(-2)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,float>()(0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,int32_t>()(-2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,int32_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,int8_t>()(-2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,int8_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,bool>()(-2)), false);
    BOOST_CHECK_EQUAL((LogicalNot<int16_t,bool>()(0)), true);

    BOOST_CHECK_EQUAL((LogicalNot<int8_t,double>()(-2)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,double>()(0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,float>()(-2)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,float>()(0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,int16_t>()(-2)), 0);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,int16_t>()(0)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,bool>()(-2)), false);
    BOOST_CHECK_EQUAL((LogicalNot<int8_t,bool>()(0)), true);

    BOOST_CHECK_EQUAL((LogicalNot<bool,double>()(false)), 1.0);
    BOOST_CHECK_EQUAL((LogicalNot<bool,double>()(true)), 0.0);
    BOOST_CHECK_EQUAL((LogicalNot<bool,float>()(false)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalNot<bool,float>()(true)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalNot<bool,uint32_t>()(false)), 1U);
    BOOST_CHECK_EQUAL((LogicalNot<bool,uint32_t>()(true)), 0U);
    BOOST_CHECK_EQUAL((LogicalNot<bool,int32_t>()(false)), 1);
    BOOST_CHECK_EQUAL((LogicalNot<bool,int32_t>()(true)), 0);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(BitwiseNot_test)
{
    bool    b   = true;

    int8_t  i8  = -8;
    int16_t i16 = -16;
    int32_t i32 = -32;
    int64_t i64 = -64;

    uint8_t  ui8  = 8;
    uint16_t ui16 = 16;
    uint32_t ui32 = 32;
    uint64_t ui64 = 64;

    // odd result for bool (but correct)
    BOOST_CHECK_EQUAL(BitwiseNot<bool>()(b), true);

    BOOST_CHECK_EQUAL(BitwiseNot<int8_t>()(i8), 7);
    BOOST_CHECK_EQUAL(BitwiseNot<int16_t>()(i16), 15);
    BOOST_CHECK_EQUAL(BitwiseNot<int32_t>()(i32), 31);
    BOOST_CHECK_EQUAL(BitwiseNot<int64_t>()(i64), 63);
    BOOST_CHECK_EQUAL(BitwiseNot<uint8_t>()(ui8),   0xf7);
    BOOST_CHECK_EQUAL(BitwiseNot<uint16_t>()(ui16), 0xffef);
    BOOST_CHECK_EQUAL(BitwiseNot<uint32_t>()(ui32), 0xffffffdf);
    BOOST_CHECK_EQUAL(BitwiseNot<uint64_t>()(ui64),
                      0xffffffffffffffbf);

    // different domains
    BOOST_CHECK_EQUAL((BitwiseNot<uint64_t,uint32_t>()(ui64)),
                      0xffffffbf);
    BOOST_CHECK_EQUAL((BitwiseNot<uint64_t,uint16_t>()(ui64)),
                      0xffbf);
    BOOST_CHECK_EQUAL((BitwiseNot<uint64_t,uint8_t>()(ui64)),
                      0xbf);
}

//****************************************************************************
// Binary Operator tests
//****************************************************************************

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_or_same_domain_test)
{
    BOOST_CHECK_EQUAL(LogicalOr<double>()(0.0, 0.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalOr<double>()(1.0, 0.0), 1.0);
    BOOST_CHECK_EQUAL(LogicalOr<double>()(0.0, 1.0), 1.0);
    BOOST_CHECK_EQUAL(LogicalOr<double>()(1.0, 1.0), 1.0);

    BOOST_CHECK_EQUAL(LogicalOr<float>()(0.0f, 0.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalOr<float>()(1.0f, 0.0f), 1.0f);
    BOOST_CHECK_EQUAL(LogicalOr<float>()(0.0f, 1.0f), 1.0f);
    BOOST_CHECK_EQUAL(LogicalOr<float>()(1.0f, 1.0f), 1.0f);

    BOOST_CHECK_EQUAL(LogicalOr<uint64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<uint64_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint64_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint64_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<uint32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<uint32_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint32_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint32_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<uint16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<uint16_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint16_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint16_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<uint8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<uint8_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint8_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<uint8_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<int64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<int64_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int64_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int64_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<int32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<int32_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int32_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int32_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<int16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<int16_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int16_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int16_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<int8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalOr<int8_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int8_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalOr<int8_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalOr<bool>()(false, false), false);
    BOOST_CHECK_EQUAL(LogicalOr<bool>()(false, true),  true);
    BOOST_CHECK_EQUAL(LogicalOr<bool>()(true, false),  true);
    BOOST_CHECK_EQUAL(LogicalOr<bool>()(true, true),   true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_or_different_domain_test)
{
    BOOST_CHECK_EQUAL((LogicalOr<int,double>()( 0, 0.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalOr<int,double>()(-1, 0.0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalOr<int,double>()( 0, -1.0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalOr<int,double>()(-1, 1.0)), 1.0);

    BOOST_CHECK_EQUAL((LogicalOr<float,int>()(0.0f, 0)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalOr<float,int>()(1.0f, 0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalOr<float,int>()(0.0f, -1)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalOr<float,int>()(1.0f, -1)), 1.0f);

    BOOST_CHECK_EQUAL((LogicalOr<float, uint64_t>()(  0.f, 0)), 0.f);
    BOOST_CHECK_EQUAL((LogicalOr<float, uint64_t>()( 0.1f, 0)), 1.f);
    BOOST_CHECK_EQUAL((LogicalOr<float, uint64_t>()(  0.f, 1)), 1.f);
    BOOST_CHECK_EQUAL((LogicalOr<float, uint64_t>()(-.05f, 1)), 1.f);

    BOOST_CHECK_EQUAL((LogicalOr<int32_t,float>()( 0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalOr<int32_t,float>()(-1, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalOr<int32_t,float>()( 0, 1.f)), 1);
    BOOST_CHECK_EQUAL((LogicalOr<int32_t,float>()(-1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalOr<double, uint16_t>()(0., 0)), 0.);
    BOOST_CHECK_EQUAL((LogicalOr<double, uint16_t>()(1., 0)), 1.);
    BOOST_CHECK_EQUAL((LogicalOr<double, uint16_t>()(0., 1)), 1.);
    BOOST_CHECK_EQUAL((LogicalOr<double, uint16_t>()(1., 1)), 1.);

    BOOST_CHECK_EQUAL((LogicalOr<uint8_t, float>()(0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalOr<uint8_t, float>()(1, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalOr<uint8_t, float>()(0, 1.f)), 1);
    BOOST_CHECK_EQUAL((LogicalOr<uint8_t, float>()(1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalOr<bool, float>()(false, 0.f)), false);
    BOOST_CHECK_EQUAL((LogicalOr<bool, float>()(true,  0.f)), true);
    BOOST_CHECK_EQUAL((LogicalOr<bool, float>()(false, 1.f)), true);
    BOOST_CHECK_EQUAL((LogicalOr<bool, float>()(true,  1.f)), true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_and_same_domain_test)
{
    BOOST_CHECK_EQUAL(LogicalAnd<double>()(0.0, 0.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalAnd<double>()(1.0, 0.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalAnd<double>()(0.0, 1.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalAnd<double>()(1.0, 1.0), 1.0);

    BOOST_CHECK_EQUAL(LogicalAnd<float>()(0.0f, 0.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalAnd<float>()(1.0f, 0.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalAnd<float>()(0.0f, 1.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalAnd<float>()(1.0f, 1.0f), 1.0f);

    BOOST_CHECK_EQUAL(LogicalAnd<uint64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint64_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint64_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint64_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<uint32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint32_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint32_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint32_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<uint16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint16_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint16_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint16_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<uint8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint8_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint8_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<uint8_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<int64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int64_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int64_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int64_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<int32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int32_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int32_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int32_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<int16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int16_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int16_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int16_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<int8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int8_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int8_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalAnd<int8_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalAnd<bool>()(false, false), false);
    BOOST_CHECK_EQUAL(LogicalAnd<bool>()(false, true),  false);
    BOOST_CHECK_EQUAL(LogicalAnd<bool>()(true, false),  false);
    BOOST_CHECK_EQUAL(LogicalAnd<bool>()(true, true),   true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_and_different_domain_test)
{
    BOOST_CHECK_EQUAL((LogicalAnd<int,double>()( 0, 0.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalAnd<int,double>()(-1, 0.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalAnd<int,double>()( 0,-1.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalAnd<int,double>()(-1, 1.0)), 1.0);

    BOOST_CHECK_EQUAL((LogicalAnd<float,int>()(0.0f,  0)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalAnd<float,int>()(1.0f,  0)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalAnd<float,int>()(0.0f, -1)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalAnd<float,int>()(1.0f, -1)), 1.0f);

    BOOST_CHECK_EQUAL((LogicalAnd<float, uint64_t>()(  0.f, 0)), 0.f);
    BOOST_CHECK_EQUAL((LogicalAnd<float, uint64_t>()( 0.1f, 0)), 0.f);
    BOOST_CHECK_EQUAL((LogicalAnd<float, uint64_t>()(  0.f, 1)), 0.f);
    BOOST_CHECK_EQUAL((LogicalAnd<float, uint64_t>()(-.05f, 1)), 1.f);

    BOOST_CHECK_EQUAL((LogicalAnd<int32_t,float>()( 0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<int32_t,float>()(-1, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<int32_t,float>()( 0, 1.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<int32_t,float>()(-1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalAnd<double, uint16_t>()(0., 0)), 0.);
    BOOST_CHECK_EQUAL((LogicalAnd<double, uint16_t>()(1., 0)), 0.);
    BOOST_CHECK_EQUAL((LogicalAnd<double, uint16_t>()(0., 1)), 0.);
    BOOST_CHECK_EQUAL((LogicalAnd<double, uint16_t>()(1., 1)), 1.);

    BOOST_CHECK_EQUAL((LogicalAnd<uint8_t, float>()(0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<uint8_t, float>()(1, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<uint8_t, float>()(0, 1.f)), 0);
    BOOST_CHECK_EQUAL((LogicalAnd<uint8_t, float>()(1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalAnd<bool, float>()(false, 0.f)), false);
    BOOST_CHECK_EQUAL((LogicalAnd<bool, float>()(true,  0.f)), false);
    BOOST_CHECK_EQUAL((LogicalAnd<bool, float>()(false, 1.f)), false);
    BOOST_CHECK_EQUAL((LogicalAnd<bool, float>()(true,  1.f)), true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_xor_same_domain_test)
{
    BOOST_CHECK_EQUAL(LogicalXor<double>()(0.0, 0.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalXor<double>()(1.0, 0.0), 1.0);
    BOOST_CHECK_EQUAL(LogicalXor<double>()(0.0, 1.0), 1.0);
    BOOST_CHECK_EQUAL(LogicalXor<double>()(1.0, 1.0), 0.0);

    BOOST_CHECK_EQUAL(LogicalXor<float>()(0.0f, 0.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalXor<float>()(1.0f, 0.0f), 1.0f);
    BOOST_CHECK_EQUAL(LogicalXor<float>()(0.0f, 1.0f), 1.0f);
    BOOST_CHECK_EQUAL(LogicalXor<float>()(1.0f, 1.0f), 0.0f);

    BOOST_CHECK_EQUAL(LogicalXor<uint64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<uint64_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint64_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint64_t>()(1, 1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<uint32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<uint32_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint32_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint32_t>()(1, 1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<uint16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<uint16_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint16_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint16_t>()(1, 1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<uint8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<uint8_t>()(1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint8_t>()(0, 1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<uint8_t>()(1, 1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<int64_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<int64_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int64_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int64_t>()(-1, -1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<int32_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<int32_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int32_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int32_t>()(-1, -1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<int16_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<int16_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int16_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int16_t>()(-1, -1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<int8_t>()(0, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXor<int8_t>()(-1, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int8_t>()(0, -1), 1);
    BOOST_CHECK_EQUAL(LogicalXor<int8_t>()(-1, -1), 0);

    BOOST_CHECK_EQUAL(LogicalXor<bool>()(false, false), false);
    BOOST_CHECK_EQUAL(LogicalXor<bool>()(false, true),  true);
    BOOST_CHECK_EQUAL(LogicalXor<bool>()(true, false),  true);
    BOOST_CHECK_EQUAL(LogicalXor<bool>()(true, true),   false);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_xor_different_domain_test)
{
    BOOST_CHECK_EQUAL((LogicalXor<int,double>()( 0, 0.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalXor<int,double>()(-1, 0.0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalXor<int,double>()( 0,-1.0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalXor<int,double>()(-1, 1.0)), 0.0);

    BOOST_CHECK_EQUAL((LogicalXor<float,int>()(0.0f,  0)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalXor<float,int>()(1.0f,  0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalXor<float,int>()(0.0f, -1)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalXor<float,int>()(1.0f, -1)), 0.0f);

    BOOST_CHECK_EQUAL((LogicalXor<float, uint64_t>()(  0.f, 0)), 0.f);
    BOOST_CHECK_EQUAL((LogicalXor<float, uint64_t>()( 0.1f, 0)), 1.f);
    BOOST_CHECK_EQUAL((LogicalXor<float, uint64_t>()(  0.f, 1)), 1.f);
    BOOST_CHECK_EQUAL((LogicalXor<float, uint64_t>()(-.05f, 1)), 0.f);

    BOOST_CHECK_EQUAL((LogicalXor<int32_t,float>()( 0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXor<int32_t,float>()(-1, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXor<int32_t,float>()( 0, 1.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXor<int32_t,float>()(-1, 1.f)), 0);

    BOOST_CHECK_EQUAL((LogicalXor<double, uint16_t>()(0., 0)), 0.);
    BOOST_CHECK_EQUAL((LogicalXor<double, uint16_t>()(1., 0)), 1.);
    BOOST_CHECK_EQUAL((LogicalXor<double, uint16_t>()(0., 1)), 1.);
    BOOST_CHECK_EQUAL((LogicalXor<double, uint16_t>()(1., 1)), 0.);

    BOOST_CHECK_EQUAL((LogicalXor<uint8_t, float>()(0, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXor<uint8_t, float>()(1, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXor<uint8_t, float>()(0, 1.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXor<uint8_t, float>()(1, 1.f)), 0);

    BOOST_CHECK_EQUAL((LogicalXor<bool, float>()(false, 0.f)), false);
    BOOST_CHECK_EQUAL((LogicalXor<bool, float>()(true,  0.f)),  true);
    BOOST_CHECK_EQUAL((LogicalXor<bool, float>()(false, 1.f)),  true);
    BOOST_CHECK_EQUAL((LogicalXor<bool, float>()(true,  1.f)), false);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_xnor_same_domain_test)
{
    BOOST_CHECK_EQUAL(LogicalXnor<double>()(0.0, 0.0), 1.0);
    BOOST_CHECK_EQUAL(LogicalXnor<double>()(1.0, 0.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalXnor<double>()(0.0, 1.0), 0.0);
    BOOST_CHECK_EQUAL(LogicalXnor<double>()(1.0, 1.0), 1.0);

    BOOST_CHECK_EQUAL(LogicalXnor<float>()(0.0f, 0.0f), 1.0f);
    BOOST_CHECK_EQUAL(LogicalXnor<float>()(1.0f, 0.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalXnor<float>()(0.0f, 1.0f), 0.0f);
    BOOST_CHECK_EQUAL(LogicalXnor<float>()(1.0f, 1.0f), 1.0f);

    BOOST_CHECK_EQUAL(LogicalXnor<uint64_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<uint64_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint64_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint64_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<uint32_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<uint32_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint32_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint32_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<uint16_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<uint16_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint16_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint16_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<uint8_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<uint8_t>()(1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint8_t>()(0, 1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<uint8_t>()(1, 1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<int64_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<int64_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int64_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int64_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<int32_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<int32_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int32_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int32_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<int16_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<int16_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int16_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int16_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<int8_t>()(0, 0), 1);
    BOOST_CHECK_EQUAL(LogicalXnor<int8_t>()(-1, 0), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int8_t>()(0, -1), 0);
    BOOST_CHECK_EQUAL(LogicalXnor<int8_t>()(-1, -1), 1);

    BOOST_CHECK_EQUAL(LogicalXnor<bool>()(false, false), true);
    BOOST_CHECK_EQUAL(LogicalXnor<bool>()(false, true), false);
    BOOST_CHECK_EQUAL(LogicalXnor<bool>()(true, false), false);
    BOOST_CHECK_EQUAL(LogicalXnor<bool>()(true, true),   true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(logical_xnor_different_domain_test)
{
    BOOST_CHECK_EQUAL((LogicalXnor<int,double>()( 0, 0.0)), 1.0);
    BOOST_CHECK_EQUAL((LogicalXnor<int,double>()(-1, 0.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalXnor<int,double>()( 0,-1.0)), 0.0);
    BOOST_CHECK_EQUAL((LogicalXnor<int,double>()(-1, 1.0)), 1.0);

    BOOST_CHECK_EQUAL((LogicalXnor<float,int>()(0.0f,  0)), 1.0f);
    BOOST_CHECK_EQUAL((LogicalXnor<float,int>()(1.0f,  0)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalXnor<float,int>()(0.0f, -1)), 0.0f);
    BOOST_CHECK_EQUAL((LogicalXnor<float,int>()(1.0f, -1)), 1.0f);

    BOOST_CHECK_EQUAL((LogicalXnor<float, uint64_t>()(  0.f, 0)), 1.f);
    BOOST_CHECK_EQUAL((LogicalXnor<float, uint64_t>()( 0.1f, 0)), 0.f);
    BOOST_CHECK_EQUAL((LogicalXnor<float, uint64_t>()(  0.f, 1)), 0.f);
    BOOST_CHECK_EQUAL((LogicalXnor<float, uint64_t>()(-.05f, 1)), 1.f);

    BOOST_CHECK_EQUAL((LogicalXnor<int32_t,float>()( 0, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXnor<int32_t,float>()(-1, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXnor<int32_t,float>()( 0, 1.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXnor<int32_t,float>()(-1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalXnor<double, uint16_t>()(0., 0)), 1.);
    BOOST_CHECK_EQUAL((LogicalXnor<double, uint16_t>()(1., 0)), 0.);
    BOOST_CHECK_EQUAL((LogicalXnor<double, uint16_t>()(0., 1)), 0.);
    BOOST_CHECK_EQUAL((LogicalXnor<double, uint16_t>()(1., 1)), 1.);

    BOOST_CHECK_EQUAL((LogicalXnor<uint8_t, float>()(0, 0.f)), 1);
    BOOST_CHECK_EQUAL((LogicalXnor<uint8_t, float>()(1, 0.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXnor<uint8_t, float>()(0, 1.f)), 0);
    BOOST_CHECK_EQUAL((LogicalXnor<uint8_t, float>()(1, 1.f)), 1);

    BOOST_CHECK_EQUAL((LogicalXnor<bool, float>()(false, 0.f)), true);
    BOOST_CHECK_EQUAL((LogicalXnor<bool, float>()(true,  0.f)), false);
    BOOST_CHECK_EQUAL((LogicalXnor<bool, float>()(false, 1.f)), false);
    BOOST_CHECK_EQUAL((LogicalXnor<bool, float>()(true,  1.f)), true);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(bitwise_or_test)
{
    //BOOST_CHECK_EQUAL(BitwiseOr<float>()(1.0f, 0.2f), 0.3f); // doesn't compile
    BOOST_CHECK_EQUAL(BitwiseOr<    bool>()(true, false), true);
    BOOST_CHECK_EQUAL(BitwiseOr< uint8_t>()(0x33, 0x3c), 0x03f);
    BOOST_CHECK_EQUAL(BitwiseOr<uint16_t>()(0x00ff, 0x0f0f), 0x0fff);
    BOOST_CHECK_EQUAL(BitwiseOr<uint32_t>()(0x00ff00ff,
                                            0x0f0f0f0f), 0x0fff0fff);
    BOOST_CHECK_EQUAL(BitwiseOr<uint64_t>()(0x00000000ffffffff,
                                            0x0000ffff0000ffff),
                      0x0000ffffffffffff);
    BOOST_CHECK_EQUAL(BitwiseOr< int8_t>()(0x33, 0x3c), 0x03f);
    BOOST_CHECK_EQUAL(BitwiseOr<int16_t>()(0x00ff, 0x0f0f), 0x0fff);
    BOOST_CHECK_EQUAL(BitwiseOr<int32_t>()(0x00ff00ff,
                                           0x0f0f0f0f), 0x0fff0fff);
    BOOST_CHECK_EQUAL(BitwiseOr<int64_t>()(0x00000000ffffffff,
                                           0x0000ffff0000ffff),
                      0x0000ffffffffffff);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(bitwise_and_test)
{
    BOOST_CHECK_EQUAL(BitwiseAnd<    bool>()(true, false), false);
    BOOST_CHECK_EQUAL(BitwiseAnd< uint8_t>()(0x33, 0x3c), 0x30);
    BOOST_CHECK_EQUAL(BitwiseAnd<uint16_t>()(0x00ff, 0x0f0f), 0x000f);
    BOOST_CHECK_EQUAL(BitwiseAnd<uint32_t>()(0x00ff00ff,
                                             0x0f0f0f0f), 0x000f000f);
    BOOST_CHECK_EQUAL(BitwiseAnd<uint64_t>()(0x00000000ffffffff,
                                             0x0000ffff0000ffff),
                      0x000000000000ffff);
    BOOST_CHECK_EQUAL(BitwiseAnd< int8_t>()(0x33, 0x3c), 0x30);
    BOOST_CHECK_EQUAL(BitwiseAnd<int16_t>()(0x00ff, 0x0f0f), 0x000f);
    BOOST_CHECK_EQUAL(BitwiseAnd<int32_t>()(0x00ff00ff,
                                            0x0f0f0f0f), 0x000f000f);
    BOOST_CHECK_EQUAL(BitwiseAnd<int64_t>()(0x00000000ffffffff,
                                            0x0000ffff0000ffff),
                      0x000000000000ffff);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(bitwise_xor_test)
{
    BOOST_CHECK_EQUAL(BitwiseXor<    bool>()(true, false), true);
    BOOST_CHECK_EQUAL(BitwiseXor< uint8_t>()(0x33, 0x3c), 0x0f);
    BOOST_CHECK_EQUAL(BitwiseXor<uint16_t>()(0x00ff, 0x0f0f), 0x0ff0);
    BOOST_CHECK_EQUAL(BitwiseXor<uint32_t>()(0x00ff00ff,
                                             0x0f0f0f0f), 0x0ff00ff0);
    BOOST_CHECK_EQUAL(BitwiseXor<uint64_t>()(0x00000000ffffffff,
                                             0x0000ffff0000ffff),
                      0x0000ffffffff0000);
    BOOST_CHECK_EQUAL(BitwiseXor< int8_t>()(0x33, 0x3c), 0x0f);
    BOOST_CHECK_EQUAL(BitwiseXor<int16_t>()(0x00ff, 0x0f0f), 0x0ff0);
    BOOST_CHECK_EQUAL(BitwiseXor<int32_t>()(0x00ff00ff,
                                            0x0f0f0f0f), 0x0ff00ff0);
    BOOST_CHECK_EQUAL(BitwiseXor<int64_t>()(0x00000000ffffffff,
                                            0x0000ffff0000ffff),
                      0x0000ffffffff0000);
}

//****************************************************************************
BOOST_AUTO_TEST_CASE(bitwise_xnor_test)
{
    //weird but true
    BOOST_CHECK_EQUAL(BitwiseXnor<    bool>()(true, false), true);

    BOOST_CHECK_EQUAL(BitwiseXnor< uint8_t>()(0x33, 0x3c), 0xf0);
    BOOST_CHECK_EQUAL(BitwiseXnor<uint16_t>()(0x00ff, 0x0f0f), 0xf00f);
    BOOST_CHECK_EQUAL(BitwiseXnor<uint32_t>()(0x00ff00ff,
                                              0x0f0f0f0f), 0xf00ff00f);
    BOOST_CHECK_EQUAL(BitwiseXnor<uint64_t>()(0x00000000ffffffff,
                                              0x0000ffff0000ffff),
                      0xffff00000000ffff);
    BOOST_CHECK_EQUAL(BitwiseXnor< int8_t>()(0x33, 0x3c), (int8_t)0xf0);
    BOOST_CHECK_EQUAL(BitwiseXnor<int16_t>()(0x00ff, 0x0f0f), (int16_t)0xf00f);
    BOOST_CHECK_EQUAL(BitwiseXnor<int32_t>()(0x00ff00ff,
                                             0x0f0f0f0f), 0xf00ff00f);
    BOOST_CHECK_EQUAL(BitwiseXnor<int64_t>()(0x00000000ffffffff,
                                             0x0000ffff0000ffff),
                      0xffff00000000ffff);
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: KIwabuchi/gbtl

max_issues_repo_name: KIwabuchi/gbtl

max_forks_repo_name: KIwabuchi/gbtl


text:
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
//  (C) Copyright Eric Friedman 2002-2003.
//  (C) Copyright Antony Polukhin 2013.
//  Use, modification and distribution are subject to the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt).
//
//  See http://www.boost.org/libs/type_traits for most recent version including documentation.

#ifndef BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED
#define BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED

#include <cstddef> // size_t
#include <boost/config.hpp>
#include <boost/type_traits/intrinsics.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type_traits/is_complete.hpp>
#include <boost/static_assert.hpp>

#ifdef BOOST_IS_NOTHROW_MOVE_CONSTRUCT

namespace boost {

template <class T>
struct is_nothrow_move_constructible : public integral_constant<bool, BOOST_IS_NOTHROW_MOVE_CONSTRUCT(T)>
{
   BOOST_STATIC_ASSERT_MSG(boost::is_complete<T>::value, "Arguments to is_nothrow_move_constructible must be complete types");
};

template <class T> struct is_nothrow_move_constructible<volatile T> : public ::boost::false_type {};
template <class T> struct is_nothrow_move_constructible<const volatile T> : public ::boost::false_type{};

#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)

#include <boost/type_traits/declval.hpp>
#include <boost/type_traits/enable_if.hpp>

namespace boost{ namespace detail{

template <class T, class Enable = void>
struct false_or_cpp11_noexcept_move_constructible: public ::boost::false_type {};

template <class T>
struct false_or_cpp11_noexcept_move_constructible <
        T,
        typename ::boost::enable_if_<sizeof(T) && BOOST_NOEXCEPT_EXPR(T(::boost::declval<T>()))>::type
    > : public ::boost::integral_constant<bool, BOOST_NOEXCEPT_EXPR(T(::boost::declval<T>()))>
{};

}

template <class T> struct is_nothrow_move_constructible
   : public integral_constant<bool, ::boost::detail::false_or_cpp11_noexcept_move_constructible<T>::value>
{
   BOOST_STATIC_ASSERT_MSG(boost::is_complete<T>::value, "Arguments to is_nothrow_move_constructible must be complete types");
};

template <class T> struct is_nothrow_move_constructible<volatile T> : public ::boost::false_type {};
template <class T> struct is_nothrow_move_constructible<const volatile T> : public ::boost::false_type{};
template <class T, std::size_t N> struct is_nothrow_move_constructible<T[N]> : public ::boost::false_type{};
template <class T> struct is_nothrow_move_constructible<T[]> : public ::boost::false_type{};

#else

#include <boost/type_traits/has_trivial_move_constructor.hpp>
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/type_traits/is_array.hpp>

namespace boost{

template <class T>
struct is_nothrow_move_constructible
   : public integral_constant<bool,
   (::boost::has_trivial_move_constructor<T>::value || ::boost::has_nothrow_copy<T>::value) && !::boost::is_array<T>::value>
{
   BOOST_STATIC_ASSERT_MSG(boost::is_complete<T>::value, "Arguments to is_nothrow_move_constructible must be complete types");
};

#endif

template <> struct is_nothrow_move_constructible<void> : false_type{};
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
template <> struct is_nothrow_move_constructible<void const> : false_type{};
template <> struct is_nothrow_move_constructible<void volatile> : false_type{};
template <> struct is_nothrow_move_constructible<void const volatile> : false_type{};
#endif
// References are always trivially constructible, even if the thing they reference is not:
template <class T> struct is_nothrow_move_constructible<T&> : public ::boost::true_type{};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T> struct is_nothrow_move_constructible<T&&> : public ::boost::true_type{};
#endif

} // namespace boost

#endif // BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED

ext: hpp

max_stars_repo_name: jason-fox/Fast-RTPS

max_issues_repo_name: jason-fox/Fast-RTPS

max_forks_repo_name: jason-fox/Fast-RTPS


text: #include <boost/property_tree/xml_parser.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text: #include <boost/mpl/aux_/preprocessed/no_ttp/map.hpp>


text:
/*
 * patSampleChoiceSetWithRandomWalk.cc
 *
 *  Created on: Jun 26, 2012
 *      Author: jchen
 */

#include "patSampleChoiceSetWithRandomWalk.h"
#include "patNBParameters.h"
#include "patDisplay.h"
#include "patOd.h"
#include <boost/lexical_cast.hpp>
#include <set>
#include <unistd.h>

patSampleChoiceSetWithRandomWalk::patSampleChoiceSetWithRandomWalk() {
	// TODO Auto-generated constructor stub

}

patSampleChoiceSetWithRandomWalk::~patSampleChoiceSetWithRandomWalk() {
	// TODO Auto-generated destructor stub
}

void patSampleChoiceSetWithRandomWalk::sampleChoiceSet(
		RWPathGenerator* path_generator, string folder) {

	const string choice_set_folder = folder + "/"
			+ patNBParameters::the()->choiceSetFolder + "/";

	int num_threads = patNBParameters::the()->nbrOfThreads;
	if (m_observations.size() <= num_threads) {
		num_threads = m_observations.size();
	}
	const int num_blocks = ceil((double) m_observations.size() / num_threads);
	DEBUG_MESSAGE(
			"threads: " << num_threads << ", " << "blocks: " << num_blocks << ", obs:" << m_observations.size());

	DEBUG_MESSAGE("path generators and networks cloned");
#pragma omp parallel num_threads( num_threads)

	{
#pragma omp for

		for (int j = 0; j < m_observations.size(); ++j) {
			patNetworkBase* cloned_network =
					path_generator->getNetwork()->clone();

			RWPathGenerator* generator_clone = path_generator->clone();
			generator_clone->setNetwork(cloned_network);

			m_observations.at(j).sampleChoiceSet(path_generator,
					choice_set_folder);
			delete generator_clone;
			generator_clone = NULL;
			delete cloned_network;
			cloned_network = NULL;
		}
	}
}
void patSampleChoiceSetWithRandomWalk::addObservation(patObservation& obs) {
	/**
	 * Get relevant OD first.
	 */
	if (obs.getId() == string("")) {
		obs.setId(boost::lexical_cast<string>(m_observations.size()));
	}

	map<const patMultiModalPath, double> path_probas =
			obs.getNormalizedPathProbas();
	set<patOd> od_set;

	unsigned long obs_id = 1;
	for (map<const patMultiModalPath, double>::const_iterator path_iter =
			path_probas.begin(); path_iter != path_probas.end(); ++path_iter) {
		patOd the_od(path_iter->first.getUpNode(),
				path_iter->first.getDownNode());
		pair<set<patOd>::const_iterator, bool> insert_result = od_set.insert(
				the_od);
		if (insert_result.second == true) {
			patObservation new_obs;
			new_obs.setId(
					obs.getId() + string("_")
							+ boost::lexical_cast<string>(obs_id));
			new_obs.addPath(path_iter->first, path_iter->second);
			m_observations.push_back(new_obs);
			++obs_id;
		}
	}
}

ext: cc

max_stars_repo_name: godosou/smaroute

max_issues_repo_name: godosou/smaroute

max_forks_repo_name: godosou/smaroute


text:
/*
    Copyright (c) 2020-2021 Xavier Leclercq
    Released under the MIT License
    See https://github.com/Ishiko-cpp/FileSystem/blob/master/LICENSE.txt
*/

#include "UtilitiesTests.h"
#include "Ishiko/FileSystem/Utilities.h"
#include "Ishiko/FileSystem/ErrorCategory.h"
#include <boost/filesystem/operations.hpp>

using namespace Ishiko;
using namespace Ishiko::FileSystem;
using namespace Ishiko::Tests;

UtilitiesTests::UtilitiesTests(const TestNumber& number, const TestEnvironment& environment)
    : TestSequence(number, "Utilities tests", environment)
{
    append<HeapAllocationErrorsTest>("Exists test 1", ExistsTest1);
    append<HeapAllocationErrorsTest>("Exists test 2", ExistsTest2);
    append<HeapAllocationErrorsTest>("Exists test 3", ExistsTest3);
    append<HeapAllocationErrorsTest>("GetFileSize test 1", GetFileSizeTest1);
    append<HeapAllocationErrorsTest>("GetFileSize test 2", GetFileSizeTest2);
    append<HeapAllocationErrorsTest>("IsDirectory test 1", IsDirectoryTest1);
    append<HeapAllocationErrorsTest>("IsDirectory test 2", IsDirectoryTest2);
    append<HeapAllocationErrorsTest>("IsDirectory test 3", IsDirectoryTest3);
    append<HeapAllocationErrorsTest>("IsEmpty test 1", IsEmptyTest1);
    append<HeapAllocationErrorsTest>("IsEmpty test 2", IsEmptyTest2);
    append<HeapAllocationErrorsTest>("IsEmpty test 3", IsEmptyTest3);
    append<HeapAllocationErrorsTest>("IsEmpty test 4", IsEmptyTest4);
    append<HeapAllocationErrorsTest>("IsEmpty test 5", IsEmptyTest5);
    append<HeapAllocationErrorsTest>("ToAbsolutePath test 1", ToAbsolutePathTest1);
    append<HeapAllocationErrorsTest>("ToAbsolutePath test 2", ToAbsolutePathTest2);
    append<HeapAllocationErrorsTest>("CreateEmptyFile test 1", CreateEmptyFileTest1);
    append<HeapAllocationErrorsTest>("CreateEmptyFile test 2", CreateEmptyFileTest2);
    append<HeapAllocationErrorsTest>("ReadFile test 1", ReadFileTest1);
    append<HeapAllocationErrorsTest>("ReadFile test 2", ReadFileTest2);
    append<HeapAllocationErrorsTest>("ReadFile test 3", ReadFileTest3);
    append<HeapAllocationErrorsTest>("ReadFile test 4", ReadFileTest4);
    append<HeapAllocationErrorsTest>("ReadFile test 5", ReadFileTest5);
    append<HeapAllocationErrorsTest>("ReadFile test 6", ReadFileTest6);
    append<HeapAllocationErrorsTest>("ReadFile test 7", ReadFileTest7);
#if ISHIKO_OS == ISHIKO_OS_WINDOWS
    append<HeapAllocationErrorsTest>("GetVolumeList test 1", GetVolumeListTest1);
#endif
}

void UtilitiesTests::ExistsTest1(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    ISHTF_FAIL_IF(Exists(inputPath.string().c_str()));
    ISHTF_PASS();
}

void UtilitiesTests::ExistsTest2(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    ISHTF_FAIL_IF_NOT(Exists(inputPath.string().c_str()));
    ISHTF_PASS();
}

void UtilitiesTests::ExistsTest3(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataDirectory());

    ISHTF_FAIL_IF_NOT(Exists(inputPath.string().c_str()));
    ISHTF_PASS();
}

void UtilitiesTests::GetFileSizeTest1(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    size_t fileSize = GetFileSize(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NEQ(fileSize, 5);
    ISHTF_PASS();
}

void UtilitiesTests::GetFileSizeTest2(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Error error;
    size_t fileSize = GetFileSize(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(error.condition().value(), FileSystem::ErrorCategory::eNotFound);
    ISHTF_FAIL_IF_NEQ(fileSize, 0);
    ISHTF_PASS();
}

void UtilitiesTests::IsDirectoryTest1(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataDirectory());

    Error error;
    bool isDir = IsDirectory(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NOT(isDir);
    ISHTF_PASS();
}

void UtilitiesTests::IsDirectoryTest2(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    bool isDir = IsDirectory(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF(isDir);
    ISHTF_PASS();
}

void UtilitiesTests::IsDirectoryTest3(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Error error;
    bool isDir = IsDirectory(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(error.condition().value(), FileSystem::ErrorCategory::eNotFound);
    ISHTF_FAIL_IF(isDir);
    ISHTF_PASS();
}

void UtilitiesTests::IsEmptyTest1(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("empty.txt"));

    Error error;
    bool empty = IsEmpty(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NOT(empty);
    ISHTF_PASS();
}

void UtilitiesTests::IsEmptyTest2(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    bool empty = IsEmpty(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF(empty);
    ISHTF_PASS();
}

void UtilitiesTests::IsEmptyTest3(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestOutputPath("empty"));
    boost::filesystem::create_directory(inputPath);

    Ishiko::Error error;
    bool empty = IsEmpty(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NOT(empty);
    ISHTF_PASS();
}

void UtilitiesTests::IsEmptyTest4(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataDirectory());

    Ishiko::Error error;
    bool empty = IsEmpty(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF(empty);
    ISHTF_PASS();
}

void UtilitiesTests::IsEmptyTest5(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Ishiko::Error error;
    bool empty = IsEmpty(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(error.condition().value(), Ishiko::FileSystem::ErrorCategory::eNotFound);
    ISHTF_FAIL_IF(empty);
    ISHTF_PASS();
}

void UtilitiesTests::ToAbsolutePathTest1(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    std::string currentPath = boost::filesystem::current_path().string();
#ifdef WIN32
    currentPath += "\\";
#else
    currentPath += "/";
#endif

    std::string absolutePath;
    ToAbsolutePath(inputPath.string().c_str(), absolutePath);

    ISHTF_FAIL_IF_NEQ(absolutePath, currentPath + inputPath.string());
    ISHTF_PASS();
}

void UtilitiesTests::ToAbsolutePathTest2(Ishiko::Tests::Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    std::string currentPath = boost::filesystem::current_path().string();
#ifdef WIN32
    currentPath += "\\";
#else
    currentPath += "/";
#endif

    std::string absolutePath;
    ToAbsolutePath(inputPath.string(), absolutePath);

    ISHTF_FAIL_IF_NEQ(absolutePath, currentPath + inputPath.string());
    ISHTF_PASS();
}

void UtilitiesTests::CreateEmptyFileTest1(Test& test)
{
    boost::filesystem::path outputPath = test.environment().getTestOutputPath("file1.txt");

    Ishiko::Error error;
    CreateEmptyFile(outputPath, error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NOT(Exists(outputPath));
    ISHTF_PASS();
}

void UtilitiesTests::CreateEmptyFileTest2(Test& test)
{
    boost::filesystem::path outputPath = test.environment().getTestOutputPath("file2.txt");

    Error error;
    CreateEmptyFile(outputPath, error);

    ISHTF_ABORT_IF(error);

    CreateEmptyFile(outputPath, error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(error.condition().value(), FileSystem::ErrorCategory::eAlreadyExists);
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest1(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    const int bufferSize = 10;
    char buffer[bufferSize];
    size_t bytesRead = ReadFile(inputPath.string().c_str(), buffer, bufferSize, error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NEQ(bytesRead, 5);
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest2(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Error error;
    const int bufferSize = 10;
    char buffer[bufferSize];
    size_t bytesRead = ReadFile(inputPath.string().c_str(), buffer, bufferSize, error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(bytesRead, 0);
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest3(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    const int bufferSize = 2;
    char buffer[bufferSize];
    size_t bytesRead = ReadFile(inputPath.string().c_str(), buffer, bufferSize, error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(error.condition().value(), FileSystem::ErrorCategory::eBufferOverflow);
    ISHTF_FAIL_IF_NEQ(bytesRead, 5);
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest4(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    std::string bytes = ReadFile(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NEQ(bytes, "hello");
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest5(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Error error;
    std::string bytes = ReadFile(inputPath.string().c_str(), error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(bytes, "");
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest6(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("file1.txt"));

    Error error;
    std::string bytes = ReadFile(inputPath, error);

    ISHTF_FAIL_IF(error);
    ISHTF_FAIL_IF_NEQ(bytes, "hello");
    ISHTF_PASS();
}

void UtilitiesTests::ReadFileTest7(Test& test)
{
    boost::filesystem::path inputPath(test.environment().getTestDataPath("doesnotexist"));

    Error error;
    std::string bytes = ReadFile(inputPath, error);

    ISHTF_FAIL_IF_NOT(error);
    ISHTF_FAIL_IF_NEQ(bytes, "");
    ISHTF_PASS();
}

#if ISHIKO_OS == ISHIKO_OS_WINDOWS
void UtilitiesTests::GetVolumeListTest1(Ishiko::Tests::Test& test)
{
    Ishiko::Error error;
    std::vector<std::string> volumeNames;
    GetVolumeList(volumeNames, error);

    ISHTF_FAIL_IF(error);
    ISHTF_ABORT_IF_NOT(volumeNames.size() >= 1);

    for (const std::string& volumeName : volumeNames)
    {
        DWORD volumePathNamesLength = 5 * (MAX_PATH + 1) + 1;
        char* volumePathNames = new char[volumePathNamesLength];
        if (GetVolumePathNamesForVolumeNameA(volumeName.c_str(), volumePathNames, volumePathNamesLength,
            &volumePathNamesLength))
        {
            if ((volumePathNamesLength != 0) && (volumePathNames[0] != 0) && (strcmp(volumePathNames, "C:\\") == 0))
            {
                ISHTF_PASS();
            }
        }
        delete[] volumePathNames;
    }
}
#endif

ext: cpp

max_stars_repo_name: codesmithyide/FileSystem

max_issues_repo_name: codesmithyide/FileSystem

max_forks_repo_name: codesmithyide/FileSystem


text:
/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <linux/major.h>
#include <linux/raid/md_p.h>
#include <linux/raid/md_u.h>

#include <fstream>
#include <memory>
#include <numeric>

#include <boost/algorithm/string/trim.hpp>

#include <osquery/core/conversions.h>
#include <osquery/filesystem.h>
#include <osquery/logger.h>

#include "osquery/events/linux/udev.h"
#include "osquery/tables/system/linux/md_tables.h"

namespace osquery {
namespace tables {

const std::string kMDStatPath = "/proc/mdstat";

/**
 * @brief Removes prefixing and suffixing character from each string in vector
 *
 * @param strs reference to vector of target strings
 *
 */
static inline void trimStrs(std::vector<std::string>& strs) {
  for (auto& s : strs) {
    boost::algorithm::trim(s);
  }
}

/**
 * @brief reads mdstat file and parses as vector of lines
 *
 * @param lines reference to vector of strings to store lines in
 *
 * Trims all white space in lines and ignores empty lines (i.e. only spaces,
 * tabs, etc.)
 */
static inline void getLines(std::vector<std::string>& lines) {
  if (!pathExists(kMDStatPath).ok()) {
    return;
  }

  std::string content;
  if (!readFile(kMDStatPath, content).ok()) {
    return;
  }

  lines = split(content, "\n");
  trimStrs(lines);
}

/**
 * @brief function for walking thru a udev subsystem and working on devices
 *
 * @param systemName the name of the sysfs subsytem to work with
 * @param f function to execute on the subsystem; returns true if can break the
 * device loop, false to keep walking
 *
 */
void walkUdevDevices(const std::string& systemName,
                     std::function<bool(udev_device* const&)> f) {
  auto delUdev = [](udev* u) { udev_unref(u); };
  std::unique_ptr<udev, decltype(delUdev)> handle(udev_new(), delUdev);
  if (handle.get() == nullptr) {
    LOG(ERROR) << "Could not get udev handle";
    return;
  }

  auto delUdevEnum = [](udev_enumerate* e) { udev_enumerate_unref(e); };
  std::unique_ptr<udev_enumerate, decltype(delUdevEnum)> udevEnum(
      udev_enumerate_new(handle.get()), delUdevEnum);
  if (udevEnum.get() == nullptr) {
    LOG(ERROR) << "Could not get enumerate handle";
    return;
  }

  udev_enumerate_add_match_subsystem(udevEnum.get(), systemName.c_str());
  udev_enumerate_scan_devices(udevEnum.get());
  udev_list_entry* device_entries =
      udev_enumerate_get_list_entry(udevEnum.get());

  udev_list_entry* entry;
  udev_list_entry_foreach(entry, device_entries) {
    const char* path = udev_list_entry_get_name(entry);

    auto delUdevDevice = [](udev_device* d) { udev_device_unref(d); };
    std::unique_ptr<udev_device, decltype(delUdevDevice)> device(
        udev_device_new_from_syspath(handle.get(), path), delUdevDevice);
    if (device.get() == nullptr) {
      LOG(ERROR) << "Could not get udev device handle";
      continue;
    }
    if (f(device.get()) == true) {
      break;
    }
  }
}

std::string MD::getPathByDevName(const std::string& name) {
  std::string devPath;

  walkUdevDevices("block", [&](udev_device* const& device) {
    const char* devName = udev_device_get_property_value(device, "DEVNAME");

    if (name.compare(
            strlen(devName) - name.length(), std::string::npos, devName) == 0) {
      devPath = devName;
      if (devPath.find('/') != 0) {
        devPath = "/dev/" + devPath;
      }

      return true;
    }

    return false;
  });

  return devPath;
}

std::string MD::getDevName(int major, int minor) {
  std::string devName = "unknown";

  walkUdevDevices("block", [&](udev_device* const& device) {
    const char* devMajor = udev_device_get_property_value(device, "MAJOR");
    const char* devMinor = udev_device_get_property_value(device, "MINOR");

    if (std::stoi(devMajor) == major && std::stoi(devMinor) == minor) {
      devName = udev_device_get_property_value(device, "DEVNAME");
      return true;
    }

    return false;
  });

  return devName;
}

std::string MD::getSuperblkVersion(const std::string& arrayName) {
  std::string version;

  walkUdevDevices("block", [&](udev_device* const& device) {
    const char* devName = udev_device_get_property_value(device, "DEVNAME");

    if (arrayName.compare(strlen(devName) - arrayName.length(),
                          std::string::npos,
                          devName) == 0) {
      version = udev_device_get_property_value(device, "MD_METADATA");
      return true;
    }

    return false;
  });

  return version;
}

/**
 * @brief resolves MD disk state field to string representation
 *
 * @param  state state field of mdu_disk_info_t
 *
 * @return stringified state
 */
std::string getDiskStateStr(int state) {
  // If state is 0, which is undefined, we assume recoverying, as this is all
  // have seen in the wild
  if (state == 0) {
    return "recovering";
  }

  std::string s;

  std::map<int, std::string> possibleStates = {
#ifdef MD_DISK_FAULTY
      {MD_DISK_FAULTY, "faulty "},
#endif
#ifdef MD_DISK_ACTIVE
      {MD_DISK_ACTIVE, "active "},
#endif
#ifdef MD_DISK_SYNC
      {MD_DISK_SYNC, "sync "},
#endif
#ifdef MD_DISK_REMOVED
      {MD_DISK_REMOVED, "removed "},
#endif
#ifdef MD_DISK_WRITEMOSTLY
      {MD_DISK_WRITEMOSTLY, "writemostly "},
#endif
#ifdef MD_DISK_FAILFAST
      {MD_DISK_FAILFAST, "failfast "},
#endif
#ifdef MD_DISK_JOURNAL
      {MD_DISK_JOURNAL, "journal "},
#endif
#ifdef MD_DISK_CANDIDATE
      {MD_DISK_CANDIDATE, "spare "},
#endif
#ifdef MD_DISK_CLUSTER_ADD
      {MD_DISK_CLUSTER_ADD, "clusteradd "},
#endif
  };

  for (auto const& ps : possibleStates) {
    if ((1 << ps.first) & state) {
      s += ps.second;
    }
  }

  boost::algorithm::trim(s);
  return s;
}

/**
 * @brief resolves superblock state field to string representation
 *
 * @param  state state field of mdu_array_info_t
 *
 * @return stringified state
 */
std::string getSuperBlkStateStr(int state) {
  if (state == 0) {
    return "unknown";
  }

  std::string s;

  std::map<int, std::string> possibleStates = {
#ifdef MD_SB_CLEAN
      {MD_SB_CLEAN, "clean "},
#endif
#ifdef MD_SB_ERRORS
      {MD_SB_ERRORS, "errors "},
#endif
#ifdef MD_SB_BBM_ERRORS
      {MD_SB_BBM_ERRORS, "bbm_errors "},
#endif
#ifdef MD_SB_BLOCK_CONTAINER_RESHAPE
      {MD_SB_BLOCK_CONTAINER_RESHAPE, "container_reshape "},
#endif
#ifdef MD_SB_BLOCK_VOLUME
      {MD_SB_BLOCK_VOLUME, "block_activation "},
#endif
#ifdef MD_SB_CLUSTERED
      {MD_SB_CLUSTERED, "clustered "},
#endif
#ifdef MD_SB_BITMAP_PRESENT
      {MD_SB_BITMAP_PRESENT, "bitmap_present "},
#endif
  };

  for (auto const& ps : possibleStates) {
    if ((1 << ps.first) & state) {
      s += ps.second;
    }
  }

  boost::algorithm::trim(s);
  return s;
}

// For use with unique_ptr of file close as a hacky way of preventing fd leaks
auto const kFClose = [](int* fd) { close(*fd); };

bool MD::getDiskInfo(const std::string& arrayName, mdu_disk_info_t& diskInfo) {
  std::map<std::string, std::string> results;
  int fd = 0;

  std::unique_ptr<int, decltype(kFClose)> _(
      &(fd = open(arrayName.c_str(), O_RDONLY)), kFClose);
  auto status = ioctl(fd, GET_DISK_INFO, &diskInfo);

  if (status == -1) {
    LOG(WARNING) << "Call to ioctl 'GET_DISK_INFO' " << arrayName
                 << " failed: " << strerror(errno);
    return false;
  }

  return true;
}

bool MD::getArrayInfo(const std::string& name, mdu_array_info_t& array) {
  std::map<std::string, std::string> results;
  int fd = 0;

  std::unique_ptr<int, decltype(kFClose)> _(
      &(fd = open(name.c_str(), O_RDONLY)), kFClose);
  auto status = ioctl(fd, GET_ARRAY_INFO, &array);

  if (status == -1) {
    LOG(ERROR) << "Call to ioctl 'GET_ARRAY_INFO' for " << name
               << " failed: " << strerror(errno);
    return false;
  }

  return true;
}

inline void parseMDPersonalities(const std::string& line,
                                 std::vector<std::string>& result) {
  auto enabledPersonalities(split(line, " "));
  for (auto& p : enabledPersonalities) {
    boost::algorithm::trim(p);
    if (p.length() > 2) {
      result.push_back(p.substr(1, p.length() - 2));
    }
  }
}

void parseMDAction(const std::string& line, MDAction& result) {
  /* Make assumption that recovery/resync format is [d+]% ([d+]/[d+])
   * finish=<duration> speed=<rate> */
  auto pieces(split(line, " "));
  if (pieces.size() != 4) {
    LOG(WARNING) << "Unexpected recovery/resync line format: " << line;
    return;
  }
  trimStrs(pieces);

  result.progress = pieces[0] + ' ' + pieces[1];

  auto start = pieces[2].find_first_not_of("finish=");
  if (start != std::string::npos) {
    result.finish = pieces[2].substr(start);

  } else {
    result.finish = pieces[2];
  }

  start = pieces[3].find_first_not_of("speed=");
  if (start != std::string::npos) {
    result.speed = pieces[3].substr(start);

  } else {
    result.speed = pieces[3];
  }
}

void parseMDBitmap(const std::string& line, MDBitmap& result) {
  auto bitmapInfos(split(line, ","));
  if (bitmapInfos.size() < 2) {
    LOG(WARNING) << "Unexpected bitmap line structure: " << line;

  } else {
    trimStrs(bitmapInfos);
    result.onMem = bitmapInfos[0];
    result.chunkSize = bitmapInfos[1];

    if (bitmapInfos.size() > 2) {
      auto pos = bitmapInfos[2].find("file:");
      if (pos != std::string::npos) {
        result.externalFile = bitmapInfos[2].substr(pos + sizeof("file:") - 1);
        boost::algorithm::trim(result.externalFile);
      }
    }
  }
}

/*
 * @brief Handles checkArrays, resyncs, reshapes, bitmap lines of mdstat
 *
 * @param lines mdstat file represented as vector of lines
 * @param n ref to current line number; works on line n + 1
 * @param searchTerm search term to determine line should be handled
 * @param handleFunc function to execute when search term is found and line is
 * extracted
 *
 * @return bool indicating whether a line for the searchTerm was found in the
 * line n + 1 and handleFunc was executed, increments param n to n + 1
 */
static inline bool handleMDStatuses(
    const std::vector<std::string>& lines,
    size_t& n,
    const std::string& searchTerm,
    std::function<void(const std::string& line)> handleFunc) {
  std::size_t pos = lines[n + 1].find(searchTerm);
  if (pos != std::string::npos) {
    std::string line(lines[n + 1].substr(pos + searchTerm.length()));
    boost::algorithm::trim(line);
    handleFunc(line);
    // Add an extra line for next iteration if so..
    n += 1;
    return true;
  }

  return false;
}

MDDrive parseMDDrive(const std::string& name) {
  MDDrive drive;
  drive.name = name;

  auto start = name.find('[');
  auto end = name.find(']');
  if (start == std::string::npos || end == std::string::npos) {
    LOG(WARNING) << "Unexpected drive name format: " << name;
    return drive;
  }

  drive.pos = std::stoi(name.substr(start + 1, end - start - 1));

  return drive;
}

void MD::parseMDStat(const std::vector<std::string>& lines, MDStat& result) {
  // Will be used to determine starting point of lines to work on.
  size_t n = 0;

  if (lines.empty()) {
    return;
  }

  // This should always evaluate to true, but just in case we check.
  if (lines[0].find("Personalities :") != std::string::npos) {
    std::string pline(lines[0].substr(sizeof("Personalities :") - 1));
    parseMDPersonalities(pline, result.personalities);

    n = 1;

  } else {
    LOG(WARNING) << "mdstat Personalites not found at line 0: " << lines[0];
  }

  while (n < lines.size()) {
    if (lines[n].find_first_not_of("\t\r\v ") == std::string::npos) {
      n += 1;
      continue;
    }
    // Work off of first 2 character instead of just the first to be safe.
    std::string firstTwo = lines[n].substr(0, 2);
    if (firstTwo == "md") {
      auto mdline(split(lines[n], ":", 1));
      if (mdline.size() < 2) {
        LOG(WARNING) << "Unexpected md device line structure: " << lines[n];
        n += 1;
        continue;
      }

      MDDevice mdd;
      mdd.name = std::move(mdline[0]);
      boost::algorithm::trim(mdd.name);

      auto settings(split(mdline[1], " "));
      trimStrs(settings);
      // First 2 of settings are always status and RAID level
      if (settings.size() >= 2) {
        mdd.status = std::move(settings[0]);
        mdd.raidLevel = std::move(settings[1]);

        for (size_t i = 2; i < settings.size(); i++) {
          mdd.drives.push_back(parseMDDrive(settings[i]));
        }
      }

      /* Next line is device config and settings.  We handle here instead of
       * later b/c pieces are need for both md_drives and md_devices table.  For
       * safety, we check if we at the end of the file. */
      if (n >= lines.size() - 1) {
        continue;
        n += 1;
      }
      auto configline(split(lines[n + 1]));

      if (configline.size() < 4) {
        LOG(WARNING) << "Unexpected md device config: " << lines[n + 1];

      } else {
        trimStrs(configline);

        if (configline[1] == "blocks") {
          Status status = safeStrtol(configline[0], 10, mdd.usableSize);
          if (!status.ok()) {
            LOG(WARNING) << "Could not parse usable size of " << mdd.name;
          }

        } else {
          LOG(WARNING) << "Did not find size in mdstat for " << mdd.name;
        }

        mdd.healthyDrives = configline[configline.size() - 2];
        mdd.driveStatuses = configline[configline.size() - 1];

        if (configline.size() > 4) {
          for (size_t i = 2; i < configline.size() - 2; i++) {
            mdd.other += (" " + configline[i]);
            boost::algorithm::trim(mdd.other);
          }
        }
      }
      // Skip config line for next iteration
      n += 1;

      // Handle potential bitmap, recovery, and resync lines
      while (n < lines.size() - 1) {
        if (handleMDStatuses(
                lines, n, "recovery =", [&mdd](const std::string& line) {
                  parseMDAction(line, mdd.recovery);
                })) {
          continue;
        }

        if (handleMDStatuses(
                lines, n, "resync =", [&mdd](const std::string& line) {
                  parseMDAction(line, mdd.resync);
                })) {
          continue;
        }

        // If in this format, it's generally signaling a progress delay
        if (handleMDStatuses(
                lines, n, "resync=", [&mdd](const std::string& line) {
                  mdd.resync.progress = line;
                })) {
          continue;
        }

        if (handleMDStatuses(
                lines, n, "reshape =", [&mdd](const std::string& line) {
                  parseMDAction(line, mdd.reshape);
                })) {
          continue;
        }

        if (handleMDStatuses(
                lines, n, "check =", [&mdd](const std::string& line) {
                  parseMDAction(line, mdd.checkArray);
                })) {
          continue;
        }

        if (handleMDStatuses(
                lines, n, "bitmap:", [&mdd](const std::string& line) {
                  parseMDBitmap(line, mdd.bitmap);
                })) {
          continue;
        }

        // If none of above, then we can break out of loop
        break;
      }

      result.devices.push_back(mdd);

      // Assume unused
    } else if (firstTwo == "un") {
      result.unused = lines[n].substr(sizeof("unused devices:") - 1);
      boost::algorithm::trim(result.unused);
      // Unexpected mdstat line, log a warning...
    } else {
      LOG(WARNING) << "Unexpected mdstat line: " << lines[n];
    }

    n += 1;
  }
}

void getDrivesForArray(const std::string& arrayName,
                       MDInterface& md,
                       QueryData& data) {
  std::string path(md.getPathByDevName(arrayName));
  if (path.empty()) {
    LOG(ERROR) << "Could not get file path for " << arrayName;
    return;
  }

  mdu_array_info_t array;
  if (!md.getArrayInfo(path, array)) {
    return;
  }

  /* Create a vector of with all expected slot positions.  As we work through
   * the RAID disks, we remove discovered slots */
  std::vector<size_t> missingSlots(array.raid_disks);
  std::iota(missingSlots.begin(), missingSlots.end(), 0);

  /* Keep track of index in QueryData that have removed slots since we can't
   * make safe assumptions about it's original slot position if disk_number >=
   * total_disk and we're unable to deteremine total number of missing slots
   * until we walk thru all MD_SB_DISKS */
  std::vector<size_t> removedSlots;

  size_t qdPos = data.size();
  for (size_t i = 0; i < MD_SB_DISKS; i++) {
    mdu_disk_info_t disk;
    disk.number = i;
    if (!md.getDiskInfo(path, disk)) {
      continue;
    }

    if (disk.major > 0) {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = md.getDevName(disk.major, disk.minor);
      r["state"] = getDiskStateStr(disk.state);

      if (disk.raid_disk >= 0) {
        r["slot"] = INTEGER(disk.raid_disk);
        missingSlots.erase(
            std::remove(
                missingSlots.begin(), missingSlots.end(), disk.raid_disk),
            missingSlots.end());

        /* We assume that if the disk number is less than the total disk count
         * of the array, then it assumes its original slot position;  If the
         * number is greater than the disk count, then it's not safe to make
         * that assumption. We do this check here b/c if a recovery is targeted
         * for the same slot, we potentially miss identifying the original slot
         * position of the bad disk. */
      } else if (disk.raid_disk < 0 && disk.number < array.raid_disks) {
        r["slot"] = std::to_string(disk.number);
        missingSlots.erase(
            std::remove(missingSlots.begin(), missingSlots.end(), disk.number),
            missingSlots.end());

        /* Mark QueryData position as a removedSlot to handle later*/
      } else {
        removedSlots.push_back(qdPos);
      }

      qdPos++;
      data.push_back(r);
    }
  }

  /* Handle all missing slots.  See `scattered_faulty_and_removed` unit test in
   * `./tests/md_tables_tests.cpp`*/
  for (const auto& slot : missingSlots) {
    if (!removedSlots.empty()) {
      data[removedSlots[0]]["slot"] = INTEGER(slot);
      removedSlots.erase(removedSlots.begin());

    } else {
      Row r;
      r["md_device_name"] = arrayName;
      r["drive_name"] = "unknown";
      r["state"] = "removed";
      r["slot"] = std::to_string(slot);
      data.push_back(r);
    }
  }
}

QueryData genMDDrives(QueryContext& context) {
  QueryData results;
  MDStat mds;
  MD md;
  std::vector<std::string> lines;
  getLines(lines);

  md.parseMDStat(lines, mds);

  for (const auto& device : mds.devices) {
    getDrivesForArray(device.name, md, results);
  }

  return results;
}

QueryData genMDDevices(QueryContext& context) {
  QueryData results;
  MDStat mds;
  MD md;
  std::vector<std::string> lines;

  getLines(lines);

  md.parseMDStat(lines, mds);
  for (const auto& device : mds.devices) {
    std::string path(md.getPathByDevName(device.name));
    if (path.empty()) {
      LOG(ERROR) << "Could not get file path for " << device.name;
      return results;
    }

    mdu_array_info_t array;
    if (!md.getArrayInfo(path, array)) {
      return results;
    }

    Row r;
    r["device_name"] = device.name;
    r["status"] = device.status;
    r["raid_level"] = INTEGER(array.level);
    r["size"] = BIGINT(device.usableSize);
    r["chunk_size"] = BIGINT(array.chunk_size);
    r["raid_disks"] = INTEGER(array.raid_disks);
    r["nr_raid_disks"] = INTEGER(array.nr_disks);
    r["working_disks"] = INTEGER(array.working_disks);
    r["active_disks"] = INTEGER(array.active_disks);
    r["failed_disks"] = INTEGER(array.failed_disks);
    r["spare_disks"] = INTEGER(array.spare_disks);

    r["superblock_state"] = getSuperBlkStateStr(array.state);
    r["superblock_version"] = md.getSuperblkVersion(device.name);
    r["superblock_update_time"] = BIGINT(array.utime);

    if (!device.recovery.progress.empty()) {
      r["recovery_progress"] = device.recovery.progress;
      r["recovery_finish"] = device.recovery.finish;
      r["recovery_speed"] = device.recovery.speed;
    }

    if (!device.resync.progress.empty()) {
      r["resync_progress"] = device.resync.progress;
      r["resync_finish"] = device.resync.finish;
      r["resync_speed"] = device.resync.speed;
    }

    if (!device.reshape.progress.empty()) {
      r["reshape_progress"] = device.reshape.progress;
      r["reshape_finish"] = device.reshape.finish;
      r["reshape_speed"] = device.reshape.speed;
    }

    if (!device.checkArray.progress.empty()) {
      r["check_array_progress"] = device.checkArray.progress;
      r["check_array_finish"] = device.checkArray.finish;
      r["check_array_speed"] = device.checkArray.speed;
    }

    if (!device.bitmap.onMem.empty()) {
      r["bitmap_on_mem"] = device.bitmap.onMem;
      r["bitmap_chunk_size"] = device.bitmap.chunkSize;
      r["bitmap_external_file"] = device.bitmap.externalFile;
    }

    r["other"] = device.other;
    r["unused_devices"] = mds.unused;

    results.push_back(r);
  }

  return results;
}

QueryData genMDPersonalities(QueryContext& context) {
  QueryData results;
  MDStat mds;
  std::vector<std::string> lines;
  MD md;

  getLines(lines);

  md.parseMDStat(lines, mds);

  for (const auto& name : mds.personalities) {
    Row r = {{"name", name}};

    results.push_back(r);
  }

  return results;
}
} // namespace tables
} // namespace osquery

max_stars_repo_name: poppyseedplehzr/osquery

max_issues_repo_name: poppyseedplehzr/osquery

max_forks_repo_name: poppyseedplehzr/osquery


text:
//
// Copyright Jason Rice 2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef NBDL_DETAIL_FILTER_EMPTIES_HPP
#define NBDL_DETAIL_FILTER_EMPTIES_HPP

#include <boost/hana/bool.hpp>
#include <boost/hana/filter.hpp>
#include <boost/hana/functional/on.hpp>
#include <boost/hana/tuple.hpp>
#include <functional>
#include <type_traits>
#include <utility>

namespace nbdl { namespace detail
{
  namespace hana = boost::hana;

  struct unref_fn
  {
    template <typename Ref>
    decltype(auto) operator()(Ref ref) const
    {
      return ref.get();
    }
  };

  template <typename F>
  struct filter_empties_fn
  {
    F f;
    template <typename ...X>
    decltype(auto) operator()(X&& ...x) const
    {
      return hana::unpack(
        hana::filter(hana::make_tuple(std::ref(x)...), [](auto ref)
        {
          return hana::bool_c<!std::is_empty<typename decltype(ref)::type>::value>;
        }),
        hana::on(f, detail::unref_fn{})
      );
    }
  };
}} // nbdl::detail

#endif

max_stars_repo_name: ricejasonf/nbdl

max_issues_repo_name: ricejasonf/nbdl

max_forks_repo_name: ricejasonf/nbdl