예제 #1
0
def checkConstantInit(val, st, signed, wl, fpf):
	"""Check the constant init, by comparing the three methods"""
	methods = ('', 'log','Benoit','threshold')
	c = [Constant(val, wl=wl, signed=signed, method=method, fpf=fpf, name=st) for method in methods]

	# check the mantissa range
	for cst in c:
		if signed:
			assert((-2 ** (wl - 1) <= cst.mantissa < -2 ** (wl - 2)) or (2 ** (wl-2) <= cst.mantissa < 2 ** (wl-1)))
		else:
			assert(2 ** (wl-1) <= cst.mantissa < 2 ** wl)
		# check str and value method
		str(c)
		repr(c)
		assert(cst.value == val)

	# compare the three constants (compare their FPF, mantissa and approx)
	cst = c[0]
	for i in range(1,len(c)):
		assert(cst.FPF == c[i].FPF)
		assert(cst.mantissa == c[i].mantissa)
		assert(cst.approx == c[i].approx)

	# check if |c - c_FxP| < 2 ^(l-1)
	for cst in c:
		if cst.mantissa == -2**(cst.FPF.wl-1):
			assert(almosteq(cst.approx, val, abs_eps=ldexp(1, cst.FPF.lsb)))
		else:
			assert (almosteq(cst.approx, val, abs_eps=ldexp(1, cst.FPF.lsb - 1)))

	# check relative and absolute error
	cst = c[0]
예제 #2
0
def iterSomeSignedMidPoints(N):
	"""Iter some particular values (mid-point between two consecutive signed FxP number with w bits)
	Returns the wordlength, string and mpf value"""
	# ordinary case: +/- (M+0.5)2^l, with (2^(w-1))+2 <= M <= 2^w - 2
	for _ in range(N):
		w = randint(8,200)
		l = randint(-50,50)
		M = randint( 2**(w-1)+2, 2**w-2)
		st = "(%d+0.5)2^%d" % (M,l)
		mp = ldexp(fadd(M, 0.5, exact=True),l)
		yield w, st, mp

	# 2^m+2^(l-1) (so exactly the mid-point between 2^m-2^l and 2^m)
	for _ in range(N):
		w = randint(8,200)
		l = randint(-50, 50)
		m = w + l - 1
		st = "2^%d-2^%d" % (m,l-1)
		mp = fadd(ldexp(1,m), ldexp(1,l-1), exact=True)
		yield w, st, mp

	# -2^m-2^l (so exactly the mid-point between -2^m and -2^m-2^(l+1))
	for _ in range(N):
		w = randint(8,200)
		l = randint(-50, 50)
		m = w + l - 1
		st = "-2^%d-2^%d" % (m,l)
		mp = fadd(ldexp(-1,m), ldexp(-1,l), exact=True)
		yield w, st, mp
예제 #3
0
파일: formats.py 프로젝트: hidmic/ltitop
 def value_interval(self):
     with mpmath.workprec(self.wordlength + 1):  # wl bits is enough
         if self.signed:
             return interval(
                 -mpmath.ldexp(1, self.msb),
                 mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb))
         return interval(
             0,
             mpmath.ldexp(1, self.msb) - mpmath.ldexp(1, self.lsb))
예제 #4
0
	def minmax(self):
		"""Gives the interval a variable of this FPF may belong to.
		Returns:
			a tuple (min, max)
		"""
		with workprec(self._wl+1):      # wl bits is enough
			if self._signed:
				return -ldexp(1, self._msb), ldexp(1, self._msb) - ldexp(1, self.lsb)
			else:
				return 0, ldexp(1, self._msb+1) - ldexp(1, self.lsb)
 def rinfo(self, *, signed=True):
     if signed:
         epsilon = mpmath.ldexp(1, -self.wordlength + 1)
         limit = mpmath.ldexp(1, self.wordlength - 1)
         return MultiFormatArithmeticLogicUnit.Info(
             eps=epsilon, min=-limit, max=limit - 1
         )
     epsilon = mpmath.ldexp(1, -self.wordlength)
     limit = mpmath.ldexp(1, self.wordlength)
     return MultiFormatArithmeticLogicUnit.Info(
         eps=epsilon, min=mpmath.mp.zero, max=limit
     )
예제 #6
0
def quantize(c, shr, dtype=numpy.int64):
    assert numpy.all(shr >= 1)
    c = mpmath.matrix(
        [[mpmath.ldexp(c[i, j] + .5, int(shr[j]))
          for j in range(c.cols - 1)] + [c[i, c.cols - 1]]
         for i in range(c.rows)])
    return numpy.array([[int(mpmath.nint(c[i, j])) for j in range(c.cols)]
                        for i in range(c.rows)], dtype)
예제 #7
0
def decompose(x, gamma_pow, precision=40):
    with mp.workdps(2048):
        tail = x
        compressed = np.zeros(precision + 1)
        for i in xrange(precision + 1):
            if tail == 0:
                break
            tail, compressed[i] = mp.frac(tail), mp.floor(tail)
            tail = mp.ldexp(tail, gamma_pow)
        return compressed
예제 #8
0
def align(p, a, b, x_exp, bits, y_exp=None, epsilon=EPSILON):
    exp = intermediate_exp(p, a, b, epsilon) - bits
    if y_exp is not None:
        assert exp[0] <= y_exp
        exp[0] = y_exp
    #print('exp', exp)
    shr = exp[:-1] - exp[1:] - x_exp
    #print('shr', shr)
    return (mpmath.matrix(
        [[mpmath.ldexp(p[i, j], int(-exp[j])) for j in range(p.cols)]
         for i in range(p.rows)]), shr, exp)
예제 #9
0
def mpquantize(value, nbits, rounding_method):
    if isinstance(value, Interval):
        return Interval(
            lower_bound=mpquantize(
                value.lower_bound, nbits=nbits,
                rounding_method=rounding_method
            ),
            upper_bound=mpquantize(
                value.upper_bound, nbits=nbits,
                rounding_method=rounding_method
            )
        )
    if not mpmath.isfinite(value):
        raise ValueError(f'Cannot quantize non-finite value: {value}')
    return int(rounding_method(mpmath.ldexp(value, int(nbits))))
예제 #10
0
def iterSomeNumbers(N, pmax=50, wmax=100):
	"""Generate:
	 - N numbers that are powers of 2 (randomly choose between python floats and mpmath)
	 then
	 - N numbers that are close to some powers of 2 (mpmath or float approx.)
	    (in form +/-2^p +/- x*2^q , with p, q and x random, |p|<=pmax, |p-q|<=wmax and |x|<=1)
	 and finally
	 - N random numbers we can express with at least wmax bits (mpmath or float approx.)
	 Returns the string representation and the float/mp
	 """
	# some powers of 2
	for _ in range(N//10):
		sign = choice((0, 1))
		p = randint(-pmax, pmax)
		# float and mp
		pfloat = -2**p if sign else 2**p
		mp = ldexp(-1 if sign else 1, p)
		usemp = choice((True, False))
		# str
		st = "%s(%s2^%d)" % ('mpf' if usemp else 'float', '-' if sign else '', p)
		yield st, mp if usemp else pfloat

	# some +/-2^p +/- x*2^q , with p, q and x random, |p|<=pmax, |p-q|<=wmax and |x|<=1
	for _ in range(N):
		# build signs, p, q and x
		signp = choice((0, 1))
		signq = choice((0, 1))
		p = randint(-pmax, pmax)
		q = p - randint(0, wmax)
		x = random()
		usemp = choice((True, False))
		st, mp = twoMinusXtwo(signp, p, signq, q, x)
		yield "%s(%s)" % ('mpf' if usemp else 'float',st), mp if usemp else float(mp)

	# some random numbers we can express with at least wmax bits (mpmath or float approx.)
	for _ in range(N):
		st = [ choice("0123456789") for _ in range(randint(int(wmax/2/3.3), int(wmax/3.3)))]
		pos = randint(0,len(st))
		st.insert(pos, ".")
		st = "".join(st)
		yield st, mpf(st)
예제 #11
0
파일: formats.py 프로젝트: hidmic/ltitop
 def value_epsilon(self):
     return mpmath.ldexp(1, self.lsb)
예제 #12
0
파일: Constant.py 프로젝트: fixif/FxP
    def __init__(self,
                 value,
                 wl=None,
                 signed=None,
                 fpf=None,
                 method='float',
                 name=None):
        """Constructs a constant object, from a real value (something that mpmath can handle, so a float or a string).
		 It could be build with wl bits (and signedness) OR (exclusive) with the given fpf
		Parameters:
		- value: (float or mpf) the real value of the constant
		- wl: (positive integer) word-length
		- signed: (boolean) True if signed fixed-point arithmetic is used, False if unsigned arithmetic
		- fpf: (FPF) Fixed-Point Format
		- method: (string) should be
				'float' (default) for using the mantissa from floating-point conversion (using mpmath if it's a string)
				'Benoit' for using Benoit's method (see "Reliable Implementation of Linear Filters with Fixed-Point Arithmetic", Hilaire and Lopez, 2013)
				'log' using the complete logarithm-based formula
				-> Of course, the 3 methods returns the same results
		Raises:
			ValueError if the parameters' values are not coherent
		"""
        # combination of arguments (wl AND signed) XOR fpf
        if wl is not None and fpf is not None:
            raise ValueError(
                "Bad combination of arguments: cannot give a word-length and a FPF in the same time"
            )
        if wl is None and fpf is None:
            raise ValueError(
                "Bad combination of arguments: no wordlength or FPF given")
        if wl is not None and wl < 2:
            raise ValueError(
                "Constant: The word-length should be at least equal to 2")
        if signed is None:
            if fpf is None:
                signed = True
            else:
                signed = fpf.signed

        # store name
        if name:
            self._name = name
        else:
            self._name = str(value)

        # store the exact value given (string, float or mpf) and it's mp math conversion (losslessly)
        self._value = value
        mpvalue = mpmathify(value)

        # check for non-sense values
        if signed is False and mpvalue < 0:
            raise ValueError("Unsigned FPF with negative constant !!")

        # treat null constant
        if mpvalue == 0:
            self._mantissa = 0
            self._value = 0
            if fpf is not None:
                self._FPF = fpf
            else:
                self._FPF = FPF(wl=wl, lsb=0)  # arbitrary choose lsb=0

            # raise ValueError("zero cannot be stored in a Constant !!")
            return

        # conversion to a given FPF
        if fpf is not None:
            # do the conversion
            self._FPF = fpf
            self._mantissa = nint(ldexp(mpvalue, -fpf.lsb))
            self._value = ldexp(self._mantissa, fpf.lsb)
            # check if mantissa is ok
            if signed:
                if not (-2**(fpf.wl - 1) <= self._mantissa <=
                        (2**(fpf.wl - 1) - 1)):
                    raise ValueError(
                        "The constant cannot be converted to the FPF %s", fpf)
            else:
                if not (0 <= self._mantissa <= (2**fpf.wl - 1)):
                    raise ValueError(
                        "The constant cannot be converted to the FPF %s", fpf)
            # check underflow
            #TODO: add option to allow underflow (sometimes useful)
            if self._mantissa == 0:
                raise ValueError(
                    "Underflow during the conversion of the constant!")
            return

        # Otherwise, perform the best w-bit conversion (with different methods)
        if method == 'Benoit':
            # Benoit's method (ie log2 + check for special cases)
            # see "Reliable Implementation of Linear Filters with Fixed-Point Arithmetic", Hilaire and Lopez, 2013
            with workprec(20 * wl):  # "enough bits"
                # compute MSB
                # if fpf:
                # 	msb = fpf.msb
                if mpvalue > 0:
                    msb = int(floor(log(mpvalue, 2))) + (1 if signed else 0)
                else:
                    msb = int(ceil(log(-mpvalue, 2)))

                # compute mantissa
                self._mantissa = int(nint(ldexp(
                    mpvalue, (wl - msb - 1))))  # round-to-nearest even

                # check for particular case (when the quantized constant overpass the limit whereas the constant doesN'T)
                if self._mantissa == 2**(wl - (1 if signed else 0)):
                    # like for the case 127.8 on 8 bits unsigned...
                    msb += 1
                    self._mantissa = 2**(wl - (2 if signed else 1))
                elif self._mantissa == -2**(wl - 2):
                    # like -128.1 on 8 bits
                    msb -= 1
                    self._mantissa = -2**(wl - 1)

        elif method == 'log':
            # log2-based method (only based on logarithm base 2, with exact mp arithmetic)
            # that takes care of two's complement asymmetry
            with workprec(20 * wl + 1):  # enough ??
                # set the msb
                if mpvalue > 0:
                    corr = fsub(1,
                                ldexp(1, -wl + (0 if signed else -1)),
                                exact=True)
                    msb = int(floor(log(mpvalue / corr,
                                        2))) + (1 if signed else 0)
                else:
                    corr = fadd(1, ldexp(1, -wl + 1), exact=True)
                    msb = int(ceil(log(-mpvalue / corr, 2)))
                # set the lsb and the mantissa
                lsb = msb + 1 - wl
                self._mantissa = max(int(nint(ldexp(mpvalue, -lsb))),
                                     -2**(wl - 1))  # round-to-nearest even

        elif method == 'threshold':
            # compute the minimum wordlength where the constant is not a special case (boundaries)
            with workprec(20 * wl):  # enough?
                # compute wmin
                if mpvalue > 0:
                    fr = mpvalue / 2**floor(log(
                        mpvalue, 2))  # fr = 2**frac(log(mpvalue, 2))
                    if fr < 2:
                        wmin = int(
                            floor(-log(2 - fr, 2))) + (2 if signed else 1)
                    else:
                        # should not happen when fr is computed with infinite precision... here, it happens
                        wmin = mpf('+inf')
                else:
                    fr = -mpvalue / 2**ceil(log(-mpvalue, 2))
                    wmin = int(floor(-log(2 * fr - 1, 2)) + 2)
                # compute msb
                if mpvalue > 0:
                    msb = int(floor(log(mpvalue, 2))) + (
                        1 if signed else 0) + (1 if wl < wmin else 0)
                else:
                    msb = int(ceil(log(-mpvalue, 2))) - (1 if wl < wmin else 0)
                # compute lsb and mantissa
                lsb = msb + 1 - wl
                self._mantissa = max(int(nint(ldexp(mpvalue, -lsb))),
                                     -2**(wl - 1))  # round-to-nearest even

        else:
            # default method
            # since the value is already transformed in floating-point (mantissa + exponent) with mpmath
            # we can use that mantissa and exponent (be careful of the two's complement asymmetry, -2^p is ok with msb=p)
            with workprec(20 * wl):

                # floating-point with the right word-length
                fl = mpf(value, prec=wl - (1 if signed else 0))
                # since mpmath do not have the integral significant (with MSB=1), we take the normalized significant
                # and build the mantissa (M) and exponent (e)
                m, ep = frexp(fl)
                M = ldexp(m, wl - (1 if signed else 0))
                e = ep - wl + (1 if signed else 0)
                # FxP mantissa, msb and lsb
                self._mantissa = int(M)
                lsb = e
                msb = wl + lsb - 1
                if self._mantissa == -2**(wl - 2):
                    lsb -= 1
                    msb -= 1
                    self._mantissa = -2**(wl - 1)

        # associated FPF
        self._FPF = FPF(wl=wl, msb=msb, signed=signed)
예제 #13
0
파일: Constant.py 프로젝트: fixif/FxP
 def approx(self):
     """Return the approximation of the constant with the chosen fixed-point format"""
     return ldexp(self._mantissa, self._FPF.lsb)
예제 #14
0
def twoMinusXtwo(signp, p, signq, q, x):
	"""Returns a string and a mp number in form +/-2^p +/- x*2^q"""
	mp = fadd(ldexp(-1 if signp else 1, p), ldexp(-x if signq else x, q), exact=True)
	st = "%s2^%d %s%s*2^%d" % ('-' if signp else '', p, '-' if signq else '+', x.hex(), q)
	return st, mp