# Path: pyinform/error.py
# class InformError(Exception):
#     """
#     InformError signifies an error occurred in a call to inform.
#     """
# 
#     def __init__(self, e=-1, func=None):
#         msg = error_string(e)
# 
#         if func is None:
#             msg = "an inform error occurred - \"{}\"".format(msg)
#         else:
#             msg = "an inform error occurred in `{}` - \"{}\"".format(func, msg)
# 
#         super(InformError, self).__init__(msg)
# 
#         self.error_code = e if isinstance(e, ErrorCode) else ErrorCode(e)
# 
# Path: pyinform/relativeentropy.py
# def relative_entropy(xs, ys, local=False):
#     """
#     Compute the local or global relative entropy between two time series
#     treating each as observations from a distribution.
# 
#     :param xs: the time series sampled from the posterior distribution
#     :type xs: a sequence or ``numpy.ndarray``
#     :param ys: the time series sampled from the prior distribution
#     :type ys: a sequence or ``numpy.ndarray``
#     :param bool local: compute the local relative entropy
#     :return: the local or global relative entropy
#     :rtype: float or ``numpy.ndarray``
#     :raises ValueError: if the time series have different shapes
#     :raises InformError: if an error occurs within the ``inform`` C call
#     """
#     us = np.ascontiguousarray(xs, dtype=np.int32)
#     vs = np.ascontiguousarray(ys, dtype=np.int32)
#     if us.shape != vs.shape:
#         raise ValueError("timeseries lengths do not match")
# 
#     b = max(2, np.amax(us) + 1, np.amax(vs) + 1)
# 
#     xdata = us.ctypes.data_as(POINTER(c_int))
#     ydata = vs.ctypes.data_as(POINTER(c_int))
#     n = us.size
# 
#     e = ErrorCode(0)
# 
#     if local is True:
#         re = np.empty(b, dtype=np.float64)
#         out = re.ctypes.data_as(POINTER(c_double))
#         _local_relative_entropy(xdata, ydata, c_ulong(n), c_int(b), out, byref(e))
#     else:
#         re = _relative_entropy(xdata, ydata, c_ulong(n), c_int(b), byref(e))
# 
#     error_guard(e)
# 
#     return re


import unittest
import numpy as np
from pyinform.error import InformError
from pyinform.relativeentropy import relative_entropy
from math import isnan, isinf
            elif isinf(expect[i]) or isinf(got[i]):
                self.fail("unequal infinite values")
            else:
                self.assertAlmostEqual(expect[i], got[i], places=places)

    def test_relative_entropy_empty(self):
        with self.assertRaises(ValueError):
            relative_entropy([], [], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1, 2, 3], [], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([], [1, 2, 3], local=True)

    def test_relative_entropy_dimensions(self):
        with self.assertRaises(ValueError):
            relative_entropy([[1]], [1], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1], [[1]], local=True)

    def test_relative_entropy_size(self):
        with self.assertRaises(ValueError):
            relative_entropy([1, 2, 3], [1, 2], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1, 2], [1, 2, 3], local=True)

    def test_relative_entropy_negative_states(self):

# Path: pyinform/error.py
# class InformError(Exception):
#     """
#     InformError signifies an error occurred in a call to inform.
#     """
# 
#     def __init__(self, e=-1, func=None):
#         msg = error_string(e)
# 
#         if func is None:
#             msg = "an inform error occurred - \"{}\"".format(msg)
#         else:
#             msg = "an inform error occurred in `{}` - \"{}\"".format(func, msg)
# 
#         super(InformError, self).__init__(msg)
# 
#         self.error_code = e if isinstance(e, ErrorCode) else ErrorCode(e)
# 
# Path: pyinform/relativeentropy.py
# def relative_entropy(xs, ys, local=False):
#     """
#     Compute the local or global relative entropy between two time series
#     treating each as observations from a distribution.
# 
#     :param xs: the time series sampled from the posterior distribution
#     :type xs: a sequence or ``numpy.ndarray``
#     :param ys: the time series sampled from the prior distribution
#     :type ys: a sequence or ``numpy.ndarray``
#     :param bool local: compute the local relative entropy
#     :return: the local or global relative entropy
#     :rtype: float or ``numpy.ndarray``
#     :raises ValueError: if the time series have different shapes
#     :raises InformError: if an error occurs within the ``inform`` C call
#     """
#     us = np.ascontiguousarray(xs, dtype=np.int32)
#     vs = np.ascontiguousarray(ys, dtype=np.int32)
#     if us.shape != vs.shape:
#         raise ValueError("timeseries lengths do not match")
# 
#     b = max(2, np.amax(us) + 1, np.amax(vs) + 1)
# 
#     xdata = us.ctypes.data_as(POINTER(c_int))
#     ydata = vs.ctypes.data_as(POINTER(c_int))
#     n = us.size
# 
#     e = ErrorCode(0)
# 
#     if local is True:
#         re = np.empty(b, dtype=np.float64)
#         out = re.ctypes.data_as(POINTER(c_double))
#         _local_relative_entropy(xdata, ydata, c_ulong(n), c_int(b), out, byref(e))
#     else:
#         re = _relative_entropy(xdata, ydata, c_ulong(n), c_int(b), byref(e))
# 
#     error_guard(e)
# 
#     return re


# Path: test/test_relativeentropy.py
import unittest
import numpy as np
from pyinform.error import InformError
from pyinform.relativeentropy import relative_entropy
from math import isnan, isinf

            elif isinf(expect[i]) or isinf(got[i]):
                self.fail("unequal infinite values")
            else:
                self.assertAlmostEqual(expect[i], got[i], places=places)

    def test_relative_entropy_empty(self):
        with self.assertRaises(ValueError):
            relative_entropy([], [], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1, 2, 3], [], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([], [1, 2, 3], local=True)

    def test_relative_entropy_dimensions(self):
        with self.assertRaises(ValueError):
            relative_entropy([[1]], [1], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1], [[1]], local=True)

    def test_relative_entropy_size(self):
        with self.assertRaises(ValueError):
            relative_entropy([1, 2, 3], [1, 2], local=True)

        with self.assertRaises(ValueError):
            relative_entropy([1, 2], [1, 2, 3], local=True)

    def test_relative_entropy_negative_states(self):

        with self.assertRaises(InformError):