//  Taken from the Boost.Bind library
//
//  bind_const_test.cpp - test const bind objects
//
//  Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd.
//  Copyright (c) 2001 David Abrahams
//  Copyright (c) 2013 Agustin Berge
//
//  SPDX-License-Identifier: BSL-1.0
// 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)
//

#if defined(HPX_MSVC)
#pragma warning(disable : 4786)    // identifier truncated in debug info
#pragma warning(disable : 4710)    // function not inlined
#pragma warning(                                                               \
    disable : 4711)    // function selected for automatic inline expansion
#pragma warning(disable : 4514)    // unreferenced inline removed
#endif

#include <hpx/functional/bind.hpp>

namespace placeholders = hpx::placeholders;

#include <iostream>

#include <hpx/modules/testing.hpp>

//

long f_0()
{
    return 17041L;
}

long f_1(long a)
{
    return a;
}

long f_2(long a, long b)
{
    return a + 10 * b;
}

long f_3(long a, long b, long c)
{
    return a + 10 * b + 100 * c;
}

long f_4(long a, long b, long c, long d)
{
    return a + 10 * b + 100 * c + 1000 * d;
}

long f_5(long a, long b, long c, long d, long e)
{
    return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}

long f_6(long a, long b, long c, long d, long e, long f)
{
    return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}

long f_7(long a, long b, long c, long d, long e, long f, long g)
{
    return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f +
        1000000 * g;
}

long f_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
    return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f +
        1000000 * g + 10000000 * h;
}

long f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
    return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f +
        1000000 * g + 10000000 * h + 100000000 * i;
}

long global_result;

void fv_0()
{
    global_result = 17041L;
}

void fv_1(long a)
{
    global_result = a;
}

void fv_2(long a, long b)
{
    global_result = a + 10 * b;
}

void fv_3(long a, long b, long c)
{
    global_result = a + 10 * b + 100 * c;
}

void fv_4(long a, long b, long c, long d)
{
    global_result = a + 10 * b + 100 * c + 1000 * d;
}

void fv_5(long a, long b, long c, long d, long e)
{
    global_result = a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}

void fv_6(long a, long b, long c, long d, long e, long f)
{
    global_result = a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}

void fv_7(long a, long b, long c, long d, long e, long f, long g)
{
    global_result =
        a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
}

void fv_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
    global_result = a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f +
        1000000 * g + 10000000 * h;
}

void fv_9(
    long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
    global_result = a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f +
        1000000 * g + 10000000 * h + 100000000 * i;
}

template <class F, class A>
long test(F const& f, A const& a)
{
    return f(a);
}

template <class F, class A>
long testv(F const& f, A const& a)
{
    f(a);
    return global_result;
}

void function_test()
{
    int const i = 1;

    HPX_TEST_EQ(test(hpx::bind(f_0), i), 17041L);
    HPX_TEST_EQ(test(hpx::bind(f_1, placeholders::_1), i), 1L);
    HPX_TEST_EQ(test(hpx::bind(f_2, placeholders::_1, 2), i), 21L);
    HPX_TEST_EQ(test(hpx::bind(f_3, placeholders::_1, 2, 3), i), 321L);
    HPX_TEST_EQ(test(hpx::bind(f_4, placeholders::_1, 2, 3, 4), i), 4321L);
    HPX_TEST_EQ(test(hpx::bind(f_5, placeholders::_1, 2, 3, 4, 5), i), 54321L);
    HPX_TEST(
        test(hpx::bind(f_6, placeholders::_1, 2, 3, 4, 5, 6), i) == 654321L);
    HPX_TEST(test(hpx::bind(f_7, placeholders::_1, 2, 3, 4, 5, 6, 7), i) ==
        7654321L);
    HPX_TEST(test(hpx::bind(f_8, placeholders::_1, 2, 3, 4, 5, 6, 7, 8), i) ==
        87654321L);
    HPX_TEST(test(hpx::bind(f_9, placeholders::_1, 2, 3, 4, 5, 6, 7, 8, 9),
                 i) == 987654321L);

    HPX_TEST_EQ(testv(hpx::bind(fv_0), i), 17041L);
    HPX_TEST_EQ(testv(hpx::bind(fv_1, placeholders::_1), i), 1L);
    HPX_TEST_EQ(testv(hpx::bind(fv_2, placeholders::_1, 2), i), 21L);
    HPX_TEST_EQ(testv(hpx::bind(fv_3, placeholders::_1, 2, 3), i), 321L);
    HPX_TEST_EQ(testv(hpx::bind(fv_4, placeholders::_1, 2, 3, 4), i), 4321L);
    HPX_TEST(testv(hpx::bind(fv_5, placeholders::_1, 2, 3, 4, 5), i) == 54321L);
    HPX_TEST(
        testv(hpx::bind(fv_6, placeholders::_1, 2, 3, 4, 5, 6), i) == 654321L);
    HPX_TEST(testv(hpx::bind(fv_7, placeholders::_1, 2, 3, 4, 5, 6, 7), i) ==
        7654321L);
    HPX_TEST(testv(hpx::bind(fv_8, placeholders::_1, 2, 3, 4, 5, 6, 7, 8), i) ==
        87654321L);
    HPX_TEST(testv(hpx::bind(fv_9, placeholders::_1, 2, 3, 4, 5, 6, 7, 8, 9),
                 i) == 987654321L);
}

int main()
{
    function_test();
    return hpx::util::report_errors();
}
