def generate_error_samples(self, sample_time, name, golden=False): """ Generate sample_nb samples of tree evaluation in the tree's working precision :return an array of samples, absolute errors and relative errors """ if golden and loadIfExists and os.path.exists(storage_path + name): print("Golden distribution is going to be loaded from disk!") return True, [], [], [] print("Generating Samples...") rel_err = [] abs_err = [] err = [] values = [] set_context_precision(self.precision, self.exponent) start_time = time.time() end_time = 0 while end_time <= sample_time: self.resetInit(self.tree) sample, lp_sample = self.evaluate_error_at_sample(self.tree) values.append(sample) tmp_abs = abs(float(printMPFRExactly(lp_sample)) - sample) err.append(sample - float(printMPFRExactly(lp_sample))) abs_err.append(tmp_abs) rel_err.append(tmp_abs / sample) end_time = time.time() - start_time self.resetInit(self.tree) reset_default_precision() print("... Done with generation") return False, np.asarray(values), np.asarray(abs_err), np.asarray( rel_err), np.asarray(err)
def _middle_segment(self, x): sum = 0.0 err = x * self.unit_roundoff set_context_precision(self.precision, self.exponent) z = mpfr(printMPFRExactly(self.inf_val)) # Loop through all floating point numbers in reduced precision while z <= self.sup_val: xp = float(printMPFRExactly(z)) / (1.0 - err) sum += self.input_distribution.get_piecewise_pdf()(xp) * abs(xp) * self.unit_roundoff / (1.0 - err) z = gmpy2.next_above(z) reset_default_precision() return sum
def getFinalMaxValue(self, supVal): if not gmpy2.is_finite(supVal): print("Error cannot compute intervals with infinity") exit(-1) bkpCtx = gmpy2.get_context().copy() i = 0 while not gmpy2.is_finite(gmpy2.next_above(supVal)): set_context_precision(self.precision + i, self.exponent + i) i = i + 1 prec = printMPFRExactly(gmpy2.next_above(supVal)) gmpy2.set_context(bkpCtx) return prec
def __init__(self, wrapperInputDistribution, precision, exponent): self.wrapperInputDistribution = wrapperInputDistribution #self.inputdistribution = self.wrapperInputDistribution.execute() #self.inputdistribution.get_piecewise_pdf() tmp_value=wrapperInputDistribution.discretization.lower self.precision = precision self.exponent = exponent self.unit_roundoff = 2 ** -self.precision set_context_precision(self.precision, self.exponent) qValue = printMPFRExactly(mpfr(str(tmp_value))) reset_default_precision() error = float(tmp_value) - float(qValue) self.distribution = ConstDistr(float(error)) self.distribution.get_piecewise_pdf()
def _get_min_exponent(self): set_context_precision(self.precision, self.exponent) inf_val = gmpy2.mpfr(str(self.input_distribution.range_()[0])) self.min_sign = gmpy2.sign(inf_val) # For some reason the exponent returned by get_exp() is 1 too high and 0 for infinities if gmpy2.is_finite(inf_val): e = gmpy2.get_exp(inf_val) - 1 else: e = 2 ** (self.exponent - 1) if self.min_sign > 0: self.min_exp = e else: if inf_val < -2 ** (float)(e): self.min_exp = e + 1 else: self.min_exp = e reset_default_precision()
def _get_max_exponent(self): set_context_precision(self.precision, self.exponent) sup_val = gmpy2.mpfr(str(self.input_distribution.range_()[1])) self.max_sign = gmpy2.sign(sup_val) # For some reason the exponent returned by get_exp() is 1 too high and 0 if sup_val is infinite if gmpy2.is_finite(sup_val): e = gmpy2.get_exp(sup_val) - 1 else: e = 2 ** (self.exponent - 1) if self.max_sign < 0: self.max_exp = e else: if sup_val > 2 ** float(e): self.max_exp = e + 1 else: self.max_exp = e reset_default_precision()
def __init__(self, input_distribution, input_name, precision, exponent, polynomial_precision=[0, 0]): """ Constructor interpolates the density function using Chebyshev interpolation then uses this interpolation to build a PaCal object: the self.distribution attribute which contains all the methods we could possibly want Inputs: input_distribution: a PaCal object representing the distribution for which we want to compute the rounding error distribution precision, exponent: specify the gmpy2 precision environment polynomial_precision: default precision as implemented in AbstractErrorModel will typically not converge so it is re-implemented as dynamically setting polynomial_precision. For very low precision, polynomial_precision needs to be high because the function is very discontinuous (there are few floating points so it won't impact performance). For higher precision it needs to be low for performance reason (but it won't impact accuracy because the function becomes much more regular). Warning: the relative error is not defined in the interval rounding to 0. In low precision this interval might have a large probability. This will be reflected by the distribution not integrating to 1. Example: Uniform(-2,2) with 3 bit exponent, 4 bit mantissa and default polynomial_precision integrates to 0.926 ! """ super(LowPrecisionErrorModel, self).__init__(input_distribution, precision, exponent, polynomial_precision) #self.name = "LPError(" + input_distribution.getName() + ")" self.name = "LPE_" + input_name set_context_precision(self.precision, self.exponent) self.inf_val = mpfr(str(self.input_distribution.range_()[0])) self.sup_val = mpfr(str(self.input_distribution.range_()[1])) if not gmpy2.is_finite(self.inf_val): self.inf_val = gmpy2.next_above(self.inf_val) if not gmpy2.is_finite(self.sup_val): self.sup_val = gmpy2.next_below(self.sup_val) self.max_exp = 2 ** (exponent - 1) if self.inf_val == 0: # take most negative exponent self.exp_inf_val = -self.max_exp else: self.exp_inf_val = floor(log(abs(self.inf_val), 2)) if self.sup_val == 0: # take most negative exponent self.exp_sup_val = -self.max_exp else: self.exp_sup_val = floor(log(abs(self.sup_val), 2)) reset_default_precision() if polynomial_precision == [0, 0]: self.polynomial_precision = [floor(400.0 / float(self.precision)), floor(100.0 / float(self.precision))]