# ____________________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2026 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and Engineering
# Solutions of Sandia, LLC, the U.S. Government retains certain rights in this
# software.  This software is distributed under the 3-clause BSD License.
# ____________________________________________________________________________________

from pyomo.contrib.appsi.cmodel import cmodel, cmodel_available
import pyomo.common.unittest as unittest
import math
from pyomo.contrib.fbbt.tests.test_interval import IntervalTestBase


@unittest.skipUnless(cmodel_available, 'appsi extensions are not available')
class TestInterval(IntervalTestBase, unittest.TestCase):
    def setUp(self):
        super(TestInterval, self).setUp()
        self.add = cmodel.py_interval_add
        self.sub = cmodel.py_interval_sub
        self.mul = cmodel.py_interval_mul
        self.inv = cmodel.py_interval_inv
        self.div = cmodel.py_interval_div
        self.power = cmodel.py_interval_power
        self.exp = cmodel.py_interval_exp
        self.log = cmodel.py_interval_log
        self.log10 = cmodel.py_interval_log10
        self.sin = cmodel.py_interval_sin
        self.cos = cmodel.py_interval_cos
        self.tan = cmodel.py_interval_tan
        self.asin = cmodel.py_interval_asin
        self.acos = cmodel.py_interval_acos
        self.atan = cmodel.py_interval_atan
        self._inverse_power1 = cmodel._py_inverse_power1
        self._inverse_power2 = cmodel._py_inverse_power2


@unittest.skipUnless(cmodel_available, 'appsi extensions are not available')
class TestCInterval(unittest.TestCase):
    def test_pow_with_inf(self):
        x_list = [
            0,
            -math.inf,
            math.inf,
            -3,
            3,
            -2,
            2,
            -1,
            1,
            -2.5,
            2.5,
            -0.5,
            0.5,
            -1.5,
            1.5,
        ]
        y_list = list(x_list)
        for x in x_list:
            for y in y_list:
                try:
                    expected = x**y
                    if type(expected) is complex:
                        expect_error = True
                        expected = None
                    else:
                        expect_error = False
                except ZeroDivisionError as e:
                    expected = None
                    expect_error = True
                if expect_error:
                    with self.assertRaises(ValueError):
                        cmodel._pow_with_inf(x, y)
                else:
                    got = cmodel._pow_with_inf(x, y)
                    self.assertAlmostEqual(expected, got)
