// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

#include "color2.h"
#include "../common/shaders/pretty.h"

#define OSL_UNITTEST_VERBOSE 1
#include "../common/shaders/osl-unittest.h"

float xcomp(color2 v) { return v.r; }
float ycomp(color2 v) { return v.a; }

#define TEST_UNARY_VAL(func, val) \
    OSL_CHECK_EQUAL(func(val), color2(func(xcomp(val)), func(ycomp(val))))

#define TEST_BINARY_VAL(func, valA, valB) \
    OSL_CHECK_EQUAL(func(valA, valB), color2(func(xcomp(valA), xcomp(valB)), \
                                             func(ycomp(valA), ycomp(valB))))

#define TEST_UNARY(func) \
    TEST_UNARY_VAL(func, color2(0.5, 1.5))

#define TEST_BINARY(func) \
    TEST_BINARY_VAL(func, color2(0.5, 1.5), color2(1.0, 4.0))



shader
test (color2 param1 = color2 (0.5, 1.5),
      color2 param2 = color2 (0.25, 0.25)
     )
{
    printf("parameter initialization: param1 = %g %g\n", param1.r, param1.a);
    printf("parameter initialization: param2 = %g %g\n", param2.r, param2.a);
    printf("\n");

    OSL_CHECK_EQUAL(param1, color2(0.5, 1.5));
    OSL_CHECK_EQUAL(-param1, color2(-0.5, -1.5));
    OSL_CHECK(param1 != param2);

    OSL_CHECK_EQUAL(param1 + param2, color2(0.75, 1.75));
    OSL_CHECK_EQUAL(param1 + 1, color2(1.5, 2.5));
    OSL_CHECK_EQUAL(param1 + 1.0, color2(1.5, 2.5));
    OSL_CHECK_EQUAL(1 + param1, color2(1.5, 2.5));
    OSL_CHECK_EQUAL(1.0 + param1, color2(1.5, 2.5));

    OSL_CHECK_EQUAL(param1 - param2, color2(0.25, 1.25));
    OSL_CHECK_EQUAL(param1 - 1, color2(-0.5, 0.5));
    OSL_CHECK_EQUAL(param1 - 1.0, color2(-0.5, 0.5));
    OSL_CHECK_EQUAL(1 - param1, color2(0.5, -0.5));
    OSL_CHECK_EQUAL(1.0 - param1, color2(0.5, -0.5));

    OSL_CHECK_EQUAL(param1 * param2, color2(0.125, 0.375));
    OSL_CHECK_EQUAL(param1 * 2, color2(1.0, 3.0));
    OSL_CHECK_EQUAL(param1 * 2.0, color2(1.0, 3.0));
    OSL_CHECK_EQUAL(2 * param1, color2(1.0, 3.0));
    OSL_CHECK_EQUAL(2.0 * param1, color2(1.0, 3.0));

    OSL_CHECK_EQUAL(param1 / param2, color2(2.0, 6.0));
    OSL_CHECK_EQUAL(param1 / 2, color2(0.25, 0.75));
    OSL_CHECK_EQUAL(param1 / 2.0, color2(0.25, 0.75));
    OSL_CHECK_EQUAL(2 / param1, color2(4.0, 2.0/1.5));
    OSL_CHECK_EQUAL(2.0 / param1, color2(4.0, 2.0/1.5));

    TEST_UNARY_VAL(abs, color2(0.5, 1.5));
    TEST_UNARY_VAL(abs, color2(-0.5, -1.5));
    TEST_UNARY_VAL(ceil, color2(0.5, 1.5));
    TEST_UNARY_VAL(ceil, color2(-0.5, -1.5));
    TEST_UNARY_VAL(floor, color2(0.5, 1.5));
    TEST_UNARY_VAL(floor, color2(-0.5, -1.5));

    TEST_UNARY(sqrt);
    TEST_UNARY(exp);
    TEST_UNARY(log);
    TEST_UNARY(log2);

    OSL_CHECK_EQUAL(mix(color2(1.0, 2.0), color2(21.0, 22.0), 0.0), color2(1.0, 2.0));
    OSL_CHECK_EQUAL(mix(color2(1.0, 2.0), color2(21.0, 22.0), 1.0), color2(21.0, 22.0));
    OSL_CHECK_EQUAL(mix(color2(1.0, 2.0), color2(21.0, 22.0), 0.5), color2(11.0, 12.0));

    OSL_CHECK_EQUAL(smoothstep(color2(1.0, 2.0), color2(3.0, 4.0), color2(0.0, 0.0)), color2(0.0, 0.0));
    OSL_CHECK_EQUAL(smoothstep(color2(1.0, 2.0), color2(3.0, 4.0), color2(10.0, 10.0)), color2(1.0, 1.0));
    OSL_CHECK_EQUAL(smoothstep(color2(1.0, 2.0), color2(3.0, 4.0), color2(2.0, 3.0)), color2(0.5, 0.5));
    
    OSL_CHECK_EQUAL(clamp(color2(0.0, 0.0), color2(1.0, 2.0), color2(2.0, 3.0)), color2(1.0, 2.0));
    OSL_CHECK_EQUAL(clamp(color2(10.0, 10.0), color2(1.0, 2.0), color2(2.0, 3.0)), color2(2.0, 3.0));
    OSL_CHECK_EQUAL(clamp(color2(1.5, 2.5), color2(1.0, 2.0), color2(2.0, 3.0)), color2(1.5, 2.5));

    OSL_CHECK_EQUAL(clamp(color2(0.25, 0.5), 1.0, 2.0), color2(1.0, 1.0));
    OSL_CHECK_EQUAL(clamp(color2(2.25, 2.5), 1.0, 2.0), color2(2.0, 2.0));
    OSL_CHECK_EQUAL(clamp(color2(1.25, 1.5), 1.0, 2.0), color2(1.25, 1.5));

    OSL_CHECK_EQUAL(max(color2(1.0, 4.0), color2(2.0, 3.0)), color2(2.0, 4.0));
    OSL_CHECK_EQUAL(min(color2(1.0, 4.0), color2(2.0, 3.0)), color2(1.0, 3.0));

    TEST_BINARY_VAL(fmod, color2(5.0, 8.0), color2(2.0, 3.0));
    TEST_BINARY_VAL(pow, color2(2.0, 3.0), color2(2.5, 3.5));
    TEST_UNARY_VAL(sign, color2(0.5, -0.5));
    TEST_UNARY_VAL(sign, color2(-0.5, 0.5));
    TEST_UNARY(sin);
    TEST_UNARY(cos);
    TEST_UNARY(tan);
    TEST_UNARY_VAL(asin, color2(0.5, 0.25));
    TEST_UNARY_VAL(acos, color2(0.5, 0.25));
    TEST_BINARY(atan2);
    OSL_CHECK_EQUAL(atan2(color2(2.0, 0.5), 1.0), color2(atan2(2.0, 1.0), atan2(0.5, 1.0)));
}
