def matrices_close(m1, m2, precision=1e-4): """ Returns True iff m1 and m2 are almost equal, where elements can be either floats or AffineScalarFunc objects. m1, m2 -- NumPy matrices. precision -- precision passed through to uncertainties.test_uncertainties._numbers_close(). """ # ! numpy.allclose() is similar to this function, but does not # work on arrays that contain numbers with uncertainties, because # of the isinf() function. for (elmt1, elmt2) in zip(m1.flat, m2.flat): # For a simpler comparison, both elements are # converted to AffineScalarFunc objects: elmt1 = uncertainties.to_affine_scalar(elmt1) elmt2 = uncertainties.to_affine_scalar(elmt2) if not _numbers_close(elmt1.nominal_value, elmt2.nominal_value, precision): return False if not _numbers_close(elmt1.std_dev(), elmt2.std_dev(), precision): return False return True
def frexp(x): """ Version of frexp that works for numbers with uncertainty, and also for regular numbers. """ # The code below is inspired by uncertainties.wrap(). It is # simpler because only 1 argument is given, and there is no # delegation to other functions involved (as for __mul__, etc.). aff_func = to_affine_scalar(x) if aff_func.derivatives: result = math.frexp(aff_func.nominal_value) # With frexp(x) = (m, e), dm/dx = 1/(2**e): factor = 1 / (2**result[1]) return ( AffineScalarFunc( result[0], # Chain rule: dict((var, factor * deriv) for (var, deriv) in aff_func.derivatives.iteritems())), # The exponent is an integer and is supposed to be # continuous (small errors): result[1]) else: # This function was not called with an AffineScalarFunc # argument: there is no need to return numbers with uncertainties: return math.frexp(x)
def ldexp(x, y): # The code below is inspired by uncertainties.wrap(). It is # simpler because only 1 argument is given, and there is no # delegation to other functions involved (as for __mul__, etc.). # Another approach would be to add an additional argument to # uncertainties.wrap() so that some arguments are automatically # considered as constants. aff_func = to_affine_scalar(x) # y must be an integer, for math.ldexp if aff_func.derivatives: factor = 2**y return AffineScalarFunc( math.ldexp(aff_func.nominal_value, y), # Chain rule: dict((var, factor * deriv) for (var, deriv) in aff_func.derivatives.iteritems())) else: # This function was not called with an AffineScalarFunc # argument: there is no need to return numbers with uncertainties: # aff_func.nominal_value is not passed instead of x, because # we do not have to care about the type of the return value of # math.ldexp, this way (aff_func.nominal_value might be the # value of x coerced to a difference type [int->float, for # instance]): return math.ldexp(x, y)
def frexp(x): """ Version of frexp that works for numbers with uncertainty, and also for regular numbers. """ # The code below is inspired by uncertainties.wrap(). It is # simpler because only 1 argument is given, and there is no # delegation to other functions involved (as for __mul__, etc.). aff_func = to_affine_scalar(x) if aff_func.derivatives: result = math.frexp(aff_func.nominal_value) # With frexp(x) = (m, e), dm/dx = 1/(2**e): factor = 1/(2**result[1]) return ( AffineScalarFunc( result[0], # Chain rule: dict([(var, factor*deriv) for (var, deriv) in aff_func.derivatives.iteritems()])), # The exponent is an integer and is supposed to be # continuous (small errors): result[1]) else: # This function was not called with an AffineScalarFunc # argument: there is no need to return numbers with uncertainties: return math.frexp(x)
def ldexp(x, y): # The code below is inspired by uncertainties.wrap(). It is # simpler because only 1 argument is given, and there is no # delegation to other functions involved (as for __mul__, etc.). # Another approach would be to add an additional argument to # uncertainties.wrap() so that some arguments are automatically # considered as constants. aff_func = to_affine_scalar(x) # y must be an integer, for math.ldexp if aff_func.derivatives: factor = 2**y return AffineScalarFunc( math.ldexp(aff_func.nominal_value, y), # Chain rule: dict([(var, factor*deriv) for (var, deriv) in aff_func.derivatives.iteritems()])) else: # This function was not called with an AffineScalarFunc # argument: there is no need to return numbers with uncertainties: # aff_func.nominal_value is not passed instead of x, because # we do not have to care about the type of the return value of # math.ldexp, this way (aff_func.nominal_value might be the # value of x coerced to a difference type [int->float, for # instance]): return math.ldexp(x, y)
def modf(x): """ Version of modf that works for numbers with uncertainty, and also for regular numbers. """ # The code below is inspired by uncertainties.wrap(). It is # simpler because only 1 argument is given, and there is no # delegation to other functions involved (as for __mul__, etc.). aff_func = to_affine_scalar(x) (frac_part, int_part) = math.modf(aff_func.nominal_value) if aff_func.derivatives: # The derivative of the fractional part is simply 1: the # derivatives of modf(x)[0] are the derivatives of x: return (AffineScalarFunc(frac_part, aff_func.derivatives), int_part) else: # This function was not called with an AffineScalarFunc # argument: there is no need to return numbers with uncertainties: return (frac_part, int_part)