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 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)