Пример #1
0
def testZero():
	""" Check value zero. """
	c = Constant(value=0, wl=8)
	assert(c.FPF == FPF(msb=7, lsb=0))

	c = Constant(value=0.0, wl=8)
	assert (c.FPF == FPF(msb=7, lsb=0))

	c = Constant(value="0", wl=8)
	assert (c.FPF == FPF(msb=7, lsb=0))

	c = Constant(value=mpf(0), wl=8)
	assert (c.FPF == FPF(msb=7, lsb=0))

	# with FPF:
	f = FPF(msb=7, lsb=-1)
	c = Constant(value=0, fpf=f)
	assert (c.FPF == f)

	c = Constant(value=0.0, fpf=f)
	assert (c.FPF == f)

	c = Constant(value="0", fpf=f)
	assert (c.FPF == f)

	c = Constant(value=mpf(0), fpf=f)
	assert (c.FPF == f)
Пример #2
0
    def __init__(self, constants, varNames, varFPF, resName, resFPF):
        """
		Build a SoP
		:param constants: list of constants (Constant objects)
		:param varNames: list of names (VarName objects) for the variables v_i
		:param varFPF: list of FPF for the variables v_i
		:param resName: name (VarName) of the result
		:param resFPF: FPF of the result
		"""
        # store the values
        self._constants = constants
        self._varFPF = varFPF
        self._resFPF = resFPF
        # each constant should be a Constant
        if any(not isinstance(c, Constant) for c in constants):
            raise ValueError(
                "The constants should be a list of Constant objects (defined in Fixif.FxP)"
            )
        # check the sizes
        if len({len(constants), len(varNames), len(varFPF)}) != 1:
            raise ValueError(
                "The Constnants, the list of names and the list of FPF should have the same size!"
            )
        # compute the FxP format of the products
        self._productFPF = [
            FPF(msb=v.msb + c.FPF.msb, lsb=v.lsb + c.FPF.lsb)
            for v, c in zip(varFPF, constants)
        ]
        # initialize the SoP
        super(FxPSoP, self).__init__([c.value for c in constants], varNames,
                                     resName)
Пример #3
0
def Sum_service(outputFormat):
	"""Generate Sum of FPF image (or LaTeX)"""
	try:
		# get data
		formats = request.query.sum.split(":")
		# build each FPF
		F = [FPF(formatStr=f.replace('_', '.')) for f in formats]
		resultFPF = FPF(formatStr=request.query.result.replace('_', '.'))
	except ValueError:
		return "Invalid Fixed-Point Formats"  # TODO: message d'erreur plus explicite ?
	# process the options
	options = optionManager(request.query)
	options.addOptionalOption("colors", colorThemes, "YG")  # color theme
	options.addOptionalOption("width", lambda x: int(x), '500')  # used for jpg, png, tiff only
	options.addOptionalOption("height", lambda x: int(x), '1300')  # used for jpg, png, tiff only (default value is very large, to let the user specify width=2000 without being blocked by the height:300)
	options.addOptionalOption("axis", {"yes": True, "no": False}, "no")  # display a vertical axis on bit=0
	options.addOptionalOption("sort", ("no", "lsb", "msb"), "no")
	options.addOptionalOption("hatches", {"yes": True, "no": False}, "no")  # display hatches for the bits outside the FPF of the result
	options.addOptionalOption("xshift", lambda x: float(x), '0')
	options.addOptionalOption("yshift", lambda x: float(x), '0')
	# build the LaTeX from the FxP SoP (fake SoP with constant equal to 1 and variable with msb decreased by 1)
	sop = FxPSoP([Constant(1, wl=2) for _ in F], ["" for _ in F], [FPF(msb=f.msb-1, lsb=f.lsb) for f in F], ["" for _ in F], resultFPF)
	latexFPF = sop.sumLaTeX(**options.getValues())
	# generate the files
	sumName = "-".join([f.Qnotation() for f in F + [resultFPF]])
	if outputFormat != 'tex':
		# prepare the conversion argument (in the LaTeX class 'standalone')
		if outputFormat != "pdf":
			convert = "convert={size=%dx%d,outext=.%s}," % (options['width'], options['height'], outputFormat)
		else:
			convert = ""
		# encompass it into a complete latex file
		latexStr = template("latex-FPF.tex",
		                    options.getValues({"FPF": latexFPF, "format": outputFormat, "convert": convert}))
		# create the image from the latex
		return createImageFromLaTeX(sumName + "?" + str(options), latexStr, outputFormat)
	else:
		return "\t%Generated from " + Config.baseURL + "Sum.tex?" + request.query_string + "\n" + latexFPF
Пример #4
0
def aSoP_submit():
	"""Manage the aSoP data"""
	# get data
	constants = request.forms.get('constants').split("\r\n")
	var_FPF = request.forms.get('var_FPF').split("\r\n")
	var_wi = request.forms.get('var_wi').split("\r\n")
	beta_final = request.forms.get('beta_final')
	# conversion
	try:
		beta_final = float(beta_final)
	except ValueError:
		return "the beta final is not valid"

	cons = []
	for c in constants:
		try:
			c_v, c_w = c.split(',')
			cons.append(Constant(float(c_v), int(c_w)))
		except ValueError:
			return "The constants cannot be converted to float"

	try:
		_ = [FPF(formatStr=f) for f in var_FPF]
	except ValueError:
		return "Invalid FPF format"

	var_w = []  # variable wordlength
	var_i = []  # variable interval
	for wi in var_wi:
		try:
			w, i1, i2 = wi.split(',')
			var_w.append(int(w))
			var_i.append((float(i1), float(i2)))
		except ValueError:
			return "Invalid wordlength,inteval format"
	# now call Benoit's function to do the aSoP...
	interval_var = []
	for w, i in zip(var_w, var_i):
		interval_var.append(Variable(value_inf=i[0], value_sup=i[1], wl=w))  # beta=w changed in wl=w
	return simple_cleaned_SoP(cons, interval_var, beta_final)
Пример #5
0
def iterSomeFPF(N):
    for _ in range(N):
        w = randint(2, 30)
        m = randint(-30, 30)
        s = choice([True, False])
        yield FPF(wl=w, msb=m, signed=s)
Пример #6
0
def test_construct():
    """Unit test for the FPF constructor"""
    # construct FPF with less than 2 args
    with pytest.raises(ValueError):
        FPF(16)
    with pytest.raises(ValueError):
        FPF(msb=12)
    with pytest.raises(ValueError):
        FPF(lsb=-6)

    # construct with wrong wl
    with pytest.raises(ValueError):
        FPF(wl=-12, msb=6)
    with pytest.raises(ValueError):
        FPF(wl=1, msb=6, signed=True)

    # construct FPF with only wl and (lsb or msb)
    f = FPF(16, lsb=-12)
    assert (f.wml() == (16, 3, -12))
    f = FPF(16, msb=3)
    assert (f.wml() == (16, 3, -12))
    f = FPF(16, msb=0)
    assert (f.wml() == (16, 0, -15))
    with pytest.raises(ValueError):
        FPF(16, 12, -5)

    # construct form string
    f = FPF(formatStr="Q8.12")
    assert (f.wml() == (20, 7, -12))
    f = FPF(formatStr="sQ4.3")
    assert (f.wml() == (7, 3, -3))
    f = FPF(formatStr="uQ4.3")
    assert (f.wml() == (7, 3, -3))
    f = FPF(formatStr="(8,-12)")
    assert (f.wml() == (21, 8, -12))
    f = FPF(formatStr="u(8,-12)")
    assert (f.signed is False)
    assert (f.wml() == (21, 8, -12))
    with pytest.raises(ValueError):
        FPF(formatStr="totoQ6.8")

    f = FPF(msb=7, lsb=0, signed=True)
    assert (f.minmax() == (-128, 127))
    f = FPF(msb=7, lsb=0, signed=False)
    assert (f.minmax() == (0, 255))
Пример #7
0
def test_notation(fpf):
    assert (FPF(formatStr=fpf.Qnotation()) == fpf)
    assert (FPF(formatStr=fpf.ParenthesisNotation()) == fpf)
    assert (FPF(formatStr=repr(fpf)) == fpf)
    str(fpf)
Пример #8
0
def mulFPF(F1, F2):
    """FPF of a multiplication"""
    return FPF(wl=F1.wl + F2.wl, msb=F1.msb + F2.msb)
Пример #9
0
def FPF_service(FPForm, outputFormat):
	"""
	Service that generates a FPF image (or LaTeX or informations encapsulated in json) from a FPF description
	Ex: answer to /FPF/uQ3.5.pdf?option1=value1&option2=value2
	Process the request, to produce the FPF `FPForm` in the format `outputFormat` with the various options taken from the request
	
	The FPF should be given in Q-notation or in Parentheses-notation
	The outputFormat can be image ('pdf','jpg','png','tiff' or 'eps' (see utilities.imageFormats)), 'tex' or 'json' 
	
	Possible options:
		colors: indicates the color theme ('YG' for yellow and green, 'BG' for black and white, etc.)
		binary_point: (boolean) indicates if the binary point is displayed 
		numeric: (boolean) display numeric values (instead of symbolic) if True
		notation: use MSB/LSB notation if 'mlsb', or integer/fractional part if 'ifwl'
		label: indicates where to display the label ('left'/'right'/'above'/'below' or 'no' if the label should not be displayed)
		intfrac: (boolean) display integer/fractional parts if True
		power2: (boolean) display power-of-2 if True 
		height: image's height (for jpg, png, tiff only)
		widht: image's width (for jpg, png, tiff only)
		bits: binary value to be displayed (nothing if no bit is given)
	"""
	# check if the FPF is valid

	# TODO: Change the name of the generated file:
	"""
	Qd on demande une constante sur un grand nombre de bits (j'ai fait 124 bits), on a l'erreur suivante:
	127.0.0.1 - - [24/Jul/2017 22:18:52] "GET /Constant/121545@12121?WL=125 HTTP/1.1" 200 22523
	cp: cache/Q18_107?numeric=no&power2=no&intfrac=no&bits=01110110101100100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&width=500&binary_point=yes&notation=mlsb&drawMissing=no&label=no&height=1300&y_origin=0&colors=RB.jpg: File name too long
	Cela est du au fait que le champs bits est trop grand, ce qui donne un nom de fichier stocké en cache trop grand. Une solution pourrait-être de former le nom du fichier autrement : en stockant un hash (genre md5) pour le nom du fichier dès que le nom devient trop grand. On peut aussi, au lieu de stocker tous les bits dans le nom, juste stocker la même chose en décimal (ou en hexa), mais cela ne fait que repousser le problème.
	À mon avis, la bonne solution est de faire un mélange des deux (on ne met plus "bits=...." dans le nom du fichier, mais value=..., et dès que le nom du fichier dépasse le nombre maximum de caractères pour un fichier (255 sous Mac, 4069 sous Unix, le tout étant défini dans limits.h, cf https://stackoverflow.com/questions/32807560/how-do-i-get-in-python-the-maximum-filesystem-path-length-in-unix)
	"""

	FPForm = FPForm.replace('_', '.')  # allow '_' (underscore) characters, and translate them in '.' (point)
	try:
		F = FPF(formatStr=FPForm)
	except ValueError:
		return {'error': "Invalid FPF format"}
	# process the options
	options = optionManager(request.query)
	options.addOptionalOption("colors", colorThemes, "YG")  # color theme
	options.addOptionalOption("binary_point", {"yes": True, "no": False}, "no")  # show the binary-point
	options.addOptionalOption("numeric", {"yes": True, "no": False}, "no")  # display numeric values (instead of symbolic)
	options.addOptionalOption("notation", ("mlsb", "ifwl"), "mlsb")  # notation chosen for the display (MSB/LSB or integer/fractional part)
	options.addOptionalOption("label", ('no', 'left', 'right', 'above', 'below'), 'no')  # display the label
	options.addOptionalOption("intfrac", {"yes": True, "no": False}, "no")  # display the integer/fractional part
	options.addOptionalOption("power2", {"yes": True, "no": False}, "no")  # display the power-of-2
	options.addOptionalOption("width", lambda x: int(x), '500')  # used for jpg, png, tiff only
	options.addOptionalOption("height", lambda x: int(x), '1300')  # used for jpg, png, tiff only (default value is very large, to let the user specify width=2000 without being blocked by the height:300)
	options.addOptionalOption("bits", lambda x: str(x), "")  # value of the bits to be displayed
	options.addOptionalOption("y_origin", lambda x: float(x), "0")
	options.addOptionalOption("drawMissing", {"yes": True, "no": False}, "no")
	# generate LaTeX code for the FPF only
	latexFPF = F.LaTeX(**options.getValues())

	# initializing the hash object
	m = hashlib.md5()
	m.update(str(options).encode('UTF-16'))

	# create and return image (or latex code)
	if outputFormat != 'tex' and outputFormat != 'json':
		# prepare the conversion argument (in the LaTeX class 'standalone')
		if outputFormat != "pdf":
			convert = "convert={size=%dx%d,outext=.%s}," % (options['width'], options['height'], outputFormat)
		else:
			convert = ""
		# encompass it into a complete latex file
		latexStr = template("latex-FPF.tex", options.getValues({"FPF": latexFPF, "format": outputFormat, "convert": convert}))
		# and create the image from the latex
		return createImageFromLaTeX(F.Qnotation().replace('.', '_') + "?" + m.hexdigest(), latexStr, outputFormat)
	elif outputFormat == 'json':
		return {'latex': latexFPF, 'interval': '[%f;%f]' % F.minmax(), 'quantization': '2^%d = %f' % (F.lsb, 2 ** F.lsb)}
	else:
		return "\t%Generated from " + Config.baseURL + "FPF/" + FPForm + ".tex?" + request.query_string + "\n" + latexFPF
Пример #10
0
def Constant_service(constantsInter):
	"""Service that generates all the information for the transformation of a constant
	It returns a JSON object, containing dictionaries of: the FPF, the integer associated, the errors, etc. of the constants and intervals given in constantsInter.
	Ex: answer to /Constant/zzzz?option1=xxx&option2=yyy
	where zzzz is string of constants or a intervals seperated by @
	
	Possible options:
		FPF: string describing the FPF (Q-notation or parenthesis notation) 
		WL: word-length
			-> only one of these two options should be given !
		signed: (bool) indicates if the constant is represented with a signed constant

	It returns a json object containing dictionaries related to each constant or interval with the following fields
		error: (string) indicates if there is an error
		FPF: (string) the FPF used for the conversion (usefull if the WL was given)
		FPF_image: (url) the url used for the image of the FPF
	and for a constant (not for an interval)	
		integer: the associated Fixed-Point integer
		bits: 2's complement binary of the integer
		approx: the approximated value
		error_abs: absolute error
		error_rel: relative error"""
	# get the FPF
	q = request.query
	if "FPF" in q:
		try:
			F = FPF(formatStr=q["FPF"])
			WL = None
		except ValueError:
			return {"error": "invalid FPF"}
	# or get the word-length
	elif "WL" not in q:
		# return {'error':"At least one option 'FPF' or 'WL' must be given"}
		WL = 8
		F = None
	else:
		try:
			WL = int(q["WL"])
		except ValueError:
			return {"error": " The Word-length must be an integer"}
		F = None
	# and get the signedness
	if "signed" in q:
		signed = q["signed"] != 'no'
	else:
		signed = True

	returningJson = {}


	exps = []   # List containing input constants / intervals / their evaluation.

	# Treating the raw input from client:
	for i in range(0, len(constantsInter.split("@"))):
		line = constantsInter.split("@")[i].replace("div", "/")  # replacing div with the real division sign
		line = line.strip()
		if len(line) > 0:  # empty strings shouldn't be treated
			try:    # if it's a normal constant then it should simply be added to exps
				Constant(value=line, wl=100, signed=signed)
				exps.append({'exp': line, 'val': line, 'const': True})
			except ValueError:     # it's either an interval or a mathematical expression that needs to be evaluated
				if line[0] == '[':  # Since the input format is once validated in client side, we can simply use this condition to determine whether it's an interval or not
					if WL:
						exps.append({'exp': line, 'val': get_interval_inf(line, WL), 'const': False})
					else:
						exps.append({'exp': line, 'val': get_interval_inf(line, F.wl), 'const': False})
				else:   # Not an interval but a mathematical expression that needs to be evaluated
					if WL:
						exps.append({'exp': line, 'val': evaluate_exp(line, WL), 'const': True})
					else:
						exps.append({'exp': line, 'val': evaluate_exp(line, F.wl), 'const': True})

	counter = 0
	for expression in exps:
		constInter = expression['val']
		if len(constInter) != 0:
			inter = reobj_interval.match(constInter)  # is it an interval ?

			# get the constant
			if expression['const'] and expression['val'] != "NaN":
				try:
					C = Constant(value=expression['val'], wl=WL, signed=signed, fpf=F)
					dico = return_dictionary_constant(C)
					dico['value'] = expression['exp']
					returningJson[counter] = dico
				except ValueError:
					Cs = Constant(value=expression['val'], wl=F.wl, signed=signed)
					dico = return_dictionary_constant(Cs)
					dico['value'] = expression['exp']
					errStr = "Not possible with the asked FPF; suggestion: " + str(Cs.FPF)
					dico["error"] = errStr
					returningJson[counter] = dico
			elif inter:
				try:
					val_inf = float(inter.group(1))
					val_sup = float(inter.group(2))
				# TODO: conversion str->float... faire avec GMP?
				except ValueError:
					returningJson[counter] = {'value': expression['exp'], 'error': 'The interval must be of the form [xxx;yyy] where xxx and yyy are litteral'}
				try:
					if WL:
						C = Constant(value=val_sup, wl=WL)
						if float(Constant(value=val_inf, wl=WL).FPF.msb) > float(C.FPF.msb):
							C = Constant(value=val_inf, wl=WL)
					else:
						C = Constant(value=val_sup, fpf=F)
						if float(Constant(value=val_inf, fpf=F).FPF.msb) > float(C.FPF.msb):
							C = Constant(value=val_inf, fpf=F)
					dico = return_dictionary_constant(C)
					dico["value"] = expression['exp']
					returningJson[counter] = dico
				except ValueError:  # None of the interval values could be represented with the given format
					Cs = Constant(value=val_sup, wl=F.wl, signed=signed)
					if float(Constant(value=val_inf, wl=F.wl).FPF.msb) > float(Cs.FPF.msb):
						Cs = Constant(value=val_inf, wl=F.wl)
					dico = return_dictionary_constant(Cs)
					dico["value"] = expression['exp']
					errStr = "Not possible with the asked FPF; suggestion: " + str(Cs.FPF)
					dico["error"] = errStr
					returningJson[counter] = dico
			else:
				if expression["val"] != "NaN":
					returningJson[counter] = {
						'value': expression['exp'],
						'error': "The url should contain the constant or the interval (ex '/Constant/12.44' or '/Constant/[-120;10])'"
					}  # General Error
				else:
					returningJson[counter] = {
						'value': expression['exp'],
						'error': "Arithmetic problem"
					}
			counter += 1
	return returningJson
Пример #11
0
def test_construct(method):
	"""
	Test the Constant constructor
	"""
	c = Constant(value=127, wl=8, signed=False, method=method)
	assert(c.FPF.wml() == (8, 6, -1))
	assert(c.mantissa == 254)

	c = Constant(value=127, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == 127)
	
	c = Constant(value=-127, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == -127)
	
	c = Constant(value=0.36567, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, -1, -8))
	assert(c.mantissa == 94)
	assert(c.approx == 94*2**-8)
	
	with pytest.raises(ValueError):
		Constant(value=-12, wl=12, signed=False, method=method)

	with pytest.raises(ValueError):
		Constant(value=42, wl=1)

	# particular cases
	c = Constant(value=127.78, wl=8, signed=False, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == 128)
	c = Constant(value=-128.1, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == -128)
	c = Constant(value=127.7, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 8, 1))
	assert(c.mantissa == 64)
	
	c = Constant(value=-128.25, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == -128)
	c = Constant(value=-128.5, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == -128)
	c = Constant(value=-128.6, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))
	assert(c.mantissa == -128)
	c = Constant(value=-129, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 7, 0))        # tie to even (otherwise, with ties to away, it should be (8,8,1), and mantissa=-65
	assert(c.mantissa == -128)
	c = Constant(value=-129.01, wl=8, signed=True, method=method)
	assert(c.FPF.wml() == (8, 8, 1))
	assert(c.mantissa == -65)


	# wrong combination of arguments
	with pytest.raises(ValueError):
		Constant(value=12)
	with pytest.raises(ValueError):
		Constant(value=12, signed=True)
	with pytest.raises(ValueError):
		Constant(value=12, wl=5, fpf=FPF(8, 7, 0))

	# construct with a given FPF
	with pytest.raises(ValueError):
		Constant(value=258.54, wl=8, fpf=FPF(8, 7, 0))
	c = Constant(value=127.1, fpf=FPF(8, 7, 0))
	assert(c.FPF.wml() == (8, 7, 0))
	with pytest.raises(ValueError):
		Constant(value=132, fpf=FPF(8, 7, 0, signed=True))
	with pytest.raises(ValueError):
		Constant(value=300,  fpf=FPF(8, 7, 0, signed=False))
	with pytest.raises(ValueError):
		Constant(value=0.123, fpf=FPF(8, 7, 0))