def SoP(R, u_bar, w_txyu, w_z, latex=None): # FPF of t, x, u and y zeta_bar = R.Hzeta.WCPG() * u_bar FPF_txy = array([Constant(value=z[0, 0], wl=w_txyu).FPF for z in zeta_bar]) FPF_txu = r_[FPF_txy[:-1], Constant(value=u_bar, wl=w_txyu).FPF] # Coefficients FPF_Z = vectorize(lambda x: Constant(value=x, wl=w_z).FPF)(R.Zcomp) # print(FPF_Z) # var Names varT = [v.toStr() for v in R._varNameT] varX = [v.toStr() for v in R._varNameX] varU = [v.toStr() for v in R._varNameU] varTXU = varT + varX + varU varXp1 = [v.toStr(suffix='p' if R.isPnut() else '') for v in R._varNameX] varY = [v.toStr() for v in R._varNameY] varTXY = varT + varXp1 + varY # SoP for i in range(R.Z.shape[0]): str, fsop = strSOP(varTXY[i], FPF_txy[i], R.Zcomp[i, :].tolist()[0], FPF_Z[i, :].tolist()[0], varTXU, FPF_txu) print(str) print('\n'.join(f.ParenthesisNotation() for f in fsop))
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)
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]
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)
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
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
def quant(x, wl): """Simple function to quantized x with w bits (fixed-point style)""" return Constant(x, wl=wl, signed=True).approx if x else 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))