def substract(self, x, y): mantissa = x.mantissa - y.mantissa if self.format_.overflows_with(mantissa): if not self.substract.allows_overflow: raise OverflowError(f'{x} - {y} overflows in {self.format_}', mantissa * self.format_.value_epsilon, self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, self.format_)
def nearest(self, x): if x.is_integer: return x value = nearest_integer(mpfloat(x)) mantissa, (_, overflow) = self.format_.represent(value) if overflow: if not self.nearest.allows_overflow: raise OverflowError(f'round({x}) overflows in {self.format_}', mantissa * self.format_.value_epsilon, self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, format_)
def negate(self, x): if not self.format_.signed: raise RuntimeError('Cannot negate unsigned representations') if x.mantissa == 0: return x mantissa = -x.mantissa if self.format_.overflows_with(mantissa): if not self.negate.allows_overflow: raise OverflowError(f'{x} overflows in {self.format_}', mantissa * self.format_.value_epsilon, self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, self.format_)
def represent(self, value, rtype=Representation): if isinstance(value, rtype) and value.format_ == self.format_: return value mantissa, (underflow, overflow) = self.format_.represent( value, rounding_method=nearest_integer) if underflow and not self.represent.allows_underflow: raise UnderflowError(f'{value} underflows in {self.format_}', value, self.format_.value_epsilon) if overflow: if not self.represent.allows_overflow: raise OverflowError(f'{value} overflows in {self.format_}', value, self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return rtype(mantissa, self.format_)
def lshift(self, x, n): if x.format_ != self.format_: raise ValueError(f'{self} cannot handle {x}') if n < 0: raise ValueError(f'negative shift count {n}') n = int(n) mantissa = x.mantissa << n if self.format_.overflows_with(mantissa): if not self.lshift.allows_overflow: raise OverflowError(f'{x} << {n} overflows in {self.format_}', mantissa * self.format_.value_epsilon, self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, self.format_)
def multiply(self, x, y): # Use 2 * wordlength long multipliers z = Representation(mantissa=x.mantissa * y.mantissa, format_=Format(msb=self.format_.msb * 2 + 1, lsb=self.format_.lsb * 2, signed=self.format_.signed)) mantissa, (underflow, overflow) = self.format_.represent( z, rounding_method=self.rounding_method) if underflow and not self.multiply.allows_underflow: raise UnderflowError(f'{x} * {y} underflows in {self.format_}', mpfloat(z), self.format_.value_epsilon) if overflow: if not self.multiply.allows_overflow: raise OverflowError(f'{x} * {y} overflows in {self.format_}', mpfloat(z), self.format_.value_interval) mantissa, _ = self.overflow_behavior( mantissa, range_=self.format_.mantissa_interval) return type(x)(mantissa, self.format_)