From 1621e22e7758046e1262b22410a48250388abf29 Mon Sep 17 00:00:00 2001 From: Dietrich Date: Mon, 20 Apr 2015 14:56:59 -0600 Subject: renamed fp32 to BigFloat --- Source/Basetypes/BigFloat.cs | 397 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) create mode 100644 Source/Basetypes/BigFloat.cs (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs new file mode 100644 index 00000000..d1ee73a4 --- /dev/null +++ b/Source/Basetypes/BigFloat.cs @@ -0,0 +1,397 @@ +//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.Diagnostics; + +namespace Microsoft.Basetypes +{ + using BIM = System.Numerics.BigInteger; + + /// + /// A representation of a 32-bit floating point value + /// Note that this value has a 1-bit sign, 8-bit exponent, and 23-bit mantissa + /// + public struct BigFloat + { + //Please note that this code outline is copy-pasted from BigDec.cs + + // the internal representation + [Rep] + internal readonly BIM mantissa; //TODO: restrict mantissa to be 23-bits wide + [Rep] + internal readonly int exponent; //TODO: restrict exponent to be 8-bits wide + [Rep] + internal readonly Boolean isNegative; //represents the sign bit + + public BIM Mantissa { + get { + return mantissa; + } + } + + public int Exponent { + get { + return exponent; + } + } + + public static readonly BigFloat ZERO = FromInt(0); + private static readonly BIM two = new BIM(2); + private static readonly BIM ten = new BIM(10); + + + //////////////////////////////////////////////////////////////////////////// + // Constructors + + //Please note that these constructors will be called throughout boogie + //For a complete summary of where this class has been added, simply view constructor references + + [Pure] + public static BigFloat FromInt(int v) { + return new BigFloat(v, 0, v < 0); //TODO: modify for correct fp representation + } + + [Pure] + public static BigFloat FromBigInt(BIM v) { + return new BigFloat(v, 0, v < 0); //TODO: modify for correct fp representation + } + + [Pure] + public static BigFloat FromString(string v) { + //TODO: completely copied from BigDec.cs at the moment + if (v == null) throw new FormatException(); + + BIM integral = BIM.Zero; + BIM fraction = BIM.Zero; + int exponent = 0; + + int len = v.Length; + + int i = v.IndexOf('e'); + if (i >= 0) { + if (i + 1 == v.Length) throw new FormatException(); + exponent = Int32.Parse(v.Substring(i + 1, len - i - 1)); + len = i; + } + + int fractionLen = 0; + i = v.IndexOf('.'); + if (i >= 0) { + if (i + 1 == v.Length) throw new FormatException(); + fractionLen = len - i - 1; + fraction = BIM.Parse(v.Substring(i + 1, fractionLen)); + len = i; + } + + integral = BIM.Parse(v.Substring(0, len)); + + if (!fraction.IsZero) { + while (fractionLen > 0) { + integral = integral * ten; + exponent = exponent - 1; + fractionLen = fractionLen - 1; + } + } + return new BigFloat(integral - fraction, exponent, integral.Sign == -1); + } + + internal BigFloat(BIM mantissa, int exponent, bool isNegative) { + this.isNegative = isNegative; + if (mantissa.IsZero) { + this.mantissa = mantissa; + this.exponent = 0; + } + else { + while (mantissa % ten == BIM.Zero) { //TODO: get this to work as expected :P + mantissa = mantissa / ten; + exponent = exponent + 1; + } + this.mantissa = mantissa; + this.exponent = exponent; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Basic object operations + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object obj) { + if (obj == null) + return false; + if (!(obj is BigFloat)) + return false; + + return (this == (BigFloat)obj); + } + + [Pure] + public override int GetHashCode() { + return this.mantissa.GetHashCode() * 13 + this.exponent.GetHashCode(); + } + + [Pure] + public override string/*!*/ ToString() { + //TODO: modify to reflect floating points + Contract.Ensures(Contract.Result() != null); + return String.Format("{0}e{1}", this.mantissa.ToString(), this.exponent.ToString()); + } + + + //////////////////////////////////////////////////////////////////////////// + // Conversion operations + + // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). + /// + /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative + /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way. + /// + /// The Floor (rounded towards negative infinity) + /// Ceiling (rounded towards positive infinity) + public void FloorCeiling(out BIM floor, out BIM ceiling) { + //TODO: fix for fp functionality + BIM n = this.mantissa; + int e = this.exponent; + if (n.IsZero) { + floor = ceiling = n; + } else if (0 <= e) { + // it's an integer + for (; 0 < e; e--) { + n = n * ten; + } + floor = ceiling = n; + } else { + // it's a non-zero integer, so the ceiling is one more than the floor + for (; e < 0 && !n.IsZero; e++) { + n = n / ten; // Division rounds towards negative infinity + } + + if (this.mantissa >= 0) { + floor = n; + ceiling = n + 1; + } else { + ceiling = n; + floor = n - 1; + } + } + Debug.Assert(floor <= ceiling, "Invariant was not maintained"); + } + + [Pure] + public String ToDecimalString(int maxDigits) { + //TODO: fix for fp functionality + string s = this.mantissa.ToString(); + int digits = (this.mantissa >= 0) ? s.Length : s.Length - 1; + BIM max = BIM.Pow(10, maxDigits); + BIM min = -max; + + if (this.exponent >= 0) { + if (maxDigits < digits || maxDigits - digits < this.exponent) { + return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString()); + } + else { + return String.Format("{0}{1}.0", s, new string('0', this.exponent)); + } + } + else { + int exp = -this.exponent; + + if (exp < digits) { + int intDigits = digits - exp; + if (maxDigits < intDigits) { + return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString()); + } + else { + int fracDigits = Math.Min(maxDigits, digits - intDigits); + return String.Format("{0}.{1}", s.Substring(0, intDigits), s.Substring(intDigits, fracDigits)); + } + } + else { + int fracDigits = Math.Min(maxDigits, digits); + return String.Format("0.{0}{1}", new string('0', exp - fracDigits), s.Substring(0, fracDigits)); + } + } + } + + [Pure] + public string ToDecimalString() { + //TODO: fix for fp functionality + string m = this.mantissa.ToString(); + var e = this.exponent; + if (0 <= this.exponent) { + return m + Zeros(e) + ".0"; + } else { + e = -e; + // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string) + var maxK = e < m.Length ? e : m.Length - 1; + var last = m.Length - 1; + var k = 0; + while (k < maxK && m[last - k] == '0') { + k++; + } + if (0 < k) { + // chop off the suffix of k zeros from m and adjust e accordingly + m = m.Substring(0, m.Length - k); + e -= k; + } + if (e == 0) { + return m; + } else if (e < m.Length) { + var n = m.Length - e; + return m.Substring(0, n) + "." + m.Substring(n); + } else { + return "0." + Zeros(e - m.Length) + m; + } + } + } + + [Pure] + public static string Zeros(int n) { + //TODO: fix for fp functionality + Contract.Requires(0 <= n); + if (n <= 10) { + var tenZeros = "0000000000"; + return tenZeros.Substring(0, n); + } else { + var d = n / 2; + var s = Zeros(d); + if (n % 2 == 0) { + return s + s; + } else { + return s + s + "0"; + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Basic arithmetic operations + + [Pure] + public BigFloat Abs { + //TODO: fix for fp functionality + get { + return new BigFloat(BIM.Abs(this.mantissa), this.exponent, false); + } + } + + [Pure] + public BigFloat Negate { + //TODO: Modify for correct fp functionality + get { + return new BigFloat(BIM.Negate(this.mantissa), this.exponent, this.Mantissa >= 0); + } + } + + [Pure] + public static BigFloat operator -(BigFloat x) { + return x.Negate; + } + + [Pure] + public static BigFloat operator +(BigFloat x, BigFloat y) { + //TODO: Modify for correct fp functionality + BIM m1 = x.mantissa; + int e1 = x.exponent; + BIM m2 = y.mantissa; + int e2 = y.exponent; + if (e2 < e1) { + m1 = y.mantissa; + e1 = y.exponent; + m2 = x.mantissa; + e2 = x.exponent; + } + + while (e2 > e1) { + m2 = m2 * ten; + e2 = e2 - 1; + } + + return new BigFloat(m1 + m2, e1, true); + } + + [Pure] + public static BigFloat operator -(BigFloat x, BigFloat y) { + return x + y.Negate; + } + + [Pure] + public static BigFloat operator *(BigFloat x, BigFloat y) { + //TODO: modify for correct fp functionality + return new BigFloat(x.mantissa * y.mantissa, x.exponent + y.exponent, false); + } + + + //////////////////////////////////////////////////////////////////////////// + // Some basic comparison operations + + public bool IsPositive { + get { + return (this.mantissa > BIM.Zero); + } + } + + public bool IsNegative { + get { + return (isNegative); + } + } + + public bool IsZero { + get { + return this.mantissa.IsZero; + } + } + + [Pure] + public int CompareTo(BigFloat that) { + //TODO: Modify for correct fp functionality + if (this.mantissa == that.mantissa && this.exponent == that.exponent) { + return 0; + } + else { + BigFloat d = this - that; + return d.IsNegative ? -1 : 1; + } + } + + [Pure] + public static bool operator ==(BigFloat x, BigFloat y) { + return x.CompareTo(y) == 0; + } + + [Pure] + public static bool operator !=(BigFloat x, BigFloat y) { + return x.CompareTo(y) != 0; + } + + [Pure] + public static bool operator <(BigFloat x, BigFloat y) { + return x.CompareTo(y) < 0; + } + + [Pure] + public static bool operator >(BigFloat x, BigFloat y) { + return x.CompareTo(y) > 0; + } + + [Pure] + public static bool operator <=(BigFloat x, BigFloat y) { + return x.CompareTo(y) <= 0; + } + + [Pure] + public static bool operator >=(BigFloat x, BigFloat y) { + return x.CompareTo(y) >= 0; + } + } +} -- cgit v1.2.3 From ed8913170a86b73dc14ba09e40de1eba0cad4c9d Mon Sep 17 00:00:00 2001 From: Dietrich Date: Mon, 4 May 2015 18:10:09 -0600 Subject: added general floating point mantissa and exponent management --- Source/Basetypes/BigFloat.cs | 78 ++++++++++++++++++++++++++------------------ Source/Core/Scanner.cs | 1 + float_test4.bpl | 6 ++++ 3 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 float_test4.bpl (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index d1ee73a4..7c8b6001 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -25,11 +25,13 @@ namespace Microsoft.Basetypes // the internal representation [Rep] - internal readonly BIM mantissa; //TODO: restrict mantissa to be 23-bits wide + internal readonly BIM mantissa; //TODO: restrict mantissa. Note that mantissa includes the sign [Rep] internal readonly int exponent; //TODO: restrict exponent to be 8-bits wide [Rep] - internal readonly Boolean isNegative; //represents the sign bit + internal readonly int mantissaSize; //Represents the maximum size of the mantissa + [Rep] + internal readonly int exponentSize; //Represents the maximum size of the exponent public BIM Mantissa { get { @@ -43,9 +45,24 @@ namespace Microsoft.Basetypes } } + public int MantissaSize + { + get + { + return mantissaSize; + } + } + + public int ExponentSize + { + get + { + return exponentSize; + } + } + public static readonly BigFloat ZERO = FromInt(0); private static readonly BIM two = new BIM(2); - private static readonly BIM ten = new BIM(10); //////////////////////////////////////////////////////////////////////////// @@ -56,17 +73,21 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat FromInt(int v) { - return new BigFloat(v, 0, v < 0); //TODO: modify for correct fp representation + return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation } [Pure] public static BigFloat FromBigInt(BIM v) { - return new BigFloat(v, 0, v < 0); //TODO: modify for correct fp representation + return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation + } + + public static BigFloat FromBigDec(BIM v) + { + return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation } [Pure] public static BigFloat FromString(string v) { - //TODO: completely copied from BigDec.cs at the moment if (v == null) throw new FormatException(); BIM integral = BIM.Zero; @@ -95,30 +116,25 @@ namespace Microsoft.Basetypes if (!fraction.IsZero) { while (fractionLen > 0) { - integral = integral * ten; + integral = integral * two; exponent = exponent - 1; fractionLen = fractionLen - 1; } } - return new BigFloat(integral - fraction, exponent, integral.Sign == -1); + return new BigFloat(integral - fraction, exponent, 23, 8); } - internal BigFloat(BIM mantissa, int exponent, bool isNegative) { - this.isNegative = isNegative; - if (mantissa.IsZero) { - this.mantissa = mantissa; - this.exponent = 0; - } - else { - while (mantissa % ten == BIM.Zero) { //TODO: get this to work as expected :P - mantissa = mantissa / ten; - exponent = exponent + 1; - } - this.mantissa = mantissa; - this.exponent = exponent; - } + internal BigFloat(BIM mantissa, int exponent, int mantissaSize, int exponentSize) { + this.mantissaSize = mantissaSize; + this.exponentSize = mantissaSize; + this.mantissa = mantissa; + this.exponent = exponent; } + private int maxMantissa() { return (int)Math.Pow(2, mantissaSize); } + private int maxExponent() { return (int)Math.Pow(2, exponentSize); } + + //////////////////////////////////////////////////////////////////////////// // Basic object operations @@ -166,13 +182,13 @@ namespace Microsoft.Basetypes } else if (0 <= e) { // it's an integer for (; 0 < e; e--) { - n = n * ten; + n = n * two; } floor = ceiling = n; } else { // it's a non-zero integer, so the ceiling is one more than the floor for (; e < 0 && !n.IsZero; e++) { - n = n / ten; // Division rounds towards negative infinity + n = n / two; // Division rounds towards negative infinity } if (this.mantissa >= 0) { @@ -280,7 +296,7 @@ namespace Microsoft.Basetypes public BigFloat Abs { //TODO: fix for fp functionality get { - return new BigFloat(BIM.Abs(this.mantissa), this.exponent, false); + return new BigFloat(BIM.Abs(this.mantissa), this.exponent, this.mantissaSize, this.exponentSize); } } @@ -288,7 +304,7 @@ namespace Microsoft.Basetypes public BigFloat Negate { //TODO: Modify for correct fp functionality get { - return new BigFloat(BIM.Negate(this.mantissa), this.exponent, this.Mantissa >= 0); + return new BigFloat(BIM.Negate(this.mantissa), this.exponent, this.mantissaSize, this.exponentSize); } } @@ -312,11 +328,11 @@ namespace Microsoft.Basetypes } while (e2 > e1) { - m2 = m2 * ten; + m2 = m2 * two; e2 = e2 - 1; } - return new BigFloat(m1 + m2, e1, true); + return new BigFloat(m1 + m2, e1, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); } [Pure] @@ -327,7 +343,7 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator *(BigFloat x, BigFloat y) { //TODO: modify for correct fp functionality - return new BigFloat(x.mantissa * y.mantissa, x.exponent + y.exponent, false); + return new BigFloat(x.mantissa * y.mantissa, x.exponent + y.exponent, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); } @@ -342,13 +358,13 @@ namespace Microsoft.Basetypes public bool IsNegative { get { - return (isNegative); + return (this.mantissa < BIM.Zero); } } public bool IsZero { get { - return this.mantissa.IsZero; + return this.mantissa.IsZero && this.exponent == 0; } } diff --git a/Source/Core/Scanner.cs b/Source/Core/Scanner.cs index c41d0a9e..bc294aba 100644 --- a/Source/Core/Scanner.cs +++ b/Source/Core/Scanner.cs @@ -508,6 +508,7 @@ public class Scanner { case "int": t.kind = 14; break; case "real": t.kind = 15; break; case "bool": t.kind = 16; break; + case "fp": t.kind = 97; break; case "float": t.kind = 98; break; case "const": t.kind = 21; break; case "unique": t.kind = 22; break; diff --git a/float_test4.bpl b/float_test4.bpl new file mode 100644 index 00000000..a962713b --- /dev/null +++ b/float_test4.bpl @@ -0,0 +1,6 @@ + procedure F() returns () { + var x : float; + var y : float; + y := x - x; + assert y == fp (0,0,23,8); +} \ No newline at end of file -- cgit v1.2.3 From f9df0e2ea8e0b03352f5bbba54f091f2ee25b161 Mon Sep 17 00:00:00 2001 From: Dietrich Date: Tue, 5 May 2015 04:50:47 -0600 Subject: added decimal reading functionality to the float type --- Source/AbsInt/IntervalDomain.cs | 2 +- Source/Basetypes/BigFloat.cs | 56 ++++++++++++++++++----------------------- Source/Core/Parser.cs | 33 +++++++++++++++++------- float_test4.bpl | 5 ++-- float_test5.bpl | 5 ++++ float_test6.bpl | 5 ++++ 6 files changed, 61 insertions(+), 45 deletions(-) create mode 100644 float_test5.bpl create mode 100644 float_test6.bpl (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs index 502b7075..a27ae68d 100644 --- a/Source/AbsInt/IntervalDomain.cs +++ b/Source/AbsInt/IntervalDomain.cs @@ -673,7 +673,7 @@ namespace Microsoft.Boogie.AbstractInterpretation Hi = ceiling; } else if (node.Val is BigFloat) { BigInteger floor, ceiling; - ((BigDec)node.Val).FloorCeiling(out floor, out ceiling); + ((BigFloat)node.Val).FloorCeiling(out floor, out ceiling); Lo = floor; Hi = ceiling; } else if (node.Val is bool) { diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 7c8b6001..d93f7d7b 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -88,40 +88,27 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat FromString(string v) { - if (v == null) throw new FormatException(); - - BIM integral = BIM.Zero; - BIM fraction = BIM.Zero; - int exponent = 0; - - int len = v.Length; - - int i = v.IndexOf('e'); - if (i >= 0) { - if (i + 1 == v.Length) throw new FormatException(); - exponent = Int32.Parse(v.Substring(i + 1, len - i - 1)); - len = i; - } - - int fractionLen = 0; - i = v.IndexOf('.'); - if (i >= 0) { - if (i + 1 == v.Length) throw new FormatException(); - fractionLen = len - i - 1; - fraction = BIM.Parse(v.Substring(i + 1, fractionLen)); - len = i; - } - - integral = BIM.Parse(v.Substring(0, len)); - - if (!fraction.IsZero) { - while (fractionLen > 0) { - integral = integral * two; - exponent = exponent - 1; - fractionLen = fractionLen - 1; + String[] vals = v.Split(' '); + if (vals.Length == 0 || vals.Length > 4) + throw new FormatException(); + try + { + switch (vals.Length) { + case 1: + return Round(decimal.Parse(vals[0]), 23, 8); + case 2: + return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), 23, 8); + case 3: + return Round(decimal.Parse(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2])); + case 4: + return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); + default: + throw new FormatException(); //Unreachable } } - return new BigFloat(integral - fraction, exponent, 23, 8); + catch (Exception) { //Catch parsing errors + throw new FormatException(); + } } internal BigFloat(BIM mantissa, int exponent, int mantissaSize, int exponentSize) { @@ -166,6 +153,11 @@ namespace Microsoft.Basetypes //////////////////////////////////////////////////////////////////////////// // Conversion operations + public static BigFloat Round(decimal d, int mantissaSize, int exponentSize) + { //TODO: round the given decimal to the nearest fp value + return new BigFloat(0, 0, mantissaSize, exponentSize); + } + // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). /// /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index b333f654..7335dd37 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -1879,15 +1879,29 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { { //To be modified string s = ""; - if (la.kind == 97) { - Get(); - s = t.val; - } else SynErr(128); - try { - n = BigFloat.FromString(s); - } catch (FormatException) { + try + { + if (la.kind == 97) + { + //Expected format = fp (a b) || fp (a b c d) + Get(); //Skip the fp token + Get(); + if (t.val != "(") { throw new FormatException(); } + while (la.kind == 3 || la.kind == 6) { //Get values between the parens + Get(); + s += t.val + " "; + } + Get(); + if (t.val != ")") { throw new FormatException(); } + } + else SynErr(137); + + n = BigFloat.FromString(s.Trim()); + } + catch (FormatException) + { this.SemErr("incorrectly formatted floating point"); - n = BigFloat.ZERO; + n = BigFloat.ZERO; } } @@ -2131,7 +2145,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x}, {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,T,T,T, T,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x} @@ -2301,6 +2315,7 @@ public class Errors { case 134: s = "invalid AttributeOrTrigger"; break; case 135: s = "invalid AttributeParameter"; break; case 136: s = "invalid QSep"; break; + case 137: s = "invalid Float"; break; default: s = "error " + n; break; } diff --git a/float_test4.bpl b/float_test4.bpl index a962713b..2388a281 100644 --- a/float_test4.bpl +++ b/float_test4.bpl @@ -1,6 +1,5 @@ procedure F() returns () { var x : float; - var y : float; - y := x - x; - assert y == fp (0,0,23,8); + x := fp (0 0); + assert x == fp (0 0 23 8); } \ No newline at end of file diff --git a/float_test5.bpl b/float_test5.bpl new file mode 100644 index 00000000..b91e53e9 --- /dev/null +++ b/float_test5.bpl @@ -0,0 +1,5 @@ + procedure F() returns () { + var x : float; + x := fp (0 0); + assert x == fp (1 0 23 8); +} \ No newline at end of file diff --git a/float_test6.bpl b/float_test6.bpl new file mode 100644 index 00000000..532798d6 --- /dev/null +++ b/float_test6.bpl @@ -0,0 +1,5 @@ + procedure F() returns () { + var x : float; + x := fp (1.5); + assert x == fp (1 0 23 8); +} \ No newline at end of file -- cgit v1.2.3 From c55533de9fc0b0bcc47cfca5fd26de93afac4d3b Mon Sep 17 00:00:00 2001 From: Dietrich Date: Thu, 7 May 2015 14:09:39 -0600 Subject: Made significant changes to internal representation of BigFloat. Remains a work in progress --- Source/Basetypes/BigFloat.cs | 114 ++++++++++++++++++++++++++----------------- float_test6.bpl | 4 +- float_test7.bpl | 5 ++ 3 files changed, 76 insertions(+), 47 deletions(-) create mode 100644 float_test7.bpl (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index d93f7d7b..0b35c237 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -25,23 +25,27 @@ namespace Microsoft.Basetypes // the internal representation [Rep] - internal readonly BIM mantissa; //TODO: restrict mantissa. Note that mantissa includes the sign + internal readonly Boolean[] mantissa; //Note that the first element of the mantissa array is the least significant bit for coding simplicity [Rep] - internal readonly int exponent; //TODO: restrict exponent to be 8-bits wide + internal readonly Boolean isNegative; //The left-most (sign) bit in the float representation [Rep] - internal readonly int mantissaSize; //Represents the maximum size of the mantissa + internal readonly int exponent; [Rep] - internal readonly int exponentSize; //Represents the maximum size of the exponent + internal readonly int exponentSize; //The maximum bit size of the exponent public BIM Mantissa { get { - return mantissa; + BIM toReturn = 0; + for (int i = 0; i < mantissa.Length; i++) + if (mantissa[i]) + toReturn += (int) Math.Pow(2, i); + return isNegative ? -toReturn : toReturn; } } public int Exponent { get { - return exponent; + return exponent - (int)Math.Pow(2, exponentSize - 1); //account for shift } } @@ -49,7 +53,7 @@ namespace Microsoft.Basetypes { get { - return mantissaSize; + return mantissa.Length; } } @@ -95,11 +99,11 @@ namespace Microsoft.Basetypes { switch (vals.Length) { case 1: - return Round(decimal.Parse(vals[0]), 23, 8); + return Round(vals[0], 23, 8); case 2: return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), 23, 8); case 3: - return Round(decimal.Parse(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2])); + return Round(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); case 4: return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); default: @@ -112,14 +116,17 @@ namespace Microsoft.Basetypes } internal BigFloat(BIM mantissa, int exponent, int mantissaSize, int exponentSize) { - this.mantissaSize = mantissaSize; - this.exponentSize = mantissaSize; - this.mantissa = mantissa; + this.mantissa = new Boolean[mantissaSize]; + this.exponentSize = exponentSize; this.exponent = exponent; + //TODO: Add overflow check for exponent vs exponent size + this.isNegative = mantissa < 0; + if (this.isNegative) + mantissa = -mantissa; } - private int maxMantissa() { return (int)Math.Pow(2, mantissaSize); } - private int maxExponent() { return (int)Math.Pow(2, exponentSize); } + private int maxExponent() { return (int)Math.Pow(2, exponentSize - 1) - 1; } + private int minExponent() { return -(int)Math.Pow(2, exponentSize - 1); } @@ -139,21 +146,38 @@ namespace Microsoft.Basetypes [Pure] public override int GetHashCode() { - return this.mantissa.GetHashCode() * 13 + this.exponent.GetHashCode(); + return Mantissa.GetHashCode() * 13 + Exponent.GetHashCode(); } [Pure] public override string/*!*/ ToString() { //TODO: modify to reflect floating points Contract.Ensures(Contract.Result() != null); - return String.Format("{0}e{1}", this.mantissa.ToString(), this.exponent.ToString()); + return String.Format("{0}e{1}", Mantissa.ToString(), Exponent.ToString()); } //////////////////////////////////////////////////////////////////////////// // Conversion operations - public static BigFloat Round(decimal d, int mantissaSize, int exponentSize) + public static BigFloat Round(String value, int mantissaSize, int exponentSize) + { + int i = value.IndexOf('.'); + if (i == -1) + return Round(BIM.Parse(value), 0, mantissaSize, exponentSize); + return Round(BIM.Parse(value.Substring(0, i - 1)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), mantissaSize, exponentSize); + } + + /// + /// Converts value.dec_value to a float with mantissaSize, exponentSize + /// Returns the result of this calculation + /// + /// + /// + /// + /// + /// + public static BigFloat Round(BIM value, BIM dec_value, int mantissaSize, int exponentSize) { //TODO: round the given decimal to the nearest fp value return new BigFloat(0, 0, mantissaSize, exponentSize); } @@ -167,8 +191,8 @@ namespace Microsoft.Basetypes /// Ceiling (rounded towards positive infinity) public void FloorCeiling(out BIM floor, out BIM ceiling) { //TODO: fix for fp functionality - BIM n = this.mantissa; - int e = this.exponent; + BIM n = Mantissa; + int e = Exponent; if (n.IsZero) { floor = ceiling = n; } else if (0 <= e) { @@ -183,7 +207,7 @@ namespace Microsoft.Basetypes n = n / two; // Division rounds towards negative infinity } - if (this.mantissa >= 0) { + if (!isNegative) { floor = n; ceiling = n + 1; } else { @@ -197,26 +221,26 @@ namespace Microsoft.Basetypes [Pure] public String ToDecimalString(int maxDigits) { //TODO: fix for fp functionality - string s = this.mantissa.ToString(); - int digits = (this.mantissa >= 0) ? s.Length : s.Length - 1; + string s = Mantissa.ToString(); + int digits = (isNegative) ? s.Length - 1 : s.Length; BIM max = BIM.Pow(10, maxDigits); BIM min = -max; - if (this.exponent >= 0) { - if (maxDigits < digits || maxDigits - digits < this.exponent) { - return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString()); + if (Exponent >= 0) { + if (maxDigits < digits || maxDigits - digits < Exponent) { + return String.Format("{0}.0", (!isNegative) ? max.ToString() : min.ToString()); } else { - return String.Format("{0}{1}.0", s, new string('0', this.exponent)); + return String.Format("{0}{1}.0", s, new string('0', Exponent)); } } else { - int exp = -this.exponent; + int exp = -Exponent; if (exp < digits) { int intDigits = digits - exp; if (maxDigits < intDigits) { - return String.Format("{0}.0", (this.mantissa >= 0) ? max.ToString() : min.ToString()); + return String.Format("{0}.0", (!isNegative) ? max.ToString() : min.ToString()); } else { int fracDigits = Math.Min(maxDigits, digits - intDigits); @@ -233,9 +257,9 @@ namespace Microsoft.Basetypes [Pure] public string ToDecimalString() { //TODO: fix for fp functionality - string m = this.mantissa.ToString(); - var e = this.exponent; - if (0 <= this.exponent) { + string m = Mantissa.ToString(); + var e = Exponent; + if (0 <= Exponent) { return m + Zeros(e) + ".0"; } else { e = -e; @@ -288,7 +312,7 @@ namespace Microsoft.Basetypes public BigFloat Abs { //TODO: fix for fp functionality get { - return new BigFloat(BIM.Abs(this.mantissa), this.exponent, this.mantissaSize, this.exponentSize); + return new BigFloat(BIM.Abs(Mantissa), Exponent, MantissaSize, ExponentSize); } } @@ -296,7 +320,7 @@ namespace Microsoft.Basetypes public BigFloat Negate { //TODO: Modify for correct fp functionality get { - return new BigFloat(BIM.Negate(this.mantissa), this.exponent, this.mantissaSize, this.exponentSize); + return new BigFloat(BIM.Negate(Mantissa), Exponent, MantissaSize, ExponentSize); } } @@ -308,15 +332,15 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator +(BigFloat x, BigFloat y) { //TODO: Modify for correct fp functionality - BIM m1 = x.mantissa; - int e1 = x.exponent; - BIM m2 = y.mantissa; - int e2 = y.exponent; + BIM m1 = x.Mantissa; + int e1 = x.Exponent; + BIM m2 = y.Mantissa; + int e2 = y.Exponent; if (e2 < e1) { - m1 = y.mantissa; - e1 = y.exponent; - m2 = x.mantissa; - e2 = x.exponent; + m1 = y.Mantissa; + e1 = y.Exponent; + m2 = x.Mantissa; + e2 = x.Exponent; } while (e2 > e1) { @@ -335,7 +359,7 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator *(BigFloat x, BigFloat y) { //TODO: modify for correct fp functionality - return new BigFloat(x.mantissa * y.mantissa, x.exponent + y.exponent, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); + return new BigFloat(x.Mantissa * y.Mantissa, x.Exponent + y.Exponent, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); } @@ -344,19 +368,19 @@ namespace Microsoft.Basetypes public bool IsPositive { get { - return (this.mantissa > BIM.Zero); + return (Mantissa > BIM.Zero); } } public bool IsNegative { get { - return (this.mantissa < BIM.Zero); + return (Mantissa < BIM.Zero); } } public bool IsZero { get { - return this.mantissa.IsZero && this.exponent == 0; + return Mantissa.IsZero && Exponent == 0; } } diff --git a/float_test6.bpl b/float_test6.bpl index 532798d6..12cfbabe 100644 --- a/float_test6.bpl +++ b/float_test6.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; - x := fp (1.5); - assert x == fp (1 0 23 8); + x := fp (3); + assert x == fp (8388608 1 23 8); } \ No newline at end of file diff --git a/float_test7.bpl b/float_test7.bpl new file mode 100644 index 00000000..1638724d --- /dev/null +++ b/float_test7.bpl @@ -0,0 +1,5 @@ + procedure F() returns () { + var x : float; + x := fp (0.5); + assert x == fp (0 -1 23 8); +} \ No newline at end of file -- cgit v1.2.3 From 25fca02e1deb9e60e6e330803731c9b4fcd45d34 Mon Sep 17 00:00:00 2001 From: Dietrich Date: Mon, 18 May 2015 22:08:43 -0600 Subject: added interpretation of floating point constants to the parser --- Source/Basetypes/BigFloat.cs | 155 +++++++++++++++++++++++++++++++---------- Source/Core/Parser.cs | 9 ++- Source/VCExpr/Boogie2VCExpr.cs | 2 +- float_test7.bpl | 4 +- 4 files changed, 128 insertions(+), 42 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 0b35c237..a4cd6574 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -25,21 +25,19 @@ namespace Microsoft.Basetypes // the internal representation [Rep] - internal readonly Boolean[] mantissa; //Note that the first element of the mantissa array is the least significant bit for coding simplicity + internal readonly BIM mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) [Rep] internal readonly Boolean isNegative; //The left-most (sign) bit in the float representation [Rep] - internal readonly int exponent; + internal readonly int mantissaSize; [Rep] - internal readonly int exponentSize; //The maximum bit size of the exponent + internal readonly int exponent; //The value of the exponent is always positive as per fp representation requirements + [Rep] + internal readonly int exponentSize; //The bit size of the exponent public BIM Mantissa { get { - BIM toReturn = 0; - for (int i = 0; i < mantissa.Length; i++) - if (mantissa[i]) - toReturn += (int) Math.Pow(2, i); - return isNegative ? -toReturn : toReturn; + return isNegative ? -mantissa : mantissa; } } @@ -53,7 +51,7 @@ namespace Microsoft.Basetypes { get { - return mantissa.Length; + return mantissaSize; } } @@ -65,8 +63,18 @@ namespace Microsoft.Basetypes } } - public static readonly BigFloat ZERO = FromInt(0); + public static BigFloat ZERO(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Does not include negative zero + public static BigFloat INF(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard + public static BigFloat NEGINF(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard + public static BigFloat NAN(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard + private static readonly BIM two = new BIM(2); + private static BIM two_n(int n) { + BIM toReturn = new BIM(1); + for (int i = 0; i < n; i++) + toReturn = toReturn * two; + return toReturn; + } //////////////////////////////////////////////////////////////////////////// @@ -116,17 +124,39 @@ namespace Microsoft.Basetypes } internal BigFloat(BIM mantissa, int exponent, int mantissaSize, int exponentSize) { - this.mantissa = new Boolean[mantissaSize]; + this.mantissa = mantissa; + this.mantissaSize = mantissaSize; this.exponentSize = exponentSize; - this.exponent = exponent; - //TODO: Add overflow check for exponent vs exponent size + this.exponent = exponent + (int)Math.Pow(2, exponentSize - 1); + if (exponent < 0) { //ZERO case since the exponent is less than the minimum + mantissa = 0; + exponent = 0; + this.isNegative = false; + return; + } + this.isNegative = mantissa < 0; if (this.isNegative) - mantissa = -mantissa; + mantissa = -mantissa; // ==> mantissa > 0 + + BIM max = maxMantissa(); + while (this.mantissa > max) { + this.mantissa = this.mantissa / two; + this.exponent++; + } + + //TODO: Add overflow check for exponent vs exponent size + //this.exponent = this.exponent % this.exponentSize; ?? } - private int maxExponent() { return (int)Math.Pow(2, exponentSize - 1) - 1; } - private int minExponent() { return -(int)Math.Pow(2, exponentSize - 1); } + private BIM maxMantissa() + { + BIM result = new BIM(1); + for (int i = 0; i < mantissaSize; i++) + result = result * two; + return result - 1; + } + private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } @@ -151,25 +181,32 @@ namespace Microsoft.Basetypes [Pure] public override string/*!*/ ToString() { - //TODO: modify to reflect floating points Contract.Ensures(Contract.Result() != null); - return String.Format("{0}e{1}", Mantissa.ToString(), Exponent.ToString()); + return String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); } //////////////////////////////////////////////////////////////////////////// // Conversion operations + /// + /// Converts the given decimal value (provided as a string) to the nearest floating point approximation + /// the returned fp assumes the given mantissa and exponent size + /// + /// + /// + /// + /// public static BigFloat Round(String value, int mantissaSize, int exponentSize) { int i = value.IndexOf('.'); if (i == -1) return Round(BIM.Parse(value), 0, mantissaSize, exponentSize); - return Round(BIM.Parse(value.Substring(0, i - 1)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), mantissaSize, exponentSize); + return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), mantissaSize, exponentSize); } /// - /// Converts value.dec_value to a float with mantissaSize, exponentSize + /// Converts value.dec_value to a the closest float approximation with the given mantissaSize, exponentSize /// Returns the result of this calculation /// /// @@ -178,8 +215,54 @@ namespace Microsoft.Basetypes /// /// public static BigFloat Round(BIM value, BIM dec_value, int mantissaSize, int exponentSize) - { //TODO: round the given decimal to the nearest fp value - return new BigFloat(0, 0, mantissaSize, exponentSize); + { + int exp = 0; + BIM one = new BIM(1); + BIM ten = new BIM(10); + BIM dec_max = new BIM(0); //represents the order of magnitude of dec_value for carrying during calculations + + //First, determine the exponent + while (value > one) { //Divide by two, increment exponent by 1 + if (!(value % two).IsZero) { //Add "1.0" to the decimal + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + dec_value = dec_value + dec_max; + } + value = value / two; + if (!(dec_value % ten).IsZero) + dec_value = dec_value * ten; //Creates excess zeroes to avoid losing data during division + dec_value = dec_value / two; + exp++; + } + if (value.IsZero && !dec_value.IsZero) { + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + while (value.IsZero) {//Multiply by two, decrement exponent by 1 + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + one; + } + exp--; + } + } + + //Second, calculate the mantissa + value = new BIM(0); //remove implicit bit + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + for (int i = mantissaSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the mantissa is fully calculated + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + two_n(i); //Note that i is decrementing so that the most significant bit is left-most in the representation + } + } + + return new BigFloat(value, exp, mantissaSize, exponentSize); } // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). @@ -336,16 +419,18 @@ namespace Microsoft.Basetypes int e1 = x.Exponent; BIM m2 = y.Mantissa; int e2 = y.Exponent; - if (e2 < e1) { + m1 = m1 + two_n(x.mantissaSize + 1); //Add implicit bit + m2 = m2 + two_n(y.mantissaSize + 1); + if (e2 > e1) { m1 = y.Mantissa; e1 = y.Exponent; m2 = x.Mantissa; e2 = x.Exponent; } - while (e2 > e1) { - m2 = m2 * two; - e2 = e2 - 1; + while (e2 < e1) { + m2 = m2 / two; + e2++; } return new BigFloat(m1 + m2, e1, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); @@ -358,7 +443,6 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator *(BigFloat x, BigFloat y) { - //TODO: modify for correct fp functionality return new BigFloat(x.Mantissa * y.Mantissa, x.Exponent + y.Exponent, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); } @@ -368,13 +452,13 @@ namespace Microsoft.Basetypes public bool IsPositive { get { - return (Mantissa > BIM.Zero); + return (!isNegative); } } public bool IsNegative { get { - return (Mantissa < BIM.Zero); + return (isNegative); } } @@ -386,14 +470,13 @@ namespace Microsoft.Basetypes [Pure] public int CompareTo(BigFloat that) { - //TODO: Modify for correct fp functionality - if (this.mantissa == that.mantissa && this.exponent == that.exponent) { + if (this.exponent > that.exponent) + return 1; + if (this.exponent < that.exponent) + return -1; + if (this.Mantissa == that.Mantissa) return 0; - } - else { - BigFloat d = this - that; - return d.IsNegative ? -1 : 1; - } + return this.Mantissa > that.Mantissa ? 1 : -1; } [Pure] diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 7335dd37..6f793503 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -1887,9 +1887,12 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Get(); //Skip the fp token Get(); if (t.val != "(") { throw new FormatException(); } - while (la.kind == 3 || la.kind == 6) { //Get values between the parens + while (la.kind == 1 || la.kind == 3 || la.kind == 6 || la.kind == 75) { //Get values between the parens Get(); - s += t.val + " "; + if (t.val == "-") //special negative case (la.kind == 75) + s += t.val; + else + s += t.val + " "; } Get(); if (t.val != ")") { throw new FormatException(); } @@ -1901,7 +1904,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { catch (FormatException) { this.SemErr("incorrectly formatted floating point"); - n = BigFloat.ZERO; + n = BigFloat.ZERO(8, 23); } } diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs index aa246c37..942116eb 100644 --- a/Source/VCExpr/Boogie2VCExpr.cs +++ b/Source/VCExpr/Boogie2VCExpr.cs @@ -1009,7 +1009,7 @@ namespace Microsoft.Boogie.VCExprAST { return Gen.Function(VCExpressionGenerator.SubROp, Gen.Real(BigDec.ZERO), e); } else {//is float - return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO), e); + return Gen.Function(VCExpressionGenerator.SubFOp, Gen.Float(BigFloat.ZERO(8, 23)), e); } } else { diff --git a/float_test7.bpl b/float_test7.bpl index 1638724d..ca33eb08 100644 --- a/float_test7.bpl +++ b/float_test7.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; - x := fp (0.5); - assert x == fp (0 -1 23 8); + x := fp (.5 23 8); + assert x == fp (0 -1); } \ No newline at end of file -- cgit v1.2.3 From bb5395b35dcea5078c9b38a2f091f26256faac34 Mon Sep 17 00:00:00 2001 From: Dietrich Date: Mon, 20 Jul 2015 22:27:32 -0600 Subject: Float type now works correctly for simple variable declaration and comparison. --- Source/Basetypes/BigFloat.cs | 38 +++++++++++++++++-------------- Source/Core/AbsyType.cs | 22 ++++++++++-------- Source/Core/Parser.cs | 4 ++-- Source/Provers/SMTLib/SMTLibLineariser.cs | 2 +- Source/Provers/SMTLib/SMTLibProcess.cs | 1 - float_test2.bpl | 4 ++-- float_test3.bpl | 5 +--- float_test4.bpl | 4 ++-- float_test5.bpl | 2 +- float_test6.bpl | 6 ++--- float_test7.bpl | 6 ++--- float_test8.bpl | 1 + 12 files changed, 49 insertions(+), 46 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index a4cd6574..1fb05005 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -90,12 +90,12 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat FromBigInt(BIM v) { - return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation + return new BigFloat(0, v, 8, 23); //TODO: modify for correct fp representation } public static BigFloat FromBigDec(BIM v) { - return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation + return new BigFloat(0, v, 8, 23); //TODO: modify for correct fp representation } [Pure] @@ -107,13 +107,13 @@ namespace Microsoft.Basetypes { switch (vals.Length) { case 1: - return Round(vals[0], 23, 8); + return Round(vals[0], 8, 23); case 2: - return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), 23, 8); + return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 23); case 3: return Round(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); case 4: - return new BigFloat(BIM.Parse(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); + return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); default: throw new FormatException(); //Unreachable } @@ -123,11 +123,11 @@ namespace Microsoft.Basetypes } } - internal BigFloat(BIM mantissa, int exponent, int mantissaSize, int exponentSize) { - this.mantissa = mantissa; - this.mantissaSize = mantissaSize; + internal BigFloat(int exponent, BIM mantissa, int exponentSize, int mantissaSize) { this.exponentSize = exponentSize; this.exponent = exponent + (int)Math.Pow(2, exponentSize - 1); + this.mantissa = mantissa; + this.mantissaSize = mantissaSize; if (exponent < 0) { //ZERO case since the exponent is less than the minimum mantissa = 0; exponent = 0; @@ -197,12 +197,12 @@ namespace Microsoft.Basetypes /// /// /// - public static BigFloat Round(String value, int mantissaSize, int exponentSize) + public static BigFloat Round(String value, int exponentSize, int mantissaSize) { int i = value.IndexOf('.'); if (i == -1) - return Round(BIM.Parse(value), 0, mantissaSize, exponentSize); - return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), mantissaSize, exponentSize); + return Round(BIM.Parse(value), 0, exponentSize, mantissaSize); + return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), exponentSize, mantissaSize); } /// @@ -214,7 +214,7 @@ namespace Microsoft.Basetypes /// /// /// - public static BigFloat Round(BIM value, BIM dec_value, int mantissaSize, int exponentSize) + public static BigFloat Round(BIM value, BIM dec_value, int exponentSize, int mantissaSize) { int exp = 0; BIM one = new BIM(1); @@ -262,7 +262,7 @@ namespace Microsoft.Basetypes } } - return new BigFloat(value, exp, mantissaSize, exponentSize); + return new BigFloat(exp, value, exponentSize, mantissaSize); } // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). @@ -395,7 +395,7 @@ namespace Microsoft.Basetypes public BigFloat Abs { //TODO: fix for fp functionality get { - return new BigFloat(BIM.Abs(Mantissa), Exponent, MantissaSize, ExponentSize); + return new BigFloat(Exponent, BIM.Abs(Mantissa), ExponentSize, MantissaSize); } } @@ -403,7 +403,7 @@ namespace Microsoft.Basetypes public BigFloat Negate { //TODO: Modify for correct fp functionality get { - return new BigFloat(BIM.Negate(Mantissa), Exponent, MantissaSize, ExponentSize); + return new BigFloat(Exponent, BIM.Negate(Mantissa), ExponentSize, MantissaSize); } } @@ -415,6 +415,8 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator +(BigFloat x, BigFloat y) { //TODO: Modify for correct fp functionality + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.MantissaSize == y.MantissaSize); BIM m1 = x.Mantissa; int e1 = x.Exponent; BIM m2 = y.Mantissa; @@ -433,7 +435,7 @@ namespace Microsoft.Basetypes e2++; } - return new BigFloat(m1 + m2, e1, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); + return new BigFloat(e1, m1 + m2, x.MantissaSize, x.ExponentSize); } [Pure] @@ -443,7 +445,9 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator *(BigFloat x, BigFloat y) { - return new BigFloat(x.Mantissa * y.Mantissa, x.Exponent + y.Exponent, Math.Max(x.MantissaSize, y.MantissaSize), Math.Max(x.ExponentSize, y.ExponentSize)); + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.MantissaSize == y.MantissaSize); + return new BigFloat(x.Exponent + y.Exponent, x.Mantissa * y.Mantissa, x.MantissaSize, x.ExponentSize); } diff --git a/Source/Core/AbsyType.cs b/Source/Core/AbsyType.cs index 50fde975..5d41a8dd 100644 --- a/Source/Core/AbsyType.cs +++ b/Source/Core/AbsyType.cs @@ -330,20 +330,22 @@ namespace Microsoft.Boogie { return false; } } - public virtual int FloatMantissa { - get { + public virtual int FloatExponent + { + get + { { Contract.Assert(false); throw new cce.UnreachableException(); - } // Type.FloatMantissa should never be called + } // Type.FloatExponent should never be called } } - public virtual int FloatExponent { + public virtual int FloatMantissa { get { { Contract.Assert(false); throw new cce.UnreachableException(); - } // Type.FloatExponent should never be called + } // Type.FloatMantissa should never be called } } public virtual bool IsBv { @@ -1050,14 +1052,14 @@ namespace Microsoft.Boogie { public FloatType(IToken token, int exponent, int mantissa) : base(token) { Contract.Requires(token != null); - Mantissa = mantissa; Exponent = exponent; + Mantissa = mantissa; } public FloatType(int exponent, int mantissa) : base(Token.NoToken) { - Mantissa = mantissa; Exponent = exponent; + Mantissa = mantissa; } //----------- Cloning ---------------------------------- @@ -1092,7 +1094,7 @@ namespace Microsoft.Boogie { public override string ToString() { Contract.Ensures(Contract.Result() != null); - return "(_ FP " + Exponent + " " + Mantissa + ")"; + return "float (" + Exponent + " " + Mantissa + ")"; } //----------- Equality ---------------------------------- @@ -1119,10 +1121,10 @@ namespace Microsoft.Boogie { //Contract.Requires(cce.NonNullElements(unifier)); that = that.Expanded; if (that is TypeProxy || that is TypeVariable) { - return that.Unify(this, unifiableVariables, unifier); + return that.Unify(this, unifiableVariables, unifier); } else { - return this.Equals(that); + return this.Equals(that); } } diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index bb372cfb..2550c334 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -366,7 +366,7 @@ private class BvBounds : Expr { Get(); Type(out retTy); retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy); - } else SynErr(97); + } else SynErr(99); if (la.kind == 27) { Get(); Expression(out tmp); @@ -374,7 +374,7 @@ private class BvBounds : Expr { Expect(28); } else if (la.kind == 8) { Get(); - } else SynErr(98); + } else SynErr(100); if (retTyd == null) { // construct a dummy type for the case of syntax error retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int)); diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index c7ae9d57..3633a9c0 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -141,7 +141,7 @@ namespace Microsoft.Boogie.SMTLib else if (t.IsReal) return "Real"; else if (t.IsFloat) - return t.ToString(); //TODO: Match z3 syntax + return "(_ FloatingPoint " + t.FloatExponent + " " + t.FloatMantissa + ")"; //TODO: Match z3 syntax else if (t.IsBv) { return "(_ BitVec " + t.BvBits + ")"; } else { diff --git a/Source/Provers/SMTLib/SMTLibProcess.cs b/Source/Provers/SMTLib/SMTLibProcess.cs index 2b09362b..4a1331c5 100644 --- a/Source/Provers/SMTLib/SMTLibProcess.cs +++ b/Source/Provers/SMTLib/SMTLibProcess.cs @@ -93,7 +93,6 @@ namespace Microsoft.Boogie.SMTLib log = log.Replace("\r", "").Replace("\n", " "); Console.WriteLine("[SMT-INP-{0}] {1}", smtProcessId, log); } - Console.WriteLine(cmd); //TODO: Remove This Line toProver.WriteLine(cmd); } diff --git a/float_test2.bpl b/float_test2.bpl index fa34d8cf..956ac757 100644 --- a/float_test2.bpl +++ b/float_test2.bpl @@ -1,5 +1,5 @@ procedure F() returns () { - var x : float; - var y : float; + var x : float(11 53); + var y : float(11 53); assert x == y; } \ No newline at end of file diff --git a/float_test3.bpl b/float_test3.bpl index 1b70ebf4..e93e7df7 100644 --- a/float_test3.bpl +++ b/float_test3.bpl @@ -1,6 +1,3 @@ procedure F() returns () { - var x : float; - var y : float; - y := x - x; - assert y == x; + assert fp(5) == fp(5 8 23); } \ No newline at end of file diff --git a/float_test4.bpl b/float_test4.bpl index 2388a281..1252dc71 100644 --- a/float_test4.bpl +++ b/float_test4.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; - x := fp (0 0); - assert x == fp (0 0 23 8); + x := fp (.5 8 23); + assert x == fp (-1 0); } \ No newline at end of file diff --git a/float_test5.bpl b/float_test5.bpl index b91e53e9..2f565b27 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; x := fp (0 0); - assert x == fp (1 0 23 8); + assert x == fp (0 0 8 30); } \ No newline at end of file diff --git a/float_test6.bpl b/float_test6.bpl index 12cfbabe..307da9f7 100644 --- a/float_test6.bpl +++ b/float_test6.bpl @@ -1,5 +1,5 @@ - procedure F() returns () { +procedure F() returns () { var x : float; - x := fp (3); - assert x == fp (8388608 1 23 8); + x := fp(1) + fp(1); + assert x == fp(2); } \ No newline at end of file diff --git a/float_test7.bpl b/float_test7.bpl index ca33eb08..cc7a040b 100644 --- a/float_test7.bpl +++ b/float_test7.bpl @@ -1,5 +1,5 @@ - procedure F() returns () { +procedure F() returns () { var x : float; - x := fp (.5 23 8); - assert x == fp (0 -1); + x := fp(.1) + fp(.1) + fp(.1); + assert x == fp(.3); } \ No newline at end of file diff --git a/float_test8.bpl b/float_test8.bpl index 8d881126..7c23c74f 100644 --- a/float_test8.bpl +++ b/float_test8.bpl @@ -1,4 +1,5 @@ procedure F() returns () { + Logic=QF_FP; var x : float; x := fp(.1) + fp(.1); assert x == fp(.2); -- cgit v1.2.3 From 28a20e6eba2919e008f70874b4c12a3ce7ad049c Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Thu, 17 Sep 2015 03:14:27 -0600 Subject: Added initial support for float addition --- Binaries/Boogie.vshost.exe.manifest | 22 ++++++------ Source/Basetypes/BigFloat.cs | 12 +++---- Source/Core/AbsyExpr.cs | 16 ++++----- Source/Core/Parser.cs | 4 +-- Source/Provers/SMTLib/SMTLibProcess.cs | 1 + Source/Provers/SMTLib/Z3.cs | 4 +-- Source/VCExpr/VCExprAST.cs | 62 ++++++++++++++++++++++++++++++++-- Source/VCExpr/VCExprASTVisitors.cs | 1 - float_test5.bpl | 4 +-- 9 files changed, 89 insertions(+), 37 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Binaries/Boogie.vshost.exe.manifest b/Binaries/Boogie.vshost.exe.manifest index 061c9ca9..f96b1d6b 100644 --- a/Binaries/Boogie.vshost.exe.manifest +++ b/Binaries/Boogie.vshost.exe.manifest @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 1fb05005..33860a4f 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -17,7 +17,7 @@ namespace Microsoft.Basetypes /// /// A representation of a 32-bit floating point value - /// Note that this value has a 1-bit sign, 8-bit exponent, and 23-bit mantissa + /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit mantissa /// public struct BigFloat { @@ -85,17 +85,17 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat FromInt(int v) { - return new BigFloat(v, 0, 23, 8); //TODO: modify for correct fp representation + return new BigFloat(v, 0, 24, 8); //TODO: modify for correct fp representation } [Pure] public static BigFloat FromBigInt(BIM v) { - return new BigFloat(0, v, 8, 23); //TODO: modify for correct fp representation + return new BigFloat(0, v, 8, 24); //TODO: modify for correct fp representation } public static BigFloat FromBigDec(BIM v) { - return new BigFloat(0, v, 8, 23); //TODO: modify for correct fp representation + return new BigFloat(0, v, 8, 24); //TODO: modify for correct fp representation } [Pure] @@ -107,9 +107,9 @@ namespace Microsoft.Basetypes { switch (vals.Length) { case 1: - return Round(vals[0], 8, 23); + return Round(vals[0], 8, 24); case 2: - return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 23); + return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 24); case 3: return Round(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); case 4: diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs index 7e7ed10a..181076a7 100644 --- a/Source/Core/AbsyExpr.cs +++ b/Source/Core/AbsyExpr.cs @@ -1519,8 +1519,6 @@ namespace Microsoft.Boogie { return "mod"; case Opcode.RealDiv: return "/"; - case Opcode.FloatDiv: - return "/"; case Opcode.Pow: return "**"; case Opcode.Eq: @@ -1583,10 +1581,6 @@ namespace Microsoft.Boogie { opBindingStrength = 0x50; fragileRightContext = true; break; - case Opcode.FloatDiv: //TODO: Modify (potentially) - opBindingStrength = 0x50; - fragileRightContext = true; - break; case Opcode.Pow: opBindingStrength = 0x60; fragileRightContext = true; @@ -1707,10 +1701,12 @@ namespace Microsoft.Boogie { if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) { return Type.Real; } - //if (arg0type.Unify(Type.Float) && arg1type.Unify(Type.Float)) - //{ - //return Type.Float; - //} + if (arg0type.IsFloat && arg0type.Unify(arg1type)) { + return new FloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa); + } + if (arg1type.IsFloat && arg1type.Unify(arg0type)) { + return new FloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa); + } goto BAD_TYPE; case Opcode.Div: case Opcode.Mod: diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 2550c334..889d7be8 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -678,7 +678,7 @@ private class BvBounds : Expr { Expect(10); } else - ty = new FloatType(t, 8, 23); + ty = new FloatType(t, 8, 24); } else if (la.kind == 16) { Get(); ty = new BasicType(t, SimpleType.Bool); @@ -1914,7 +1914,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { catch (FormatException) { this.SemErr("incorrectly formatted floating point"); - n = BigFloat.ZERO(8, 23); + n = BigFloat.ZERO(8, 24); } } diff --git a/Source/Provers/SMTLib/SMTLibProcess.cs b/Source/Provers/SMTLib/SMTLibProcess.cs index 4a1331c5..4982d81e 100644 --- a/Source/Provers/SMTLib/SMTLibProcess.cs +++ b/Source/Provers/SMTLib/SMTLibProcess.cs @@ -93,6 +93,7 @@ namespace Microsoft.Boogie.SMTLib log = log.Replace("\r", "").Replace("\n", " "); Console.WriteLine("[SMT-INP-{0}] {1}", smtProcessId, log); } + Console.WriteLine(cmd); toProver.WriteLine(cmd); } diff --git a/Source/Provers/SMTLib/Z3.cs b/Source/Provers/SMTLib/Z3.cs index 250e04c9..8e8b2d55 100644 --- a/Source/Provers/SMTLib/Z3.cs +++ b/Source/Provers/SMTLib/Z3.cs @@ -253,7 +253,7 @@ namespace Microsoft.Boogie.SMTLib //if (options.Inspector != null) // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); - options.AddWeakSmtOption("TYPE_CHECK", "true"); + options.AddWeakSmtOption("TYPE_CHECK", "false"); options.AddWeakSmtOption("smt.BV.REFLECT", "true"); if (options.TimeLimit > 0) @@ -334,7 +334,7 @@ namespace Microsoft.Boogie.SMTLib //if (options.Inspector != null) // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); - options.AddWeakSmtOption("TYPE_CHECK", "true"); + options.AddWeakSmtOption("TYPE_CHECK", "false"); options.AddWeakSmtOption("BV_REFLECT", "true"); if (options.TimeLimit > 0) diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs index 36692f30..c44800fc 100644 --- a/Source/VCExpr/VCExprAST.cs +++ b/Source/VCExpr/VCExprAST.cs @@ -357,6 +357,15 @@ namespace Microsoft.Boogie { return new VCExprBoogieFunctionOp(func); } + // Float nodes + + public VCExpr AddFOp(VCExpr f1, VCExpr f2) + { + Contract.Requires(f1 != null); + Contract.Requires(f2 != null); + return Function(new VCExprFloatOp(f1.Type.FloatExponent, f1.Type.FloatMantissa)); + } + // Bitvector nodes public VCExpr Bitvector(BvConst bv) { @@ -403,7 +412,6 @@ namespace Microsoft.Boogie { DivOp, ModOp, RealDivOp, - FloatDivOp, PowOp, LtOp, LeOp, @@ -1309,8 +1317,6 @@ namespace Microsoft.Boogie.VCExprAST { return visitor.VisitModOp(expr, arg); case VCExpressionGenerator.SingletonOp.RealDivOp: return visitor.VisitRealDivOp(expr, arg); - case VCExpressionGenerator.SingletonOp.FloatDivOp: - return visitor.VisitFloatDivOp(expr, arg); case VCExpressionGenerator.SingletonOp.PowOp: return visitor.VisitPowOp(expr, arg); case VCExpressionGenerator.SingletonOp.LtOp: @@ -1668,6 +1674,56 @@ namespace Microsoft.Boogie.VCExprAST { } } + ///////////////////////////////////////////////////////////////////////////////// + // Float operators + + public class VCExprFloatOp : VCExprOp { + public readonly int Mantissa; + public readonly int Exponent; + + public override int Arity { + get { + return 1; + } + } + public override int TypeParamArity { + get { + return 0; + } + } + public override Type InferType(List args, List/*!*/ typeArgs) { + //Contract.Requires(cce.NonNullElements(typeArgs)); + //Contract.Requires(cce.NonNullElements(args)); + Contract.Ensures(Contract.Result() != null); + return Type.GetFloatType(Exponent, Mantissa); + } + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object that) { + if (Object.ReferenceEquals(this, that)) + return true; + if (that is VCExprFloatOp) + return this.Exponent == ((VCExprFloatOp)that).Exponent && this.Mantissa == ((VCExprFloatOp)that).Mantissa; + return false; + } + [Pure] + public override int GetHashCode() { + return Exponent * 81748912 + Mantissa * 67867979; + } + + internal VCExprFloatOp(int exp, int man) { + this.Exponent = exp; + this.Mantissa = man; + } + public override Result Accept + (VCExprNAry expr, IVCExprOpVisitor visitor, Arg arg) { + //Contract.Requires(visitor != null); + //Contract.Requires(expr != null); + return visitor.VisitBvOp(expr, arg); + } + } + ///////////////////////////////////////////////////////////////////////////////// // Bitvector operators diff --git a/Source/VCExpr/VCExprASTVisitors.cs b/Source/VCExpr/VCExprASTVisitors.cs index 1bcce113..a1fb2ff4 100644 --- a/Source/VCExpr/VCExprASTVisitors.cs +++ b/Source/VCExpr/VCExprASTVisitors.cs @@ -77,7 +77,6 @@ namespace Microsoft.Boogie.VCExprAST { Result VisitDivOp(VCExprNAry node, Arg arg); Result VisitModOp(VCExprNAry node, Arg arg); Result VisitRealDivOp(VCExprNAry node, Arg arg); - Result VisitFloatDivOp(VCExprNAry node, Arg arg); //TODO: Add this to references from above and below Result VisitPowOp(VCExprNAry node, Arg arg); Result VisitLtOp(VCExprNAry node, Arg arg); Result VisitLeOp(VCExprNAry node, Arg arg); diff --git a/float_test5.bpl b/float_test5.bpl index 2f565b27..c3d279f2 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; - x := fp (0 0); - assert x == fp (0 0 8 30); + var y : float; + assert x + y == fp(0); } \ No newline at end of file -- cgit v1.2.3 From 80f3d4ed1bb221adbd3c7162acea10920b9fab73 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Wed, 23 Sep 2015 04:08:00 -0600 Subject: Modified BigFloat to avoid evaluating the floating point value before sending it to z3 --- Source/Basetypes/BigFloat.cs | 1006 ++++++++++++++--------------- Source/Core/AbsyExpr.cs | 20 +- Source/Provers/SMTLib/SMTLibLineariser.cs | 12 - Source/VCExpr/VCExprASTPrinter.cs | 12 - float_test5.bpl | 5 +- float_test6.bpl | 4 +- 6 files changed, 505 insertions(+), 554 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 33860a4f..e9d5e670 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -1,516 +1,490 @@ -//----------------------------------------------------------------------------- -// -// Copyright (C) Microsoft Corporation. All Rights Reserved. -// -//----------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Diagnostics.Contracts; -using System.Diagnostics; - -namespace Microsoft.Basetypes -{ - using BIM = System.Numerics.BigInteger; - - /// - /// A representation of a 32-bit floating point value - /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit mantissa - /// - public struct BigFloat - { - //Please note that this code outline is copy-pasted from BigDec.cs - - // the internal representation - [Rep] - internal readonly BIM mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) - [Rep] - internal readonly Boolean isNegative; //The left-most (sign) bit in the float representation - [Rep] - internal readonly int mantissaSize; - [Rep] - internal readonly int exponent; //The value of the exponent is always positive as per fp representation requirements - [Rep] - internal readonly int exponentSize; //The bit size of the exponent - - public BIM Mantissa { - get { - return isNegative ? -mantissa : mantissa; - } - } - - public int Exponent { - get { - return exponent - (int)Math.Pow(2, exponentSize - 1); //account for shift - } - } - - public int MantissaSize - { - get - { - return mantissaSize; - } - } - - public int ExponentSize - { - get - { - return exponentSize; - } - } - - public static BigFloat ZERO(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Does not include negative zero - public static BigFloat INF(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard - public static BigFloat NEGINF(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard - public static BigFloat NAN(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Modify for IEEE standard - - private static readonly BIM two = new BIM(2); - private static BIM two_n(int n) { - BIM toReturn = new BIM(1); - for (int i = 0; i < n; i++) - toReturn = toReturn * two; - return toReturn; - } - - - //////////////////////////////////////////////////////////////////////////// - // Constructors - - //Please note that these constructors will be called throughout boogie - //For a complete summary of where this class has been added, simply view constructor references - - [Pure] - public static BigFloat FromInt(int v) { - return new BigFloat(v, 0, 24, 8); //TODO: modify for correct fp representation - } - - [Pure] - public static BigFloat FromBigInt(BIM v) { - return new BigFloat(0, v, 8, 24); //TODO: modify for correct fp representation - } - - public static BigFloat FromBigDec(BIM v) - { - return new BigFloat(0, v, 8, 24); //TODO: modify for correct fp representation - } - - [Pure] - public static BigFloat FromString(string v) { - String[] vals = v.Split(' '); - if (vals.Length == 0 || vals.Length > 4) - throw new FormatException(); - try - { - switch (vals.Length) { - case 1: - return Round(vals[0], 8, 24); - case 2: - return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 24); - case 3: - return Round(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); - case 4: - return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); - default: - throw new FormatException(); //Unreachable - } - } - catch (Exception) { //Catch parsing errors - throw new FormatException(); - } - } - - internal BigFloat(int exponent, BIM mantissa, int exponentSize, int mantissaSize) { - this.exponentSize = exponentSize; - this.exponent = exponent + (int)Math.Pow(2, exponentSize - 1); - this.mantissa = mantissa; - this.mantissaSize = mantissaSize; - if (exponent < 0) { //ZERO case since the exponent is less than the minimum - mantissa = 0; - exponent = 0; - this.isNegative = false; - return; - } - - this.isNegative = mantissa < 0; - if (this.isNegative) - mantissa = -mantissa; // ==> mantissa > 0 - - BIM max = maxMantissa(); - while (this.mantissa > max) { - this.mantissa = this.mantissa / two; - this.exponent++; - } - - //TODO: Add overflow check for exponent vs exponent size - //this.exponent = this.exponent % this.exponentSize; ?? - } - - private BIM maxMantissa() - { - BIM result = new BIM(1); - for (int i = 0; i < mantissaSize; i++) - result = result * two; - return result - 1; - } - private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } - - - - //////////////////////////////////////////////////////////////////////////// - // Basic object operations - - [Pure] - [Reads(ReadsAttribute.Reads.Nothing)] - public override bool Equals(object obj) { - if (obj == null) - return false; - if (!(obj is BigFloat)) - return false; - - return (this == (BigFloat)obj); - } - - [Pure] - public override int GetHashCode() { - return Mantissa.GetHashCode() * 13 + Exponent.GetHashCode(); - } - - [Pure] - public override string/*!*/ ToString() { - Contract.Ensures(Contract.Result() != null); - return String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); - } - - - //////////////////////////////////////////////////////////////////////////// - // Conversion operations - - /// - /// Converts the given decimal value (provided as a string) to the nearest floating point approximation - /// the returned fp assumes the given mantissa and exponent size - /// - /// - /// - /// - /// - public static BigFloat Round(String value, int exponentSize, int mantissaSize) - { - int i = value.IndexOf('.'); - if (i == -1) - return Round(BIM.Parse(value), 0, exponentSize, mantissaSize); - return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), exponentSize, mantissaSize); - } - - /// - /// Converts value.dec_value to a the closest float approximation with the given mantissaSize, exponentSize - /// Returns the result of this calculation - /// - /// - /// - /// - /// - /// - public static BigFloat Round(BIM value, BIM dec_value, int exponentSize, int mantissaSize) - { - int exp = 0; - BIM one = new BIM(1); - BIM ten = new BIM(10); - BIM dec_max = new BIM(0); //represents the order of magnitude of dec_value for carrying during calculations - - //First, determine the exponent - while (value > one) { //Divide by two, increment exponent by 1 - if (!(value % two).IsZero) { //Add "1.0" to the decimal - dec_max = new BIM(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - dec_value = dec_value + dec_max; - } - value = value / two; - if (!(dec_value % ten).IsZero) - dec_value = dec_value * ten; //Creates excess zeroes to avoid losing data during division - dec_value = dec_value / two; - exp++; - } - if (value.IsZero && !dec_value.IsZero) { - dec_max = new BIM(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - while (value.IsZero) {//Multiply by two, decrement exponent by 1 - dec_value = dec_value * two; - if (dec_value >= dec_max) { - dec_value = dec_value - dec_max; - value = value + one; - } - exp--; - } - } - - //Second, calculate the mantissa - value = new BIM(0); //remove implicit bit - dec_max = new BIM(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - for (int i = mantissaSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the mantissa is fully calculated - dec_value = dec_value * two; - if (dec_value >= dec_max) { - dec_value = dec_value - dec_max; - value = value + two_n(i); //Note that i is decrementing so that the most significant bit is left-most in the representation - } - } - - return new BigFloat(exp, value, exponentSize, mantissaSize); - } - - // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). - /// - /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative - /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way. - /// - /// The Floor (rounded towards negative infinity) - /// Ceiling (rounded towards positive infinity) - public void FloorCeiling(out BIM floor, out BIM ceiling) { - //TODO: fix for fp functionality - BIM n = Mantissa; - int e = Exponent; - if (n.IsZero) { - floor = ceiling = n; - } else if (0 <= e) { - // it's an integer - for (; 0 < e; e--) { - n = n * two; - } - floor = ceiling = n; - } else { - // it's a non-zero integer, so the ceiling is one more than the floor - for (; e < 0 && !n.IsZero; e++) { - n = n / two; // Division rounds towards negative infinity - } - - if (!isNegative) { - floor = n; - ceiling = n + 1; - } else { - ceiling = n; - floor = n - 1; - } - } - Debug.Assert(floor <= ceiling, "Invariant was not maintained"); - } - - [Pure] - public String ToDecimalString(int maxDigits) { - //TODO: fix for fp functionality - string s = Mantissa.ToString(); - int digits = (isNegative) ? s.Length - 1 : s.Length; - BIM max = BIM.Pow(10, maxDigits); - BIM min = -max; - - if (Exponent >= 0) { - if (maxDigits < digits || maxDigits - digits < Exponent) { - return String.Format("{0}.0", (!isNegative) ? max.ToString() : min.ToString()); - } - else { - return String.Format("{0}{1}.0", s, new string('0', Exponent)); - } - } - else { - int exp = -Exponent; - - if (exp < digits) { - int intDigits = digits - exp; - if (maxDigits < intDigits) { - return String.Format("{0}.0", (!isNegative) ? max.ToString() : min.ToString()); - } - else { - int fracDigits = Math.Min(maxDigits, digits - intDigits); - return String.Format("{0}.{1}", s.Substring(0, intDigits), s.Substring(intDigits, fracDigits)); - } - } - else { - int fracDigits = Math.Min(maxDigits, digits); - return String.Format("0.{0}{1}", new string('0', exp - fracDigits), s.Substring(0, fracDigits)); - } - } - } - - [Pure] - public string ToDecimalString() { - //TODO: fix for fp functionality - string m = Mantissa.ToString(); - var e = Exponent; - if (0 <= Exponent) { - return m + Zeros(e) + ".0"; - } else { - e = -e; - // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string) - var maxK = e < m.Length ? e : m.Length - 1; - var last = m.Length - 1; - var k = 0; - while (k < maxK && m[last - k] == '0') { - k++; - } - if (0 < k) { - // chop off the suffix of k zeros from m and adjust e accordingly - m = m.Substring(0, m.Length - k); - e -= k; - } - if (e == 0) { - return m; - } else if (e < m.Length) { - var n = m.Length - e; - return m.Substring(0, n) + "." + m.Substring(n); - } else { - return "0." + Zeros(e - m.Length) + m; - } - } - } - - [Pure] - public static string Zeros(int n) { - //TODO: fix for fp functionality - Contract.Requires(0 <= n); - if (n <= 10) { - var tenZeros = "0000000000"; - return tenZeros.Substring(0, n); - } else { - var d = n / 2; - var s = Zeros(d); - if (n % 2 == 0) { - return s + s; - } else { - return s + s + "0"; - } - } - } - - - //////////////////////////////////////////////////////////////////////////// - // Basic arithmetic operations - - [Pure] - public BigFloat Abs { - //TODO: fix for fp functionality - get { - return new BigFloat(Exponent, BIM.Abs(Mantissa), ExponentSize, MantissaSize); - } - } - - [Pure] - public BigFloat Negate { - //TODO: Modify for correct fp functionality - get { - return new BigFloat(Exponent, BIM.Negate(Mantissa), ExponentSize, MantissaSize); - } - } - - [Pure] - public static BigFloat operator -(BigFloat x) { - return x.Negate; - } - - [Pure] - public static BigFloat operator +(BigFloat x, BigFloat y) { - //TODO: Modify for correct fp functionality - Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.MantissaSize == y.MantissaSize); - BIM m1 = x.Mantissa; - int e1 = x.Exponent; - BIM m2 = y.Mantissa; - int e2 = y.Exponent; - m1 = m1 + two_n(x.mantissaSize + 1); //Add implicit bit - m2 = m2 + two_n(y.mantissaSize + 1); - if (e2 > e1) { - m1 = y.Mantissa; - e1 = y.Exponent; - m2 = x.Mantissa; - e2 = x.Exponent; - } - - while (e2 < e1) { - m2 = m2 / two; - e2++; - } - - return new BigFloat(e1, m1 + m2, x.MantissaSize, x.ExponentSize); - } - - [Pure] - public static BigFloat operator -(BigFloat x, BigFloat y) { - return x + y.Negate; - } - - [Pure] - public static BigFloat operator *(BigFloat x, BigFloat y) { - Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.MantissaSize == y.MantissaSize); - return new BigFloat(x.Exponent + y.Exponent, x.Mantissa * y.Mantissa, x.MantissaSize, x.ExponentSize); - } - - - //////////////////////////////////////////////////////////////////////////// - // Some basic comparison operations - - public bool IsPositive { - get { - return (!isNegative); - } - } - - public bool IsNegative { - get { - return (isNegative); - } - } - - public bool IsZero { - get { - return Mantissa.IsZero && Exponent == 0; - } - } - - [Pure] - public int CompareTo(BigFloat that) { - if (this.exponent > that.exponent) - return 1; - if (this.exponent < that.exponent) - return -1; - if (this.Mantissa == that.Mantissa) - return 0; - return this.Mantissa > that.Mantissa ? 1 : -1; - } - - [Pure] - public static bool operator ==(BigFloat x, BigFloat y) { - return x.CompareTo(y) == 0; - } - - [Pure] - public static bool operator !=(BigFloat x, BigFloat y) { - return x.CompareTo(y) != 0; - } - - [Pure] - public static bool operator <(BigFloat x, BigFloat y) { - return x.CompareTo(y) < 0; - } - - [Pure] - public static bool operator >(BigFloat x, BigFloat y) { - return x.CompareTo(y) > 0; - } - - [Pure] - public static bool operator <=(BigFloat x, BigFloat y) { - return x.CompareTo(y) <= 0; - } - - [Pure] - public static bool operator >=(BigFloat x, BigFloat y) { - return x.CompareTo(y) >= 0; - } - } -} +//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.Diagnostics; + +namespace Microsoft.Basetypes +{ + using BIM = System.Numerics.BigInteger; + + /// + /// A representation of a 32-bit floating point value + /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit mantissa + /// + public struct BigFloat + { + //Please note that this code outline is copy-pasted from BigDec.cs + + // the internal representation + [Rep] + internal readonly BIM mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) + [Rep] + internal readonly int mantissaSize; + [Rep] + internal readonly int exponent; //The value of the exponent is always positive as per fp representation requirements + [Rep] + internal readonly int exponentSize; //The bit size of the exponent + [Rep] + internal readonly BigDec dec_value; + [Rep] + internal readonly bool isDec; + + public BIM Mantissa { + get { + return mantissa; + } + } + + public int Exponent { + get { + return exponent; + } + } + + public int MantissaSize { + get { + return mantissaSize; + } + } + + public int ExponentSize { + get { + return exponentSize; + } + } + + public BigDec Decimal { + get { + return dec_value; + } + } + + public bool IsDec { + get { + return IsDec; + } + } + + public static BigFloat ZERO(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Does not include negative zero + + private static readonly BIM two = new BIM(2); + private static BIM two_n(int n) { + BIM toReturn = new BIM(1); + for (int i = 0; i < n; i++) + toReturn = toReturn * two; + return toReturn; + } + + + //////////////////////////////////////////////////////////////////////////// + // Constructors + + //Please note that these constructors will be called throughout boogie + //For a complete summary of where this class has been added, simply view constructor references + + [Pure] + public static BigFloat FromInt(int v) { + return new BigFloat(v, 0, 24, 8); + } + + [Pure] + public static BigFloat FromBigInt(BIM v) { + return new BigFloat(0, v, 8, 24); + } + + public static BigFloat FromBigDec(BigDec v) + { + return new BigFloat(v, 8, 24); + } + + [Pure] + public static BigFloat FromString(string v) { + String[] vals = v.Split(' '); + if (vals.Length == 0 || vals.Length > 4) + throw new FormatException(); + try + { + switch (vals.Length) { + case 1: + return new BigFloat(BigDec.FromString(vals[0]), 8, 24); + case 2: + return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 24); + case 3: + return new BigFloat(BigDec.FromString(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2])); + case 4: + return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); + default: + throw new FormatException(); //Unreachable + } + } + catch (Exception) { //Catch parsing errors + throw new FormatException(); + } + } + + internal BigFloat(int exponent, BIM mantissa, int exponentSize, int mantissaSize) { + this.exponentSize = exponentSize; + this.exponent = exponent; + this.mantissa = mantissa; + this.mantissaSize = mantissaSize; + this.isDec = false; + this.dec_value = BigDec.ZERO; + } + + internal BigFloat(BigDec dec_value, int exponentSize, int mantissaSize) { + this.exponentSize = exponentSize; + this.mantissaSize = mantissaSize; + this.exponent = 0; + this.mantissa = 0; + this.isDec = true; + this.dec_value = dec_value; + } + + private BIM maxMantissa() + { + BIM result = new BIM(1); + for (int i = 0; i < mantissaSize; i++) + result = result * two; + return result - 1; + } + private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } + + + + //////////////////////////////////////////////////////////////////////////// + // Basic object operations + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object obj) { + if (obj == null) + return false; + if (!(obj is BigFloat)) + return false; + + return (this == (BigFloat)obj); + } + + [Pure] + public override int GetHashCode() { + return Mantissa.GetHashCode() * 13 + Exponent.GetHashCode(); + } + + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + return String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); + } + + + //////////////////////////////////////////////////////////////////////////// + // Conversion operations + + /// + /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!! + /// Converts the given decimal value (provided as a string) to the nearest floating point approximation + /// the returned fp assumes the given mantissa and exponent size + /// + /// + /// + /// + /// + public static BigFloat Round(String value, int exponentSize, int mantissaSize) + { + int i = value.IndexOf('.'); + if (i == -1) + return Round(BIM.Parse(value), 0, exponentSize, mantissaSize); + return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), exponentSize, mantissaSize); + } + + /// + /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!!! + /// Converts value.dec_value to a the closest float approximation with the given mantissaSize, exponentSize + /// Returns the result of this calculation + /// + /// + /// + /// + /// + /// + public static BigFloat Round(BIM value, BIM dec_value, int exponentSize, int mantissaSize) + { + int exp = 0; + BIM one = new BIM(1); + BIM ten = new BIM(10); + BIM dec_max = new BIM(0); //represents the order of magnitude of dec_value for carrying during calculations + + //First, determine the exponent + while (value > one) { //Divide by two, increment exponent by 1 + if (!(value % two).IsZero) { //Add "1.0" to the decimal + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + dec_value = dec_value + dec_max; + } + value = value / two; + if (!(dec_value % ten).IsZero) + dec_value = dec_value * ten; //Creates excess zeroes to avoid losing data during division + dec_value = dec_value / two; + exp++; + } + if (value.IsZero && !dec_value.IsZero) { + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + while (value.IsZero) {//Multiply by two, decrement exponent by 1 + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + one; + } + exp--; + } + } + + //Second, calculate the mantissa + value = new BIM(0); //remove implicit bit + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + for (int i = mantissaSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the mantissa is fully calculated + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + two_n(i); //Note that i is decrementing so that the most significant bit is left-most in the representation + } + } + + return new BigFloat(exp, value, exponentSize, mantissaSize); + } + + // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). + /// + /// NOTE: THIS PROBABLY WON'T GIVE USEFUL OUTPUT!!! + /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative + /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way. + /// + /// The Floor (rounded towards negative infinity) + /// Ceiling (rounded towards positive infinity) + public void FloorCeiling(out BIM floor, out BIM ceiling) { + //TODO: fix for fp functionality + BIM n = Mantissa; + int e = Exponent; + if (n.IsZero) { + floor = ceiling = n; + } else if (0 <= e) { + // it's an integer + for (; 0 < e; e--) { + n = n * two; + } + floor = ceiling = n; + } else { + // it's a non-zero integer, so the ceiling is one more than the floor + for (; e < 0 && !n.IsZero; e++) { + n = n / two; // Division rounds towards negative infinity + } + + if (!IsNegative) { + floor = n; + ceiling = n + 1; + } else { + ceiling = n; + floor = n - 1; + } + } + Debug.Assert(floor <= ceiling, "Invariant was not maintained"); + } + + [Pure] + public String ToDecimalString(int maxDigits) { + //TODO: fix for fp functionality + { + throw new NotImplementedException(); + } + } + + [Pure] + public string ToDecimalString() { + //TODO: fix for fp functionality + string m = Mantissa.ToString(); + var e = Exponent; + if (0 <= Exponent) { + return m + Zeros(e) + ".0"; + } else { + e = -e; + // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string) + var maxK = e < m.Length ? e : m.Length - 1; + var last = m.Length - 1; + var k = 0; + while (k < maxK && m[last - k] == '0') { + k++; + } + if (0 < k) { + // chop off the suffix of k zeros from m and adjust e accordingly + m = m.Substring(0, m.Length - k); + e -= k; + } + if (e == 0) { + return m; + } else if (e < m.Length) { + var n = m.Length - e; + return m.Substring(0, n) + "." + m.Substring(n); + } else { + return "0." + Zeros(e - m.Length) + m; + } + } + } + + [Pure] + public static string Zeros(int n) { + //TODO: fix for fp functionality + Contract.Requires(0 <= n); + if (n <= 10) { + var tenZeros = "0000000000"; + return tenZeros.Substring(0, n); + } else { + var d = n / 2; + var s = Zeros(d); + if (n % 2 == 0) { + return s + s; + } else { + return s + s + "0"; + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Basic arithmetic operations + + [Pure] + public BigFloat Abs { + //TODO: fix for fp functionality + get { + return new BigFloat(Exponent, BIM.Abs(Mantissa), ExponentSize, MantissaSize); + } + } + + [Pure] + public BigFloat Negate { + //TODO: Modify for correct fp functionality + get { + return new BigFloat(Exponent, BIM.Negate(Mantissa), ExponentSize, MantissaSize); + } + } + + [Pure] + public static BigFloat operator -(BigFloat x) { + return x.Negate; + } + + [Pure] + public static BigFloat operator +(BigFloat x, BigFloat y) { + //TODO: Modify for correct fp functionality + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.MantissaSize == y.MantissaSize); + BIM m1 = x.Mantissa; + int e1 = x.Exponent; + BIM m2 = y.Mantissa; + int e2 = y.Exponent; + m1 = m1 + two_n(x.mantissaSize + 1); //Add implicit bit + m2 = m2 + two_n(y.mantissaSize + 1); + if (e2 > e1) { + m1 = y.Mantissa; + e1 = y.Exponent; + m2 = x.Mantissa; + e2 = x.Exponent; + } + + while (e2 < e1) { + m2 = m2 / two; + e2++; + } + + return new BigFloat(e1, m1 + m2, x.MantissaSize, x.ExponentSize); + } + + [Pure] + public static BigFloat operator -(BigFloat x, BigFloat y) { + return x + y.Negate; + } + + [Pure] + public static BigFloat operator *(BigFloat x, BigFloat y) { + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.MantissaSize == y.MantissaSize); + return new BigFloat(x.Exponent + y.Exponent, x.Mantissa * y.Mantissa, x.MantissaSize, x.ExponentSize); + } + + + //////////////////////////////////////////////////////////////////////////// + // Some basic comparison operations + + public bool IsPositive { + get { + return !IsNegative; + } + } + + public bool IsNegative { + get { + return (isDec && dec_value >= BigDec.ZERO) || mantissa >= 0; + } + } + + public bool IsZero { + get { + return Mantissa.IsZero && Exponent == 0; + } + } + + [Pure] + public int CompareTo(BigFloat that) { + if (this.exponent > that.exponent) + return 1; + if (this.exponent < that.exponent) + return -1; + if (this.Mantissa == that.Mantissa) + return 0; + return this.Mantissa > that.Mantissa ? 1 : -1; + } + + [Pure] + public static bool operator ==(BigFloat x, BigFloat y) { + return x.CompareTo(y) == 0; + } + + [Pure] + public static bool operator !=(BigFloat x, BigFloat y) { + return x.CompareTo(y) != 0; + } + + [Pure] + public static bool operator <(BigFloat x, BigFloat y) { + return x.CompareTo(y) < 0; + } + + [Pure] + public static bool operator >(BigFloat x, BigFloat y) { + return x.CompareTo(y) > 0; + } + + [Pure] + public static bool operator <=(BigFloat x, BigFloat y) { + return x.CompareTo(y) <= 0; + } + + [Pure] + public static bool operator >=(BigFloat x, BigFloat y) { + return x.CompareTo(y) >= 0; + } + } +} diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs index 181076a7..cf6fb922 100644 --- a/Source/Core/AbsyExpr.cs +++ b/Source/Core/AbsyExpr.cs @@ -1702,10 +1702,10 @@ namespace Microsoft.Boogie { return Type.Real; } if (arg0type.IsFloat && arg0type.Unify(arg1type)) { - return new FloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa); + return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa); } if (arg1type.IsFloat && arg1type.Unify(arg0type)) { - return new FloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa); + return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa); } goto BAD_TYPE; case Opcode.Div: @@ -1719,6 +1719,12 @@ namespace Microsoft.Boogie { (arg1type.Unify(Type.Int) || arg1type.Unify(Type.Real))) { return Type.Real; } + if (arg0type.IsFloat && arg0type.Unify(arg1type)) { + return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatMantissa); + } + if (arg1type.IsFloat && arg1type.Unify(arg0type)) { + return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatMantissa); + } goto BAD_TYPE; case Opcode.Pow: if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) { @@ -1751,10 +1757,9 @@ namespace Microsoft.Boogie { if (arg0type.Unify(Type.Real) && arg1type.Unify(Type.Real)) { return Type.Bool; } - //if (arg0type.Unify(Type.Float) && arg1type.Unify(Type.Float)) - //{ - //return Type.Bool; - //} + if ((arg0type.IsFloat && arg0type.Unify(arg1type)) || (arg1type.IsFloat && arg1type.Unify(arg0type))) { + return Type.Bool; + } goto BAD_TYPE; case Opcode.And: case Opcode.Or: @@ -1799,9 +1804,6 @@ namespace Microsoft.Boogie { case Opcode.Pow: return Type.Real; - //case Opcode.FloatDiv: - //return Type.Float; - case Opcode.Eq: case Opcode.Neq: case Opcode.Gt: diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index 3633a9c0..f030870e 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -689,12 +689,6 @@ namespace Microsoft.Boogie.SMTLib return true; } - public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options) - { //TODO: match z3 - WriteApplication("/f", node, options); - return true; - } - public bool VisitPowOp(VCExprNAry node, LineariserOptions options) { WriteApplication("real_pow", node, options); return true; @@ -746,12 +740,6 @@ namespace Microsoft.Boogie.SMTLib return true; } - public bool VisitToFloatOp(VCExprNAry node, LineariserOptions options) - { - WriteApplication("to_float", node, options); - return true; - } - private string ExtractDatatype(Function func) { if (func is DatatypeSelector) { DatatypeSelector selector = (DatatypeSelector) func; diff --git a/Source/VCExpr/VCExprASTPrinter.cs b/Source/VCExpr/VCExprASTPrinter.cs index 8b79b0e5..00e6fb9c 100644 --- a/Source/VCExpr/VCExprASTPrinter.cs +++ b/Source/VCExpr/VCExprASTPrinter.cs @@ -302,12 +302,6 @@ namespace Microsoft.Boogie.VCExprAST { //Contract.Requires(node != null); return PrintNAry("/", node, wr); } - public bool VisitFloatDivOp(VCExprNAry node, TextWriter wr) - { - //Contract.Requires(wr != null); - //Contract.Requires(node != null); - return PrintNAry("/f", node, wr); - } public bool VisitPowOp(VCExprNAry node, TextWriter wr) { //Contract.Requires(wr != null); //Contract.Requires(node != null); @@ -353,12 +347,6 @@ namespace Microsoft.Boogie.VCExprAST { //Contract.Requires(node != null); return PrintNAry("real", node, wr); } - public bool VisitToFloatOp(VCExprNAry node, TextWriter wr) - { - //Contract.Requires(wr != null); - //Contract.Requires(node != null); - return PrintNAry("float", node, wr); - } public bool VisitBoogieFunctionOp(VCExprNAry node, TextWriter wr) { //Contract.Requires(wr != null); //Contract.Requires(node != null); diff --git a/float_test5.bpl b/float_test5.bpl index c3d279f2..be72b988 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,5 +1,4 @@ - procedure F() returns () { +procedure F() returns () { var x : float; - var y : float; - assert x + y == fp(0); + assert x - x == fp(0); } \ No newline at end of file diff --git a/float_test6.bpl b/float_test6.bpl index 307da9f7..423bc45a 100644 --- a/float_test6.bpl +++ b/float_test6.bpl @@ -1,5 +1,5 @@ procedure F() returns () { var x : float; - x := fp(1) + fp(1); - assert x == fp(2); + var y : float; + assert (x + x) + (y + y) == fp(0); } \ No newline at end of file -- cgit v1.2.3 From 0324757fb1a12d76861a51be988690bf8de75f64 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Wed, 14 Oct 2015 12:57:50 -0600 Subject: Modified translation so that z3 runs with type checking for simple binary operations --- Source/Basetypes/BigFloat.cs | 48 +++------- Source/Core/AbsyExpr.cs | 1 - Source/Provers/SMTLib/SMTLibLineariser.cs | 76 ++++++++++++++- Source/Provers/SMTLib/Z3.cs | 4 +- Source/VCExpr/Boogie2VCExpr.cs | 36 +++++-- Source/VCExpr/SimplifyLikeLineariser.cs | 120 ++++++++++++++++++++--- Source/VCExpr/TypeErasure.cs | 84 ++++++++++++++++ Source/VCExpr/VCExprAST.cs | 56 ++++++++--- Source/VCExpr/VCExprASTPrinter.cs | 72 ++++++++++++++ Source/VCExpr/VCExprASTVisitors.cs | 154 +++++++++++++++++++++++++++--- float_test5.bpl | 2 +- float_test8.bpl | 5 +- 12 files changed, 570 insertions(+), 88 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index e9d5e670..9e798959 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -33,7 +33,7 @@ namespace Microsoft.Basetypes [Rep] internal readonly int exponentSize; //The bit size of the exponent [Rep] - internal readonly BigDec dec_value; + internal readonly String dec_value; [Rep] internal readonly bool isDec; @@ -61,7 +61,7 @@ namespace Microsoft.Basetypes } } - public BigDec Decimal { + public String Decimal { get { return dec_value; } @@ -102,7 +102,7 @@ namespace Microsoft.Basetypes public static BigFloat FromBigDec(BigDec v) { - return new BigFloat(v, 8, 24); + return new BigFloat(v.ToDecimalString(), 8, 24); } [Pure] @@ -114,11 +114,11 @@ namespace Microsoft.Basetypes { switch (vals.Length) { case 1: - return new BigFloat(BigDec.FromString(vals[0]), 8, 24); + return new BigFloat(vals[0], 8, 24); case 2: return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 24); case 3: - return new BigFloat(BigDec.FromString(vals[0]), Int32.Parse(vals[1]), Int32.Parse(vals[2])); + return new BigFloat(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); case 4: return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); default: @@ -136,10 +136,10 @@ namespace Microsoft.Basetypes this.mantissa = mantissa; this.mantissaSize = mantissaSize; this.isDec = false; - this.dec_value = BigDec.ZERO; + this.dec_value = ""; } - internal BigFloat(BigDec dec_value, int exponentSize, int mantissaSize) { + internal BigFloat(String dec_value, int exponentSize, int mantissaSize) { this.exponentSize = exponentSize; this.mantissaSize = mantissaSize; this.exponent = 0; @@ -181,7 +181,7 @@ namespace Microsoft.Basetypes [Pure] public override string/*!*/ ToString() { Contract.Ensures(Contract.Result() != null); - return String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); + return isDec ? dec_value : String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); } @@ -313,34 +313,8 @@ namespace Microsoft.Basetypes [Pure] public string ToDecimalString() { - //TODO: fix for fp functionality - string m = Mantissa.ToString(); - var e = Exponent; - if (0 <= Exponent) { - return m + Zeros(e) + ".0"; - } else { - e = -e; - // compute k to be the longest suffix of m consisting of all zeros (but no longer than e, and not the entire string) - var maxK = e < m.Length ? e : m.Length - 1; - var last = m.Length - 1; - var k = 0; - while (k < maxK && m[last - k] == '0') { - k++; - } - if (0 < k) { - // chop off the suffix of k zeros from m and adjust e accordingly - m = m.Substring(0, m.Length - k); - e -= k; - } - if (e == 0) { - return m; - } else if (e < m.Length) { - var n = m.Length - e; - return m.Substring(0, n) + "." + m.Substring(n); - } else { - return "0." + Zeros(e - m.Length) + m; - } - } + Contract.Ensures(Contract.Result() != null); + return isDec ? dec_value : String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); } [Pure] @@ -436,7 +410,7 @@ namespace Microsoft.Basetypes public bool IsNegative { get { - return (isDec && dec_value >= BigDec.ZERO) || mantissa >= 0; + return (isDec && dec_value[0] == '-') || mantissa < 0; } } diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs index cf6fb922..ad537288 100644 --- a/Source/Core/AbsyExpr.cs +++ b/Source/Core/AbsyExpr.cs @@ -1642,7 +1642,6 @@ namespace Microsoft.Boogie { case Opcode.Div: case Opcode.Mod: case Opcode.RealDiv: - case Opcode.FloatDiv: case Opcode.Pow: case Opcode.Neq: // Neq is allowed, but not Eq case Opcode.Subtype: diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index f030870e..629f7e2d 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -141,7 +141,7 @@ namespace Microsoft.Boogie.SMTLib else if (t.IsReal) return "Real"; else if (t.IsFloat) - return "(_ FloatingPoint " + t.FloatExponent + " " + t.FloatMantissa + ")"; //TODO: Match z3 syntax + return "(_ FloatingPoint " + t.FloatExponent + " " + t.FloatMantissa + ")"; else if (t.IsBv) { return "(_ BitVec " + t.BvBits + ")"; } else { @@ -204,11 +204,13 @@ namespace Microsoft.Boogie.SMTLib else if (node is VCExprFloatLit) { BigFloat lit = ((VCExprFloatLit)node).Val; + wr.Write(("((_ to_fp 8 24) roundTowardZero ")); if (lit.IsNegative) // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString()); else wr.Write(lit.ToDecimalString()); + wr.Write(")"); } else { Contract.Assert(false); @@ -616,6 +618,78 @@ namespace Microsoft.Boogie.SMTLib return true; } + public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.add roundTowardZero", node, options); + return true; + } + + public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.sub roundTowardZero", node, options); + return true; + } + + public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.mul roundTowardZero", node, options); + return true; + } + + public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.div roundTowardZero", node, options); + return true; + } + + public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.rem roundTowardZero", node, options); + return true; + } + + public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.min", node, options); + return true; + } + + public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.max", node, options); + return true; + } + + public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.leq", node, options); + return true; + } + + public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.lt", node, options); + return true; + } + + public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.geq", node, options); + return true; + } + + public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.gt", node, options); + return true; + } + + public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options) + { + WriteApplication("fp.eq", node, options); + return true; + } + static char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public bool VisitBvOp(VCExprNAry node, LineariserOptions options) { diff --git a/Source/Provers/SMTLib/Z3.cs b/Source/Provers/SMTLib/Z3.cs index 8e8b2d55..250e04c9 100644 --- a/Source/Provers/SMTLib/Z3.cs +++ b/Source/Provers/SMTLib/Z3.cs @@ -253,7 +253,7 @@ namespace Microsoft.Boogie.SMTLib //if (options.Inspector != null) // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); - options.AddWeakSmtOption("TYPE_CHECK", "false"); + options.AddWeakSmtOption("TYPE_CHECK", "true"); options.AddWeakSmtOption("smt.BV.REFLECT", "true"); if (options.TimeLimit > 0) @@ -334,7 +334,7 @@ namespace Microsoft.Boogie.SMTLib //if (options.Inspector != null) // options.WeakAddSmtOption("PROGRESS_SAMPLING_FREQ", "100"); - options.AddWeakSmtOption("TYPE_CHECK", "false"); + options.AddWeakSmtOption("TYPE_CHECK", "true"); options.AddWeakSmtOption("BV_REFLECT", "true"); if (options.TimeLimit > 0) diff --git a/Source/VCExpr/Boogie2VCExpr.cs b/Source/VCExpr/Boogie2VCExpr.cs index f0dc505d..ad319c0e 100644 --- a/Source/VCExpr/Boogie2VCExpr.cs +++ b/Source/VCExpr/Boogie2VCExpr.cs @@ -1076,34 +1076,48 @@ namespace Microsoft.Boogie.VCExprAST { Contract.Requires(cce.NonNullElements(args)); Contract.Ensures(Contract.Result() != null); Contract.Assert(args.Count == 2); + Type t = cce.NonNull(cce.NonNull(args[0]).Type); switch (app.Op) { case BinaryOperator.Opcode.Add: - if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) { + if (t.IsInt) { return Gen.Function(VCExpressionGenerator.AddIOp, args); } - else { + else if (t.IsReal) { return Gen.Function(VCExpressionGenerator.AddROp, args); } + else { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "+"), args); + } case BinaryOperator.Opcode.Sub: - if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) { + if (t.IsInt) { return Gen.Function(VCExpressionGenerator.SubIOp, args); } - else { + else if (t.IsReal) { return Gen.Function(VCExpressionGenerator.SubROp, args); } + else { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "-"), args); + } case BinaryOperator.Opcode.Mul: - if (cce.NonNull(cce.NonNull(args[0]).Type).IsInt) { + if (t.IsInt) { return Gen.Function(VCExpressionGenerator.MulIOp, args); } - else { + else if (t.IsReal) { return Gen.Function(VCExpressionGenerator.MulROp, args); } + else + { //t is float + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "*"), args); + } case BinaryOperator.Opcode.Div: return Gen.Function(VCExpressionGenerator.DivIOp, args); case BinaryOperator.Opcode.Mod: return Gen.Function(VCExpressionGenerator.ModOp, args); case BinaryOperator.Opcode.RealDiv: + if (t.IsFloat) { + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "/"), args); + } VCExpr arg0 = cce.NonNull(args[0]); VCExpr arg1 = cce.NonNull(args[1]); if (cce.NonNull(arg0.Type).IsInt) { @@ -1118,16 +1132,26 @@ namespace Microsoft.Boogie.VCExprAST { case BinaryOperator.Opcode.Eq: case BinaryOperator.Opcode.Iff: // we don't distinguish between equality and equivalence at this point + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "=="), args); return Gen.Function(VCExpressionGenerator.EqOp, args); case BinaryOperator.Opcode.Neq: return Gen.Function(VCExpressionGenerator.NeqOp, args); case BinaryOperator.Opcode.Lt: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<"), args); return Gen.Function(VCExpressionGenerator.LtOp, args); case BinaryOperator.Opcode.Le: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, "<="), args); return Gen.Function(VCExpressionGenerator.LeOp, args); case BinaryOperator.Opcode.Ge: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">="), args); return Gen.Function(VCExpressionGenerator.GeOp, args); case BinaryOperator.Opcode.Gt: + if (t.IsFloat) + return Gen.Function(Gen.BinaryFloatOp(t.FloatExponent, t.FloatMantissa, ">"), args); return Gen.Function(VCExpressionGenerator.GtOp, args); case BinaryOperator.Opcode.Imp: return Gen.Function(VCExpressionGenerator.ImpliesOp, args); diff --git a/Source/VCExpr/SimplifyLikeLineariser.cs b/Source/VCExpr/SimplifyLikeLineariser.cs index 0ff6d67f..6f74fe08 100644 --- a/Source/VCExpr/SimplifyLikeLineariser.cs +++ b/Source/VCExpr/SimplifyLikeLineariser.cs @@ -384,6 +384,14 @@ namespace Microsoft.Boogie.VCExprAST { internal const string floatSubName = "floatSub"; internal const string floatMulName = "floatMul"; internal const string floatDivName = "floatDiv"; + internal const string floatRemName = "floatRem"; + internal const string floatMinName = "floatMin"; + internal const string floatMaxName = "floatMax"; + internal const string floatLeqName = "floatLeq"; + internal const string floatLtName = "floatLt"; + internal const string floatGeqName = "floatGeq"; + internal const string floatGtName = "floatGt"; + internal const string floatEqName = "floatEq"; internal const string realPowName = "realPow"; internal const string toIntName = "toIntCoercion"; internal const string toRealName = "toRealCoercion"; @@ -888,7 +896,104 @@ namespace Microsoft.Boogie.VCExprAST { return true; } - public bool VisitBvOp(VCExprNAry node, LineariserOptions options) { + public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatAddName, node, options); + return true; + } + + public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatSubName, node, options); + return true; + } + + public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatMulName, node, options); + return true; + } + + public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatDivName, node, options); + return true; + } + + public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatRemName, node, options); + return true; + } + + public bool VisitFloatMinOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatMinName, node, options); + return true; + } + + public bool VisitFloatMaxOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatMaxName, node, options); + return true; + } + + public bool VisitFloatLeqOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatLeqName, node, options); + return true; + } + + public bool VisitFloatLtOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatLtName, node, options); + return true; + } + + public bool VisitFloatGeqOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatGeqName, node, options); + return true; + } + + public bool VisitFloatGtOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatGtName, node, options); + return true; + } + + public bool VisitFloatEqOp(VCExprNAry node, LineariserOptions options) + { + //Contract.Requires(options != null); + //Contract.Requires(node != null); + WriteTermApplication(floatEqName, node, options); + return true; + } + + public bool VisitBvOp(VCExprNAry node, LineariserOptions options) + { //Contract.Requires(options != null); //Contract.Requires(node != null); WriteTermApplication("$make_bv" + node.Type.BvBits, node, options); @@ -948,11 +1053,8 @@ namespace Microsoft.Boogie.VCExprAST { WriteTermApplication(intAddName, node, options); } } - else if (node.Type.IsReal) { - WriteTermApplication(realAddName, node, options); - } else { - WriteTermApplication(floatAddName, node, options); + WriteTermApplication(realAddName, node, options); } return true; } @@ -1008,14 +1110,6 @@ namespace Microsoft.Boogie.VCExprAST { return true; } - public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options) - { - //Contract.Requires(options != null); - //Contract.Requires(node != null); - WriteTermApplication(floatDivName, node, options); - return true; - } - public bool VisitPowOp(VCExprNAry node, LineariserOptions options) { //Contract.Requires(options != null); //Contract.Requires(node != null); diff --git a/Source/VCExpr/TypeErasure.cs b/Source/VCExpr/TypeErasure.cs index 5e821ea2..6fb38c27 100644 --- a/Source/VCExpr/TypeErasure.cs +++ b/Source/VCExpr/TypeErasure.cs @@ -1479,6 +1479,90 @@ namespace Microsoft.Boogie.TypeErasure { Contract.Ensures(Contract.Result() != null); return CastArgumentsToOldType(node, bindings, 0); } + public override VCExpr VisitFloatAddOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatSubOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatMulOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatDivOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatRemOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatMinOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatMaxOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatLeqOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatLtOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatGeqOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatGtOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } + public override VCExpr VisitFloatEqOp(VCExprNAry node, VariableBindings bindings) + { + Contract.Requires((bindings != null)); + Contract.Requires((node != null)); + Contract.Ensures(Contract.Result() != null); + return CastArgumentsToOldType(node, bindings, 0); + } public override VCExpr VisitBvOp(VCExprNAry node, VariableBindings bindings) { Contract.Requires((bindings != null)); Contract.Requires((node != null)); diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs index c44800fc..3f6e3b7a 100644 --- a/Source/VCExpr/VCExprAST.cs +++ b/Source/VCExpr/VCExprAST.cs @@ -324,7 +324,6 @@ namespace Microsoft.Boogie { public static readonly VCExprOp AddIOp = new VCExprNAryOp(2, Type.Int); public static readonly VCExprOp AddROp = new VCExprNAryOp(2, Type.Real); - //public static readonly VCExprOp AddFOp = new VCExprNAryOp(2, Type.Float); public static readonly VCExprOp SubIOp = new VCExprNAryOp(2, Type.Int); public static readonly VCExprOp SubROp = new VCExprNAryOp(2, Type.Real); // public static readonly VCExprOp SubFOp = new VCExprNAryOp(2, Type.Float); @@ -359,11 +358,13 @@ namespace Microsoft.Boogie { // Float nodes - public VCExpr AddFOp(VCExpr f1, VCExpr f2) + public VCExprOp BinaryFloatOp(int exp, int man, string op) { - Contract.Requires(f1 != null); - Contract.Requires(f2 != null); - return Function(new VCExprFloatOp(f1.Type.FloatExponent, f1.Type.FloatMantissa)); + Contract.Requires(exp > 0); + Contract.Requires(man > 0); + Contract.Requires(op != null); + Contract.Ensures(Contract.Result() != null); + return new VCExprBinaryFloatOp(exp, man, op); } // Bitvector nodes @@ -441,7 +442,6 @@ namespace Microsoft.Boogie { SingletonOpDict.Add(ImpliesOp, SingletonOp.ImpliesOp); SingletonOpDict.Add(AddIOp, SingletonOp.AddOp); SingletonOpDict.Add(AddROp, SingletonOp.AddOp); - //SingletonOpDict.Add(AddFOp, SingletonOp.AddOp); SingletonOpDict.Add(SubIOp, SingletonOp.SubOp); SingletonOpDict.Add(SubROp, SingletonOp.SubOp); //SingletonOpDict.Add(SubFOp, SingletonOp.SubOp); @@ -1677,18 +1677,19 @@ namespace Microsoft.Boogie.VCExprAST { ///////////////////////////////////////////////////////////////////////////////// // Float operators - public class VCExprFloatOp : VCExprOp { + public class VCExprBinaryFloatOp : VCExprOp { public readonly int Mantissa; public readonly int Exponent; + private string op; public override int Arity { get { - return 1; + return 2; } } public override int TypeParamArity { get { - return 0; + return 2; } } public override Type InferType(List args, List/*!*/ typeArgs) { @@ -1703,8 +1704,8 @@ namespace Microsoft.Boogie.VCExprAST { public override bool Equals(object that) { if (Object.ReferenceEquals(this, that)) return true; - if (that is VCExprFloatOp) - return this.Exponent == ((VCExprFloatOp)that).Exponent && this.Mantissa == ((VCExprFloatOp)that).Mantissa; + if (that is VCExprBinaryFloatOp) + return this.Exponent == ((VCExprBinaryFloatOp)that).Exponent && this.Mantissa == ((VCExprBinaryFloatOp)that).Mantissa; return false; } [Pure] @@ -1712,15 +1713,44 @@ namespace Microsoft.Boogie.VCExprAST { return Exponent * 81748912 + Mantissa * 67867979; } - internal VCExprFloatOp(int exp, int man) { + internal VCExprBinaryFloatOp(int exp, int man, string op) { this.Exponent = exp; this.Mantissa = man; + this.op = op; } public override Result Accept (VCExprNAry expr, IVCExprOpVisitor visitor, Arg arg) { //Contract.Requires(visitor != null); //Contract.Requires(expr != null); - return visitor.VisitBvOp(expr, arg); + switch (op) { + case ("+"): + return visitor.VisitFloatAddOp(expr, arg); + case ("-"): + return visitor.VisitFloatSubOp(expr, arg); + case ("*"): + return visitor.VisitFloatMulOp(expr, arg); + case ("/"): + return visitor.VisitFloatDivOp(expr, arg); + case ("rem"): + return visitor.VisitFloatRemOp(expr, arg); + case ("min"): + return visitor.VisitFloatMinOp(expr, arg); + case ("max"): + return visitor.VisitFloatMaxOp(expr, arg); + case ("<="): + return visitor.VisitFloatLeqOp(expr, arg); + case ("<"): + return visitor.VisitFloatLtOp(expr, arg); + case (">="): + return visitor.VisitFloatGeqOp(expr, arg); + case (">"): + return visitor.VisitFloatGtOp(expr, arg); + case ("=="): + return visitor.VisitFloatEqOp(expr, arg); + default: + Contract.Assert(false); + throw new cce.UnreachableException(); + } } } diff --git a/Source/VCExpr/VCExprASTPrinter.cs b/Source/VCExpr/VCExprASTPrinter.cs index 00e6fb9c..8e2f5d12 100644 --- a/Source/VCExpr/VCExprASTPrinter.cs +++ b/Source/VCExpr/VCExprASTPrinter.cs @@ -242,6 +242,78 @@ namespace Microsoft.Boogie.VCExprAST { //Contract.Requires(node != null); return PrintNAry("Store", node, wr); } + public bool VisitFloatAddOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.add", node, wr); + } + public bool VisitFloatSubOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.sub", node, wr); + } + public bool VisitFloatMulOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.mul", node, wr); + } + public bool VisitFloatDivOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.div", node, wr); + } + public bool VisitFloatRemOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.rem", node, wr); + } + public bool VisitFloatMinOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.min", node, wr); + } + public bool VisitFloatMaxOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.max", node, wr); + } + public bool VisitFloatLeqOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.leq", node, wr); + } + public bool VisitFloatLtOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.lt", node, wr); + } + public bool VisitFloatGeqOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.geq", node, wr); + } + public bool VisitFloatGtOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.gt", node, wr); + } + public bool VisitFloatEqOp(VCExprNAry node, TextWriter wr) + { + //Contract.Requires(wr != null); + //Contract.Requires(node != null); + return PrintNAry("fp.eq", node, wr); + } public bool VisitBvOp(VCExprNAry node, TextWriter wr) { //Contract.Requires(wr != null); //Contract.Requires(node != null); diff --git a/Source/VCExpr/VCExprASTVisitors.cs b/Source/VCExpr/VCExprASTVisitors.cs index a1fb2ff4..c81f69e5 100644 --- a/Source/VCExpr/VCExprASTVisitors.cs +++ b/Source/VCExpr/VCExprASTVisitors.cs @@ -68,6 +68,18 @@ namespace Microsoft.Boogie.VCExprAST { Result VisitLabelOp(VCExprNAry node, Arg arg); Result VisitSelectOp(VCExprNAry node, Arg arg); Result VisitStoreOp(VCExprNAry node, Arg arg); + Result VisitFloatAddOp(VCExprNAry node, Arg arg); + Result VisitFloatSubOp(VCExprNAry node, Arg arg); + Result VisitFloatMulOp(VCExprNAry node, Arg arg); + Result VisitFloatDivOp(VCExprNAry node, Arg arg); + Result VisitFloatRemOp(VCExprNAry node, Arg arg); + Result VisitFloatMinOp(VCExprNAry node, Arg arg); + Result VisitFloatMaxOp(VCExprNAry node, Arg arg); + Result VisitFloatLeqOp(VCExprNAry node, Arg arg); + Result VisitFloatLtOp(VCExprNAry node, Arg arg); + Result VisitFloatGeqOp(VCExprNAry node, Arg arg); + Result VisitFloatGtOp(VCExprNAry node, Arg arg); + Result VisitFloatEqOp(VCExprNAry node, Arg arg); Result VisitBvOp(VCExprNAry node, Arg arg); Result VisitBvExtractOp(VCExprNAry node, Arg arg); Result VisitBvConcatOp(VCExprNAry node, Arg arg); @@ -144,6 +156,78 @@ namespace Microsoft.Boogie.VCExprAST { throw new NotImplementedException(); } + public Result VisitFloatAddOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatSubOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatMulOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatDivOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatRemOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatMinOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatMaxOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatLeqOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatLtOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatGeqOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatGtOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + + public Result VisitFloatEqOp(VCExprNAry node, Arg arg) + { + Contract.Requires(node != null); + throw new NotImplementedException(); + } + public Result VisitBvOp(VCExprNAry node, Arg arg) { Contract.Requires(node != null); throw new NotImplementedException(); @@ -189,12 +273,6 @@ namespace Microsoft.Boogie.VCExprAST { throw new NotImplementedException(); } - public Result VisitFloatDivOp(VCExprNAry node, Arg arg) - { - Contract.Requires(node != null); - throw new NotImplementedException(); - } - public Result VisitPowOp(VCExprNAry node, Arg arg) { Contract.Requires(node != null); throw new NotImplementedException(); @@ -1450,6 +1528,65 @@ namespace Microsoft.Boogie.VCExprAST { //Contract.Requires(node != null); return StandardResult(node, arg); } + public virtual Result VisitFloatAddOp(VCExprNAry node, Arg arg) { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatSubOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatMulOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatDivOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatRemOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatMinOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatMaxOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatLeqOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatLtOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatGeqOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatGtOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } + public virtual Result VisitFloatEqOp(VCExprNAry node, Arg arg) + { + //Contract.Requires(node != null); + return StandardResult(node, arg); + } public virtual Result VisitBvOp(VCExprNAry node, Arg arg) { //Contract.Requires(node != null); return StandardResult(node, arg); @@ -1494,11 +1631,6 @@ namespace Microsoft.Boogie.VCExprAST { //Contract.Requires(node != null); return StandardResult(node, arg); } - public virtual Result VisitFloatDivOp(VCExprNAry node, Arg arg) - { - //Contract.Requires(node != null); - return StandardResult(node, arg); - } public virtual Result VisitPowOp(VCExprNAry node, Arg arg) { //Contract.Requires(node != null); return StandardResult(node, arg); diff --git a/float_test5.bpl b/float_test5.bpl index be72b988..2661a736 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,4 +1,4 @@ procedure F() returns () { var x : float; - assert x - x == fp(0); + assert x - x == fp(0.0); } \ No newline at end of file diff --git a/float_test8.bpl b/float_test8.bpl index 7c23c74f..32fb8863 100644 --- a/float_test8.bpl +++ b/float_test8.bpl @@ -1,6 +1,5 @@ procedure F() returns () { - Logic=QF_FP; var x : float; - x := fp(.1) + fp(.1); - assert x == fp(.2); + x := fp(0.1) + fp(0.1); + assert x == fp(0.2); } \ No newline at end of file -- cgit v1.2.3 From a3b2bfa16f991f4d5f844b6d18e836e57b4195a1 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Wed, 14 Oct 2015 13:02:48 -0600 Subject: Floating point constants given as integers are now translated correctly --- Source/Basetypes/BigFloat.cs | 2 ++ float_test5.bpl | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 9e798959..bbc39db4 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -146,6 +146,8 @@ namespace Microsoft.Basetypes this.mantissa = 0; this.isDec = true; this.dec_value = dec_value; + if (this.dec_value.IndexOf(".") == -1) + this.dec_value += ".0"; //Assures that the decimal value is a "real" number } private BIM maxMantissa() diff --git a/float_test5.bpl b/float_test5.bpl index 2661a736..be72b988 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,4 +1,4 @@ procedure F() returns () { var x : float; - assert x - x == fp(0.0); + assert x - x == fp(0); } \ No newline at end of file -- cgit v1.2.3 From a1c9e11736bda4bf8ea4bf431523b9b975b01670 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Sun, 29 Nov 2015 14:28:17 -0700 Subject: Special fp types (such as infinity and NaN are now translated by boogie --- Source/Basetypes/BigFloat.cs | 68 +++++++++++++++++++++++-------- Source/Core/Parser.cs | 4 +- Source/Provers/SMTLib/SMTLibLineariser.cs | 16 +++++--- float_test8.bpl | 4 +- 4 files changed, 64 insertions(+), 28 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index bbc39db4..6cf94feb 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -25,7 +25,7 @@ namespace Microsoft.Basetypes // the internal representation [Rep] - internal readonly BIM mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) + internal readonly long mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) [Rep] internal readonly int mantissaSize; [Rep] @@ -37,7 +37,7 @@ namespace Microsoft.Basetypes [Rep] internal readonly bool isDec; - public BIM Mantissa { + public long Mantissa { get { return mantissa; } @@ -69,17 +69,17 @@ namespace Microsoft.Basetypes public bool IsDec { get { - return IsDec; + return isDec; } } public static BigFloat ZERO(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Does not include negative zero private static readonly BIM two = new BIM(2); - private static BIM two_n(int n) { - BIM toReturn = new BIM(1); + private static long two_n(int n) { + long toReturn = 1; for (int i = 0; i < n; i++) - toReturn = toReturn * two; + toReturn = toReturn * 2; return toReturn; } @@ -96,10 +96,14 @@ namespace Microsoft.Basetypes } [Pure] - public static BigFloat FromBigInt(BIM v) { + public static BigFloat FromLong(long v) { return new BigFloat(0, v, 8, 24); } + public static BigFloat FromBigInt(BIM v) { + return FromLong(Int64.Parse(v.ToString())); //Sketchy. Hope this doesn't cause problems + } + public static BigFloat FromBigDec(BigDec v) { return new BigFloat(v.ToDecimalString(), 8, 24); @@ -116,11 +120,11 @@ namespace Microsoft.Basetypes case 1: return new BigFloat(vals[0], 8, 24); case 2: - return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), 8, 24); + return new BigFloat(Int32.Parse(vals[0]), Int64.Parse(vals[1]), 8, 24); case 3: return new BigFloat(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); case 4: - return new BigFloat(Int32.Parse(vals[0]), BIM.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); + return new BigFloat(Int32.Parse(vals[0]), Int64.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); default: throw new FormatException(); //Unreachable } @@ -130,7 +134,7 @@ namespace Microsoft.Basetypes } } - internal BigFloat(int exponent, BIM mantissa, int exponentSize, int mantissaSize) { + internal BigFloat(int exponent, long mantissa, int exponentSize, int mantissaSize) { this.exponentSize = exponentSize; this.exponent = exponent; this.mantissa = mantissa; @@ -146,8 +150,30 @@ namespace Microsoft.Basetypes this.mantissa = 0; this.isDec = true; this.dec_value = dec_value; + //Special cases: + if (this.dec_value.Equals("+oo") || this.dec_value.Equals("-oo") || this.dec_value.Equals("-zero")) + return; + if (this.dec_value.ToLower().Equals("nan")) { + this.dec_value = "NaN"; + return; + } + if (this.dec_value.Equals("INF") || this.dec_value.Equals("+INF")) { + this.dec_value = "+oo"; + return; + } + if (this.dec_value.Equals("-INF")) { + this.dec_value = "-oo"; + return; + } + if (this.dec_value.Equals("+zero")) { + this.dec_value = "0.0"; + return; + } + //End special cases if (this.dec_value.IndexOf(".") == -1) this.dec_value += ".0"; //Assures that the decimal value is a "real" number + if (this.dec_value.IndexOf(".") == 0) + this.dec_value = "0" + this.dec_value; //Assures that decimals always have a 0 in front } private BIM maxMantissa() @@ -265,7 +291,7 @@ namespace Microsoft.Basetypes } } - return new BigFloat(exp, value, exponentSize, mantissaSize); + return new BigFloat(exp, Int64.Parse(value.ToString()), exponentSize, mantissaSize); } // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). @@ -345,7 +371,7 @@ namespace Microsoft.Basetypes public BigFloat Abs { //TODO: fix for fp functionality get { - return new BigFloat(Exponent, BIM.Abs(Mantissa), ExponentSize, MantissaSize); + return new BigFloat(Exponent, Math.Abs(Mantissa), ExponentSize, MantissaSize); } } @@ -353,7 +379,7 @@ namespace Microsoft.Basetypes public BigFloat Negate { //TODO: Modify for correct fp functionality get { - return new BigFloat(Exponent, BIM.Negate(Mantissa), ExponentSize, MantissaSize); + return new BigFloat(Exponent, -Mantissa, ExponentSize, MantissaSize); } } @@ -367,9 +393,9 @@ namespace Microsoft.Basetypes //TODO: Modify for correct fp functionality Contract.Requires(x.ExponentSize == y.ExponentSize); Contract.Requires(x.MantissaSize == y.MantissaSize); - BIM m1 = x.Mantissa; + long m1 = x.Mantissa; int e1 = x.Exponent; - BIM m2 = y.Mantissa; + long m2 = y.Mantissa; int e2 = y.Exponent; m1 = m1 + two_n(x.mantissaSize + 1); //Add implicit bit m2 = m2 + two_n(y.mantissaSize + 1); @@ -381,7 +407,7 @@ namespace Microsoft.Basetypes } while (e2 < e1) { - m2 = m2 / two; + m2 = m2 / 2; e2++; } @@ -404,6 +430,14 @@ namespace Microsoft.Basetypes //////////////////////////////////////////////////////////////////////////// // Some basic comparison operations + public bool IsSpecialType { + get { + if (!IsDec) + return false; + return (dec_value.Equals("NaN") || dec_value.Equals("+oo") || dec_value.Equals("-oo") || dec_value.Equals("-zero")); + } + } + public bool IsPositive { get { return !IsNegative; @@ -418,7 +452,7 @@ namespace Microsoft.Basetypes public bool IsZero { get { - return Mantissa.IsZero && Exponent == 0; + return Mantissa == 0 && Exponent == 0; } } diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 889d7be8..5fcb1cdc 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -1897,9 +1897,9 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Get(); //Skip the fp token Get(); if (t.val != "(") { throw new FormatException(); } - while (la.kind == 1 || la.kind == 3 || la.kind == 6 || la.kind == 75) { //Get values between the parens + while (la.kind == 1 || la.kind == 3 || la.kind == 6 || la.kind == 4 || la.kind == 74 || la.kind == 75) { //Get values between the parens Get(); - if (t.val == "-") //special negative case (la.kind == 75) + if (t.val == "-" || t.val == "+") //special sign case (la.kind == 74 or 75) s += t.val; else s += t.val + " "; diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index 629f7e2d..7c3ae960 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -204,7 +204,11 @@ namespace Microsoft.Boogie.SMTLib else if (node is VCExprFloatLit) { BigFloat lit = ((VCExprFloatLit)node).Val; - wr.Write(("((_ to_fp 8 24) roundTowardZero ")); + if (lit.IsSpecialType) { + wr.Write("(_ " + lit.Decimal + " " + lit.ExponentSize.ToString() + " " + lit.MantissaSize.ToString() + ")"); + return true; + } + wr.Write("((_ to_fp " + lit.ExponentSize.ToString() + " " + lit.MantissaSize.ToString() + ") RNE "); if (lit.IsNegative) // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString()); @@ -620,31 +624,31 @@ namespace Microsoft.Boogie.SMTLib public bool VisitFloatAddOp(VCExprNAry node, LineariserOptions options) { - WriteApplication("fp.add roundTowardZero", node, options); + WriteApplication("fp.add RNE", node, options); return true; } public bool VisitFloatSubOp(VCExprNAry node, LineariserOptions options) { - WriteApplication("fp.sub roundTowardZero", node, options); + WriteApplication("fp.sub RNE", node, options); return true; } public bool VisitFloatMulOp(VCExprNAry node, LineariserOptions options) { - WriteApplication("fp.mul roundTowardZero", node, options); + WriteApplication("fp.mul RNE", node, options); return true; } public bool VisitFloatDivOp(VCExprNAry node, LineariserOptions options) { - WriteApplication("fp.div roundTowardZero", node, options); + WriteApplication("fp.div RNE", node, options); return true; } public bool VisitFloatRemOp(VCExprNAry node, LineariserOptions options) { - WriteApplication("fp.rem roundTowardZero", node, options); + WriteApplication("fp.rem RNE", node, options); return true; } diff --git a/float_test8.bpl b/float_test8.bpl index 32fb8863..554dcf00 100644 --- a/float_test8.bpl +++ b/float_test8.bpl @@ -1,5 +1,3 @@ procedure F() returns () { - var x : float; - x := fp(0.1) + fp(0.1); - assert x == fp(0.2); + assert fp(-oo)==fp(-oo); } \ No newline at end of file -- cgit v1.2.3 From 6fad4313b1a4e7f8e6cfcd12b92126a3d9ad58d0 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Mon, 4 Jan 2016 19:26:36 -0800 Subject: Added several test cases and some basic documentation for fp usage --- Source/AbsInt/IntervalDomain.cs | 29 ++++++++++++-- Source/Basetypes/BigFloat.cs | 30 +++++++++----- Source/BoogieDriver/BoogieDriver.cs | 2 +- float_test.bpl | 16 ++++++-- float_test10.bpl | 21 ++++++++-- float_test11.bpl | 38 ++++++++++++++++++ float_test12.bpl | 43 ++++++++++++++++++++ float_test13.bpl | 17 ++++++++ float_test14.bpl | 17 ++++++++ float_test15.bpl | 24 +++++++++++ float_test16.bpl | 8 ++++ float_test17.bpl | 11 ++++++ float_test18.bpl | 36 +++++++++++++++++ float_test19.bpl | 36 +++++++++++++++++ float_test2.bpl | 16 ++++++-- float_test20.bpl | 14 +++++++ float_test3.bpl | 14 ++++++- float_test4.bpl | 23 +++++++++-- float_test5.bpl | 35 ++++++++++++++-- float_test6.bpl | 43 ++++++++++++++++++-- float_test7.bpl | 41 +++++++++++++++++-- float_test8.bpl | 13 +++++- float_test9.bpl | 37 +++++++++++++++-- fp_documentation.txt | 79 +++++++++++++++++++++++++++++++++++++ 24 files changed, 596 insertions(+), 47 deletions(-) create mode 100644 float_test11.bpl create mode 100644 float_test12.bpl create mode 100644 float_test13.bpl create mode 100644 float_test14.bpl create mode 100644 float_test15.bpl create mode 100644 float_test16.bpl create mode 100644 float_test17.bpl create mode 100644 float_test18.bpl create mode 100644 float_test19.bpl create mode 100644 float_test20.bpl create mode 100644 fp_documentation.txt (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs index a27ae68d..0c954f9a 100644 --- a/Source/AbsInt/IntervalDomain.cs +++ b/Source/AbsInt/IntervalDomain.cs @@ -180,8 +180,7 @@ namespace Microsoft.Boogie.AbstractInterpretation } } return e; - } else { - Contract.Assert(V.TypedIdent.Type.IsReal); + } else if (V.TypedIdent.Type.IsReal){ Expr e = Expr.True; if (Lo != null && Hi != null && Lo == Hi) { // produce an equality @@ -199,6 +198,30 @@ namespace Microsoft.Boogie.AbstractInterpretation } } return e; + } else { + Contract.Assert(V.TypedIdent.Type.IsFloat); + Expr e = Expr.True; + if (Lo != null && Hi != null && Lo == Hi) + { + // produce an equality + var ide = new IdentifierExpr(Token.NoToken, V); + e = Expr.And(e, BplEq(ide, NumberToExpr((BigInteger)Lo, V.TypedIdent.Type))); + } + else + { + // produce a (possibly empty) conjunction of inequalities + if (Lo != null) + { + var ide = new IdentifierExpr(Token.NoToken, V); + e = Expr.And(e, BplLe(NumberToExpr((BigInteger)Lo, V.TypedIdent.Type), ide)); + } + if (Hi != null) + { + var ide = new IdentifierExpr(Token.NoToken, V); + e = Expr.And(e, BplLe(ide, NumberToExpr((BigInteger)Hi, V.TypedIdent.Type))); + } + } + return e; } } } @@ -209,7 +232,7 @@ namespace Microsoft.Boogie.AbstractInterpretation } else if (ty.IsReal) { return Expr.Literal(Basetypes.BigDec.FromBigInt(n)); } else if (ty.IsFloat) { - return Expr.Literal(Basetypes.BigFloat.FromBigInt(n)); + return Expr.Literal(Basetypes.BigFloat.FromBigInt(n, ty.FloatExponent, ty.FloatMantissa)); } else { Contract.Assume(ty.IsInt); return Expr.Literal(Basetypes.BigNum.FromBigInt(n)); diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 6cf94feb..5b169263 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -92,16 +92,21 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat FromInt(int v) { - return new BigFloat(v, 0, 24, 8); + return new BigFloat(v.ToString(), 8, 24); } - [Pure] - public static BigFloat FromLong(long v) { - return new BigFloat(0, v, 8, 24); + public static BigFloat FromInt(int v, int exponentSize, int mantissaSize) + { + return new BigFloat(v.ToString(), exponentSize, mantissaSize); } public static BigFloat FromBigInt(BIM v) { - return FromLong(Int64.Parse(v.ToString())); //Sketchy. Hope this doesn't cause problems + return new BigFloat(v.ToString(), 8, 24); + } + + public static BigFloat FromBigInt(BIM v, int exponentSize, int mantissaSize) + { + return new BigFloat(v.ToString(), exponentSize, mantissaSize); } public static BigFloat FromBigDec(BigDec v) @@ -109,6 +114,11 @@ namespace Microsoft.Basetypes return new BigFloat(v.ToDecimalString(), 8, 24); } + public static BigFloat FromBigDec(BigDec v, int exponentSize, int mantissaSize) + { + return new BigFloat(v.ToDecimalString(), exponentSize, mantissaSize); + } + [Pure] public static BigFloat FromString(string v) { String[] vals = v.Split(' '); @@ -170,9 +180,9 @@ namespace Microsoft.Basetypes return; } //End special cases - if (this.dec_value.IndexOf(".") == -1) + if (this.dec_value.IndexOf('.') == -1 && this.dec_value.IndexOf('e') == -1) this.dec_value += ".0"; //Assures that the decimal value is a "real" number - if (this.dec_value.IndexOf(".") == 0) + if (this.dec_value.IndexOf('.') == 0) this.dec_value = "0" + this.dec_value; //Assures that decimals always have a 0 in front } @@ -369,16 +379,18 @@ namespace Microsoft.Basetypes [Pure] public BigFloat Abs { - //TODO: fix for fp functionality get { + if (IsDec) + return dec_value[0] == '-' ? new BigFloat(dec_value.Remove(0, 1), ExponentSize, MantissaSize) : this; return new BigFloat(Exponent, Math.Abs(Mantissa), ExponentSize, MantissaSize); } } [Pure] public BigFloat Negate { - //TODO: Modify for correct fp functionality get { + if (IsDec) + return dec_value[0] == '-' ? new BigFloat(dec_value.Remove(0, 1), ExponentSize, MantissaSize) : new BigFloat("-" + dec_value, ExponentSize, MantissaSize); return new BigFloat(Exponent, -Mantissa, ExponentSize, MantissaSize); } } diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs index cba74bc5..2345cc1e 100644 --- a/Source/BoogieDriver/BoogieDriver.cs +++ b/Source/BoogieDriver/BoogieDriver.cs @@ -90,7 +90,7 @@ namespace Microsoft.Boogie { } } ExecutionEngine.ProcessFiles(fileList); - return 0; + return 0; END: if (CommandLineOptions.Clo.XmlSink != null) { diff --git a/float_test.bpl b/float_test.bpl index ebd0ab47..fbf8e4e3 100644 --- a/float_test.bpl +++ b/float_test.bpl @@ -1,5 +1,13 @@ -procedure F(n: float) returns(r: float) - ensures r == n; -{ - r := n; +//Translation from addsub_double_exact.c +//Should Verify +procedure main() returns () { + var x : float(11 53); + var y : float(11 53); + var z : float(11 53); + var r : float(11 53); + x := fp(10000000 11 53); + y := x + fp(1 11 53); + z := x - fp(1 11 53); + r := y - z; + assert r == fp(2 11 53); } \ No newline at end of file diff --git a/float_test10.bpl b/float_test10.bpl index 7423a3a0..566f7a56 100644 --- a/float_test10.bpl +++ b/float_test10.bpl @@ -1,5 +1,20 @@ - procedure F() returns () { +//Translation from loop.c +//Should return an error? (The real case does as well...) + +procedure main() returns () { var x : float; - x := fp (0.5 23 8); - assert x == fp (0 -1); + var y : float; + var z : float; + + x := fp(1); + y := fp(10000000); + z := fp(42); + + while (x < y) { + x := x + fp(1); + y := y - fp(1); + z := z + fp(1); + } + + assert(z >= fp(0) && z <= fp(10000000)); } \ No newline at end of file diff --git a/float_test11.bpl b/float_test11.bpl new file mode 100644 index 00000000..cf9fd3a2 --- /dev/null +++ b/float_test11.bpl @@ -0,0 +1,38 @@ +//Translation from interpolation.c +//Should Verify +//Returns inconclusize? What does that mean? + +procedure main() returns () { + var i : int; + var z : float; + var t : float; + var min : [int] float; + var max : [int] float; + + min[0] := fp(5); + min[1] := fp(10); + min[2] := fp(12); + min[3] := fp(30); + min[4] := fp(150); + + max[0] := fp(10); + max[1] := fp(12); + max[2] := fp(30); + max[3] := fp(150); + max[4] := fp(300); + + havoc t; + assume(t >= min[0] && t <= max[4]); + + i := 0; + while (i < 5) { + if (t <= max[i]) { + break; + } + i := i + 1; + } + + z := (t - min[i]) / (max[i] - min[i]); + + assert(z >= fp(0) && z <= fp(1)); +} \ No newline at end of file diff --git a/float_test12.bpl b/float_test12.bpl new file mode 100644 index 00000000..c733b9f4 --- /dev/null +++ b/float_test12.bpl @@ -0,0 +1,43 @@ +//Translation from inv_Newton.c +//Should Verify +//Unfinished code! + +procedure inv(float(11 53)) returns(float(11 53)) { + var z : float(11 53); + var t : float(11 53); + var t : float(11 53); + + +} + +procedure main() returns () { + var t : float(11 53); + var t : float(11 53); + + min[0] := fp(5); + min[1] := fp(10); + min[2] := fp(12); + min[3] := fp(30); + min[4] := fp(150); + + max[0] := fp(10); + max[1] := fp(12); + max[2] := fp(30); + max[3] := fp(150); + max[4] := fp(300); + + havoc t; + assume(t >= min[0] && t <= max[4]); + + i := 0; + while (i < 5) { + if (t <= max[i]) { + break; + } + i := i + 1; + } + + z := (t - min[i]) / (max[i] - min[i]); + + assert(z >= fp(0) && z <= fp(1)); +} \ No newline at end of file diff --git a/float_test13.bpl b/float_test13.bpl new file mode 100644 index 00000000..d073836d --- /dev/null +++ b/float_test13.bpl @@ -0,0 +1,17 @@ +//Translation from inv_square_false-unreach-call.c +//Should return an error (without crashing) + +procedure main() returns () { + var x : float; + var y : float; + var z : float; + + havoc x; + assume(x >= fp(-1) && x <= fp(1)); + + if (x != fp(0)) { + y := x * x; + assert(y != fp(0)); + z := fp(1) / y; + } +} \ No newline at end of file diff --git a/float_test14.bpl b/float_test14.bpl new file mode 100644 index 00000000..9b5dab0a --- /dev/null +++ b/float_test14.bpl @@ -0,0 +1,17 @@ +//Translation from inv_square_false-unreach-call.c +//Should Verify + +procedure main() returns () { + var x : float; + var y : float; + var z : float; + + havoc x; + assume(x >= fp(-1) && x <= fp(1)); + + if (x <= fp(-.00000000000000000001) || x >= fp(.00000000000000000001)) { + y := x * x; + assert(y != fp(0)); + z := fp(1) / y; + } +} \ No newline at end of file diff --git a/float_test15.bpl b/float_test15.bpl new file mode 100644 index 00000000..1dc549ac --- /dev/null +++ b/float_test15.bpl @@ -0,0 +1,24 @@ +//Translation from Muller_Kahan.c +//Should Verify +//NOTE: (fp(....)) causes a compiler error! +//FAILS! Heavily... + +procedure main() returns () { + var x0 : float(11 53); + var x1 : float(11 53); + var x2 : float(11 53); + var i : int; + + x0 := fp(11 11 53) / fp(2 11 53); + x1 := fp(61 11 53) / fp(11 11 53); + i := 0; + while (i < 100) { + x2 := fp(1130 11 53) - fp(3000 11 53) / x0; + x2 := fp(111 11 53) - x2 / x1; + x0 := x1; + x1 := x2; + i := i + 1; + } + + assert(x0 >= fp(99 11 53) && x0 <= fp(101 11 53)); +} \ No newline at end of file diff --git a/float_test16.bpl b/float_test16.bpl new file mode 100644 index 00000000..69ae243d --- /dev/null +++ b/float_test16.bpl @@ -0,0 +1,8 @@ +//Translation from nan_double_false-unreach-call.c +//Should return an error + +procedure main() returns () { + var x : float(11 53); + havoc x; + assert(x==x); +} \ No newline at end of file diff --git a/float_test17.bpl b/float_test17.bpl new file mode 100644 index 00000000..caa1fa74 --- /dev/null +++ b/float_test17.bpl @@ -0,0 +1,11 @@ +//Translation from nan_double_range_true-unreach-call.c +//Should verify +//Uggghhhh, should I add support for e? + +procedure main() returns () { + var x : float(11 53); + havoc x; + if (x >= fp(-100000000000000000000000000 11 53) && x <= fp(100000000000000000000000000 11 53)) { + assert(x==x); + } +} \ No newline at end of file diff --git a/float_test18.bpl b/float_test18.bpl new file mode 100644 index 00000000..71eb5286 --- /dev/null +++ b/float_test18.bpl @@ -0,0 +1,36 @@ +//Translation from rlim_exit.c +//Should verify +//Unary - unsupported float operations (on my end)... + +procedure main() returns () { + var X : float; + var Y : float; + var S : float; + var R : float; + var D : float; + var i : int; + + Y := fp(0); + + i := 0; + while (i < 100000) { + havoc X; + havoc D; + assume(X >= fp(-128) && X <= fp(128)); + assume(D >= fp(0) && D <= fp(16)); + + S := Y; + Y := X; + R := X - S; + if (R <= fp(0)-D) { + Y := S - D; + } + else if(R >= D) { + Y := S + D; + } + + i := i + 1; + } + + assert(Y >= fp(-129) && Y <= fp(129)); +} \ No newline at end of file diff --git a/float_test19.bpl b/float_test19.bpl new file mode 100644 index 00000000..f00d8a2b --- /dev/null +++ b/float_test19.bpl @@ -0,0 +1,36 @@ +//Translation from flim_invariant.c +//Should verify +//Unary - unsupported float operations (on my end)... + +procedure main() returns () { + var X : float; + var Y : float; + var S : float; + var R : float; + var D : float; + var i : int; + + Y := fp(0); + + i := 0; + while (i < 100000) { + havoc X; + havoc D; + assume(X >= fp(-128) && X <= fp(128)); + assume(D >= fp(0) && D <= fp(16)); + + S := Y; + Y := X; + R := X - S; + if (R <= fp(0)-D) { + Y := S - D; + } + else if(R >= D) { + Y := S + D; + } + + assert(Y >= fp(-129) && Y <= fp(129)); + + i := i + 1; + } +} \ No newline at end of file diff --git a/float_test2.bpl b/float_test2.bpl index 956ac757..da74909b 100644 --- a/float_test2.bpl +++ b/float_test2.bpl @@ -1,5 +1,13 @@ -procedure F() returns () { - var x : float(11 53); - var y : float(11 53); - assert x == y; +//Translation from addsub_float_exact.c +//Should Verify +procedure main() returns () { + var x : float; + var y : float; + var z : float; + var r : float; + x := fp(1000000); + y := x + fp(1); + z := x - fp(1); + r := y - z; + assert r == fp(2); } \ No newline at end of file diff --git a/float_test20.bpl b/float_test20.bpl new file mode 100644 index 00000000..57c605fd --- /dev/null +++ b/float_test20.bpl @@ -0,0 +1,14 @@ +//Should return an error? +//Translation from Rump_double.c + +procedure main() returns () { + var x : float(11 53); + var y : float(11 53); + var r : float(11 53); + + x := fp(77617 11 53); + y := fp(33096 11 53); + r := y*y*y*y*y*y * fp(333.75 11 53) + x*x * (x*x*y*y*fp(11 11 53) - y*y*y*y*y*y - y*y*y*y * fp(121 11 53) - fp(2 11 53)) + y*y*y*y*y*y*y*y * fp(5.5 11 53) + x / (y*fp(2 11 53)); + + assert(r >= fp(0 11 53)); +} \ No newline at end of file diff --git a/float_test3.bpl b/float_test3.bpl index e93e7df7..dd0c1ba4 100644 --- a/float_test3.bpl +++ b/float_test3.bpl @@ -1,3 +1,13 @@ - procedure F() returns () { - assert fp(5) == fp(5 8 23); +//Translation from addsub_float_inexact.c +//Should give an error +procedure main() returns () { + var x : float; + var y : float; + var z : float; + var r : float; + x := fp(10000000); + y := x + fp(1); + z := x - fp(1); + r := y - z; + assert r == fp(0); } \ No newline at end of file diff --git a/float_test4.bpl b/float_test4.bpl index 1252dc71..a7aa8c4b 100644 --- a/float_test4.bpl +++ b/float_test4.bpl @@ -1,5 +1,20 @@ - procedure F() returns () { - var x : float; - x := fp (.5 8 23); - assert x == fp (-1 0); +//Translation from drift_tenth.c +//Should Verify +//FAILS; note that it succeeds when tick == fp(.1) + +procedure main() returns () { + var tick : float; + var time : float; + var i: int; + + tick := fp(1)/fp(10); + time := fp(0); + + i := 0; + while (i < 10) + { + time := time + tick; + i := i + 1; + } + assert(time == fp(1)); } \ No newline at end of file diff --git a/float_test5.bpl b/float_test5.bpl index be72b988..ce5d2bc7 100644 --- a/float_test5.bpl +++ b/float_test5.bpl @@ -1,4 +1,33 @@ -procedure F() returns () { - var x : float; - assert x - x == fp(0); +//Translation from filter1.c +//Should Verify + +procedure main() returns () { + var E0 : float(11 53); + var E1 : float(11 53); + var S : float(11 53); + var i : int; + var rand : int; + + E1 := fp(0 11 53); + S := fp(0 11 53); + + i := 0; + while (i <= 1000000) + { + havoc E0; + assume(E0 >= fp(-1 11 53) && E0 <= fp(1 11 53)); + + havoc rand; + if (rand != 0) { + S := fp(0 11 53); + } + else { + S := fp(0.999 11 53) * S + E0 - E1; + } + E1 := E0; + + //assert(1==0); + assert(S >= fp(-1 11 53) && S <= fp(1 11 53)); + i := i + 1; + } } \ No newline at end of file diff --git a/float_test6.bpl b/float_test6.bpl index 423bc45a..6bef1137 100644 --- a/float_test6.bpl +++ b/float_test6.bpl @@ -1,5 +1,40 @@ -procedure F() returns () { - var x : float; - var y : float; - assert (x + x) + (y + y) == fp(0); +//Translation from filter2.c +//Should give an error +//FAILS; doesn't generate terms! + +procedure main() returns () { + var E : float(11 53); + var E0 : float(11 53); + var E1 : float(11 53); + var S : float(11 53); + var S0 : float(11 53); + var S1 : float(11 53); + var i: int; + + havoc E; + havoc E0; + assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); + assume(E0 >= fp(0.0 11 53) && E0 <= fp(1.0 11 53)); + + E1 := fp(0.0 11 53); + S1 := fp(0.0 11 53); + S0 := fp(0.0 11 53); + S := fp(0.0 11 53); + + i := 0; +// while (i <= 1000000) +// { + E1 := E0; + E0 := E; + + havoc E; + assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); + + S1 := S0; + S0 := S; + S := E*fp(0.7 11 53) - E0*fp(1.3 11 53) + E1*fp(1.1 11 53) + S0*fp(1.4 11 53) - S1*fp(0.7 11 53); + + assert(S >= fp(-4.0 11 53) && S <= fp(4.0 11 53)); + //i := i + 1; +// } } \ No newline at end of file diff --git a/float_test7.bpl b/float_test7.bpl index cc7a040b..8e07878d 100644 --- a/float_test7.bpl +++ b/float_test7.bpl @@ -1,5 +1,38 @@ -procedure F() returns () { - var x : float; - x := fp(.1) + fp(.1) + fp(.1); - assert x == fp(.3); +//Translation from filter2.c +//Should give an error +//Same as the previous one; it works with reals! + +procedure main() returns () { + var E : real; + var E0 : real; + var E1 : real; + var S : real; + var S0 : real; + var S1 : real; + var i: int; + + havoc E; + havoc E0; + assume(E >= 0.0 && E <= 1.0); + assume(E0 >= 0.0 && E0 <= 1.0); + + S0 := 0.0; + S := 0.0; + + i := 0; + while (i <= 1000000) + { + E1 := E0; + E0 := E; + + havoc E; + assume(E >= 0.0 && E <= 1.0); + + S1 := S0; + S0 := S; + S := E*0.7 - E0*1.3 + E1*1.1 + S0*1.4 - S1*0.7; + + assert(S >= -4.0 && S <= 4.0); + i := i + 1; + } } \ No newline at end of file diff --git a/float_test8.bpl b/float_test8.bpl index 554dcf00..995ed4fa 100644 --- a/float_test8.bpl +++ b/float_test8.bpl @@ -1,3 +1,12 @@ -procedure F() returns () { - assert fp(-oo)==fp(-oo); +//Translation from float_double.c +//Should Verify +//FAILS: I don't have this functionality yet... + +procedure main() returns () { + var x : float(11 53); + var y : float; + + x := fp(100000000000000000001 11 53); + y := x; + assert(x != y); } \ No newline at end of file diff --git a/float_test9.bpl b/float_test9.bpl index 7423a3a0..c3a42e6b 100644 --- a/float_test9.bpl +++ b/float_test9.bpl @@ -1,5 +1,34 @@ - procedure F() returns () { - var x : float; - x := fp (0.5 23 8); - assert x == fp (0 -1); +//Translation from feedback_diverge.c +//Should give an error +//Not sure on this one... + +procedure main() returns () { + var A : float; + var B : float; + var X : float; + var i : int; + var rand : int; + + A := fp(0); + B := fp(0); + + i := 0; + while (i < 3600000) { + + havoc rand; + if (rand != 0) { + havoc X; + assume(X >= fp(-20) && X <= fp(20)); + } + else { + X := B; + } + + B := B - (B * fp(2.0) - A - X) * fp(.005); + A := X; + + i := i + 1; + } + + assert(A >= fp(-100) && A <= fp(100)); } \ No newline at end of file diff --git a/fp_documentation.txt b/fp_documentation.txt new file mode 100644 index 00000000..09e60b9a --- /dev/null +++ b/fp_documentation.txt @@ -0,0 +1,79 @@ +Floating Point Documentation for Boogie +Written by Dietrich Geisler +Contact: dgeisler50@gmail.com + +This document aims to describe the syntax for declaring and using floating points in Boogie + +-------------------------------------------------------------------------------- +Declaring Variables: + +The syntax for declaring a floating point variable is as follows: +var name: float(exp man); +Where exp is the size of the float exponent and man is the size of the float mantissa + +It is also acceptable to use the following syntax: +var name: float(); +This syntax assumes the float exponent to be size 8 and the mantissa to be size 24 + +example: +var x: float(11 53) +Declares a variable called x with a exponent sized 11 and mantissa sized 53 + +-------------------------------------------------------------------------------- +Declaring Constants: + +All of the following syntax are viable for declaring a floating point constant: +float(dec) +float(exp_val man_val) +float(dec exp man) +float(exp_val man_val exp man) + +Where dec is the decimal value of the constant, +exp_val/man_value are the integer values of their respective fields, +And exp/man are the sizes of their respective fields. +Note that when exp and man are not specified, they are given sizes 8 and 24 respectively + +-------------------------------------------------------------------------------- +Defined Operations: + +Given two floating point values x and y with the same size of exponent and mantissa +The following operations operate as defined in Operators section of this document: +http://smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml +(Note that rounding mode is always assumed to be Round to Nearest Even (RNE)) +(Also note that operations not listed here are undefined) + +operatation boogie syntax +neg(x) -x +add(x, y) x + y +sub(x, y) x - y +mul(x, y) x * y +div(x, y) x / y +leq(x, y) x <= y +lt(x, y) x < y +geq(x, y) x >= y +gt(x, y) x > y +eq(x, y) x == y + +-------------------------------------------------------------------------------- +Other: + +The following special values can be declared with the following syntax: +Value Declaration +NaN fp(nan exp man) ++oo fp(oo exp man) OR fp(INF exp man) +-oo fp(-oo exp man) OR fp(INF exp man) +-zero fp(-zero exp man) +Where exp and man are the sizes of the exponent and mantissa respectively + +-------------------------------------------------------------------------------- +Known Issues: + +There is currently no way to convert from a floating point to any other data type + +There is currently no way to convert the value of a variable to a floating point type +For example, the following statements fails: +var x : real; +fp(x); + +Statements of the following form cause a parser error (parenthesis followed by fp constant) +... (fp(1) + fp(1)); \ No newline at end of file -- cgit v1.2.3 From 6ac996211d6f42f0c7f61ea108388d6bb798ecf8 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Sat, 20 Feb 2016 20:53:08 -0700 Subject: Modified BigFloat and parser to accept correct SMT-LIB syntax --- Source/Basetypes/BigFloat.cs | 250 ++++++++++++++---------------- Source/Core/Parser.cs | 90 +++++++---- Source/Provers/SMTLib/SMTLibLineariser.cs | 4 +- fp_documentation.txt | 19 ++- 4 files changed, 192 insertions(+), 171 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 5b169263..8cde2cb9 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -17,7 +17,7 @@ namespace Microsoft.Basetypes /// /// A representation of a 32-bit floating point value - /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit mantissa + /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit significand /// public struct BigFloat { @@ -25,33 +25,33 @@ namespace Microsoft.Basetypes // the internal representation [Rep] - internal readonly long mantissa; //Note that the mantissa arrangement matches standard fp arrangement (most significant bit is farthest left) + internal readonly BigNum significand; //Note that the significand arrangement matches standard fp arrangement (most significant bit is farthest left) [Rep] - internal readonly int mantissaSize; + internal readonly int significandSize; [Rep] - internal readonly int exponent; //The value of the exponent is always positive as per fp representation requirements + internal readonly BigNum exponent; //The value of the exponent is always positive as per fp representation requirements [Rep] internal readonly int exponentSize; //The bit size of the exponent [Rep] - internal readonly String dec_value; + internal readonly String value; //Only used with second syntax [Rep] - internal readonly bool isDec; + internal readonly bool isNeg; - public long Mantissa { + public BigNum Significand { get { - return mantissa; + return significand; } } - public int Exponent { + public BigNum Exponent { get { return exponent; } } - public int MantissaSize { + public int SignificandSize { get { - return mantissaSize; + return significandSize; } } @@ -61,25 +61,26 @@ namespace Microsoft.Basetypes } } - public String Decimal { + public bool IsNegative { get { - return dec_value; + return this.isNeg; } } - public bool IsDec { + public String Value { get { - return isDec; + return value; } } - public static BigFloat ZERO(int mantissaSize, int exponentSize) { return new BigFloat(0, 0, mantissaSize, exponentSize); } //Does not include negative zero + public static BigFloat ZERO(int exponentSize, int significandSize) { return new BigFloat(false, BigNum.ZERO, BigNum.ZERO, exponentSize, significandSize); } //Does not include negative zero - private static readonly BIM two = new BIM(2); - private static long two_n(int n) { - long toReturn = 1; + private static readonly BigNum two = new BigNum(2); + private static readonly BigNum one = new BigNum(1); + private static BigNum two_n(int n) { + BigNum toReturn = one; for (int i = 0; i < n; i++) - toReturn = toReturn * 2; + toReturn = toReturn * two; return toReturn; } @@ -95,18 +96,18 @@ namespace Microsoft.Basetypes return new BigFloat(v.ToString(), 8, 24); } - public static BigFloat FromInt(int v, int exponentSize, int mantissaSize) + public static BigFloat FromInt(int v, int exponentSize, int significandSize) { - return new BigFloat(v.ToString(), exponentSize, mantissaSize); + return new BigFloat(v.ToString(), exponentSize, significandSize); } public static BigFloat FromBigInt(BIM v) { return new BigFloat(v.ToString(), 8, 24); } - public static BigFloat FromBigInt(BIM v, int exponentSize, int mantissaSize) + public static BigFloat FromBigInt(BIM v, int exponentSize, int significandSize) { - return new BigFloat(v.ToString(), exponentSize, mantissaSize); + return new BigFloat(v.ToString(), exponentSize, significandSize); } public static BigFloat FromBigDec(BigDec v) @@ -114,84 +115,67 @@ namespace Microsoft.Basetypes return new BigFloat(v.ToDecimalString(), 8, 24); } - public static BigFloat FromBigDec(BigDec v, int exponentSize, int mantissaSize) + public static BigFloat FromBigDec(BigDec v, int exponentSize, int significandSize) { - return new BigFloat(v.ToDecimalString(), exponentSize, mantissaSize); + return new BigFloat(v.ToDecimalString(), exponentSize, significandSize); } [Pure] - public static BigFloat FromString(string v) { - String[] vals = v.Split(' '); - if (vals.Length == 0 || vals.Length > 4) - throw new FormatException(); - try - { - switch (vals.Length) { - case 1: - return new BigFloat(vals[0], 8, 24); - case 2: - return new BigFloat(Int32.Parse(vals[0]), Int64.Parse(vals[1]), 8, 24); - case 3: - return new BigFloat(vals[0], Int32.Parse(vals[1]), Int32.Parse(vals[2])); - case 4: - return new BigFloat(Int32.Parse(vals[0]), Int64.Parse(vals[1]), Int32.Parse(vals[2]), Int32.Parse(vals[3])); - default: - throw new FormatException(); //Unreachable - } - } - catch (Exception) { //Catch parsing errors - throw new FormatException(); - } + public static BigFloat FromString(String v, int exp, int sig) { //String must be + return new BigFloat(v, exp, sig); } - internal BigFloat(int exponent, long mantissa, int exponentSize, int mantissaSize) { + public BigFloat(bool sign, BigNum exponent, BigNum significand, int exponentSize, int significandSize) { this.exponentSize = exponentSize; this.exponent = exponent; - this.mantissa = mantissa; - this.mantissaSize = mantissaSize; - this.isDec = false; - this.dec_value = ""; + this.significand = significand; + this.significandSize = significandSize; + this.isNeg = sign; + this.value = ""; } - internal BigFloat(String dec_value, int exponentSize, int mantissaSize) { + public BigFloat(String value, int exponentSize, int significandSize) { this.exponentSize = exponentSize; - this.mantissaSize = mantissaSize; - this.exponent = 0; - this.mantissa = 0; - this.isDec = true; - this.dec_value = dec_value; + this.significandSize = significandSize; + this.exponent = BigNum.ZERO; + this.significand = BigNum.ZERO; + this.value = value; + this.isNeg = value[0] == '-'; //Special cases: - if (this.dec_value.Equals("+oo") || this.dec_value.Equals("-oo") || this.dec_value.Equals("-zero")) + if (this.value.Equals("+oo") || this.value.Equals("-oo") || this.value.Equals("-zero")) return; - if (this.dec_value.ToLower().Equals("nan")) { - this.dec_value = "NaN"; + if (this.value.ToLower().Equals("nan")) { + this.value = "NaN"; return; } - if (this.dec_value.Equals("INF") || this.dec_value.Equals("+INF")) { - this.dec_value = "+oo"; + if (this.value.Equals("INF") || this.value.Equals("+INF")) + { + this.value = "+oo"; return; } - if (this.dec_value.Equals("-INF")) { - this.dec_value = "-oo"; + if (this.value.Equals("-INF")) + { + this.value = "-oo"; return; } - if (this.dec_value.Equals("+zero")) { - this.dec_value = "0.0"; + if (this.value.Equals("+zero")) + { + this.value = "0.0"; return; } //End special cases - if (this.dec_value.IndexOf('.') == -1 && this.dec_value.IndexOf('e') == -1) - this.dec_value += ".0"; //Assures that the decimal value is a "real" number - if (this.dec_value.IndexOf('.') == 0) - this.dec_value = "0" + this.dec_value; //Assures that decimals always have a 0 in front + if (this.value.IndexOf('.') == -1 && this.value.IndexOf('e') == -1) + this.value += ".0"; //Assures that the decimal value is a "real" number + if (this.value.IndexOf('.') == 0) + this.value = "0" + this.value; //Assures that decimals always have a 0 in front } - private BIM maxMantissa() + private BigNum maxsignificand() { - BIM result = new BIM(1); - for (int i = 0; i < mantissaSize; i++) + BigNum result = one; + for (int i = 0; i < significandSize; i++) result = result * two; - return result - 1; + return result - one; } private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } @@ -213,13 +197,13 @@ namespace Microsoft.Basetypes [Pure] public override int GetHashCode() { - return Mantissa.GetHashCode() * 13 + Exponent.GetHashCode(); + return significand.GetHashCode() * 13 + Exponent.GetHashCode(); } [Pure] public override string/*!*/ ToString() { Contract.Ensures(Contract.Result() != null); - return isDec ? dec_value : String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); + return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; } @@ -229,41 +213,41 @@ namespace Microsoft.Basetypes /// /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!! /// Converts the given decimal value (provided as a string) to the nearest floating point approximation - /// the returned fp assumes the given mantissa and exponent size + /// the returned fp assumes the given significand and exponent size /// /// - /// + /// /// /// - public static BigFloat Round(String value, int exponentSize, int mantissaSize) + public static BigFloat Round(String value, int exponentSize, int significandSize) { int i = value.IndexOf('.'); if (i == -1) - return Round(BIM.Parse(value), 0, exponentSize, mantissaSize); - return Round(i == 0 ? 0 : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), exponentSize, mantissaSize); + return Round(BigNum.FromString(value), BigNum.ZERO, exponentSize, significandSize); + return Round(i == 0 ? BigNum.ZERO : BigNum.FromString(value.Substring(0, i)), BigNum.FromString(value.Substring(i + 1, value.Length - i - 1)), exponentSize, significandSize); } /// /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!!! - /// Converts value.dec_value to a the closest float approximation with the given mantissaSize, exponentSize + /// Converts value.dec_value to a the closest float approximation with the given significandSize, exponentSize /// Returns the result of this calculation /// /// /// - /// + /// /// /// - public static BigFloat Round(BIM value, BIM dec_value, int exponentSize, int mantissaSize) + public static BigFloat Round(BigNum value, BigNum dec_value, int exponentSize, int significandSize) { int exp = 0; - BIM one = new BIM(1); - BIM ten = new BIM(10); - BIM dec_max = new BIM(0); //represents the order of magnitude of dec_value for carrying during calculations + BigNum one = new BigNum(1); + BigNum ten = new BigNum(10); + BigNum dec_max = new BigNum(0); //represents the order of magnitude of dec_value for carrying during calculations //First, determine the exponent while (value > one) { //Divide by two, increment exponent by 1 if (!(value % two).IsZero) { //Add "1.0" to the decimal - dec_max = new BIM(10); + dec_max = new BigNum(10); while (dec_max < dec_value) dec_max = dec_max * ten; dec_value = dec_value + dec_max; @@ -275,7 +259,7 @@ namespace Microsoft.Basetypes exp++; } if (value.IsZero && !dec_value.IsZero) { - dec_max = new BIM(10); + dec_max = new BigNum(10); while (dec_max < dec_value) dec_max = dec_max * ten; while (value.IsZero) {//Multiply by two, decrement exponent by 1 @@ -288,12 +272,12 @@ namespace Microsoft.Basetypes } } - //Second, calculate the mantissa - value = new BIM(0); //remove implicit bit - dec_max = new BIM(10); + //Second, calculate the significand + value = new BigNum(0); //remove implicit bit + dec_max = new BigNum(10); while (dec_max < dec_value) dec_max = dec_max * ten; - for (int i = mantissaSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the mantissa is fully calculated + for (int i = significandSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the significand is fully calculated dec_value = dec_value * two; if (dec_value >= dec_max) { dec_value = dec_value - dec_max; @@ -301,7 +285,7 @@ namespace Microsoft.Basetypes } } - return new BigFloat(exp, Int64.Parse(value.ToString()), exponentSize, mantissaSize); + return new BigFloat(false, BigNum.ZERO, BigNum.FromString(value.ToString()), exponentSize, significandSize); //Sign not actually checked... } // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). @@ -312,30 +296,32 @@ namespace Microsoft.Basetypes /// /// The Floor (rounded towards negative infinity) /// Ceiling (rounded towards positive infinity) - public void FloorCeiling(out BIM floor, out BIM ceiling) { + public void FloorCeiling(out BigNum floor, out BigNum ceiling) { //TODO: fix for fp functionality - BIM n = Mantissa; - int e = Exponent; + BigNum n = Significand; + BigNum e = Exponent; if (n.IsZero) { floor = ceiling = n; - } else if (0 <= e) { + } else if (BigNum.ZERO <= e) { // it's an integer - for (; 0 < e; e--) { + for (; BigNum.ZERO < e; e = e - one) + { n = n * two; } floor = ceiling = n; } else { // it's a non-zero integer, so the ceiling is one more than the floor - for (; e < 0 && !n.IsZero; e++) { + for (; BigNum.ZERO < e && !n.IsZero; e = e + one) + { n = n / two; // Division rounds towards negative infinity } if (!IsNegative) { floor = n; - ceiling = n + 1; + ceiling = n + one; } else { ceiling = n; - floor = n - 1; + floor = n - one; } } Debug.Assert(floor <= ceiling, "Invariant was not maintained"); @@ -352,7 +338,7 @@ namespace Microsoft.Basetypes [Pure] public string ToDecimalString() { Contract.Ensures(Contract.Result() != null); - return isDec ? dec_value : String.Format("{0}x2^{1}", Mantissa.ToString(), Exponent.ToString()); + return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; } [Pure] @@ -380,18 +366,16 @@ namespace Microsoft.Basetypes [Pure] public BigFloat Abs { get { - if (IsDec) - return dec_value[0] == '-' ? new BigFloat(dec_value.Remove(0, 1), ExponentSize, MantissaSize) : this; - return new BigFloat(Exponent, Math.Abs(Mantissa), ExponentSize, MantissaSize); + return new BigFloat(true, Exponent, Significand, ExponentSize, SignificandSize); } } [Pure] public BigFloat Negate { get { - if (IsDec) - return dec_value[0] == '-' ? new BigFloat(dec_value.Remove(0, 1), ExponentSize, MantissaSize) : new BigFloat("-" + dec_value, ExponentSize, MantissaSize); - return new BigFloat(Exponent, -Mantissa, ExponentSize, MantissaSize); + if (value != "") + return value[0] == '-' ? new BigFloat(value.Remove(0, 1), ExponentSize, significandSize) : new BigFloat("-" + value, ExponentSize, significandSize); + return new BigFloat(!isNeg, Exponent, Significand, ExponentSize, SignificandSize); } } @@ -404,26 +388,26 @@ namespace Microsoft.Basetypes public static BigFloat operator +(BigFloat x, BigFloat y) { //TODO: Modify for correct fp functionality Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.MantissaSize == y.MantissaSize); - long m1 = x.Mantissa; - int e1 = x.Exponent; - long m2 = y.Mantissa; - int e2 = y.Exponent; - m1 = m1 + two_n(x.mantissaSize + 1); //Add implicit bit - m2 = m2 + two_n(y.mantissaSize + 1); + Contract.Requires(x.significandSize == y.significandSize); + BigNum m1 = x.significand; + BigNum e1 = x.Exponent; + BigNum m2 = y.significand; + BigNum e2 = y.Exponent; + m1 = m1 + two_n(x.significandSize + 1); //Add implicit bit + m2 = m2 + two_n(y.significandSize + 1); if (e2 > e1) { - m1 = y.Mantissa; + m1 = y.significand; e1 = y.Exponent; - m2 = x.Mantissa; + m2 = x.significand; e2 = x.Exponent; } while (e2 < e1) { - m2 = m2 / 2; - e2++; + m2 = m2 / two; + e2 = e2 + one; } - return new BigFloat(e1, m1 + m2, x.MantissaSize, x.ExponentSize); + return new BigFloat(false, e1, m1 + m2, x.significandSize, x.ExponentSize); } [Pure] @@ -434,8 +418,8 @@ namespace Microsoft.Basetypes [Pure] public static BigFloat operator *(BigFloat x, BigFloat y) { Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.MantissaSize == y.MantissaSize); - return new BigFloat(x.Exponent + y.Exponent, x.Mantissa * y.Mantissa, x.MantissaSize, x.ExponentSize); + Contract.Requires(x.significandSize == y.significandSize); + return new BigFloat(x.isNeg ^ y.isNeg, x.Exponent + y.Exponent, x.significand * y.significand, x.significandSize, x.ExponentSize); } @@ -444,9 +428,9 @@ namespace Microsoft.Basetypes public bool IsSpecialType { get { - if (!IsDec) + if (value == "") return false; - return (dec_value.Equals("NaN") || dec_value.Equals("+oo") || dec_value.Equals("-oo") || dec_value.Equals("-zero")); + return (value.Equals("NaN") || value.Equals("+oo") || value.Equals("-oo") || value.Equals("-zero")); } } @@ -456,15 +440,9 @@ namespace Microsoft.Basetypes } } - public bool IsNegative { - get { - return (isDec && dec_value[0] == '-') || mantissa < 0; - } - } - public bool IsZero { get { - return Mantissa == 0 && Exponent == 0; + return significand.Equals(BigNum.ZERO) && Exponent == BigNum.ZERO; } } @@ -474,9 +452,9 @@ namespace Microsoft.Basetypes return 1; if (this.exponent < that.exponent) return -1; - if (this.Mantissa == that.Mantissa) + if (this.significand == that.significand) return 0; - return this.Mantissa > that.Mantissa ? 1 : -1; + return this.significand > that.significand ? 1 : -1; } [Pure] diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 5fcb1cdc..bf35ccbe 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -668,17 +668,35 @@ private class BvBounds : Expr { ty = new BasicType(t, SimpleType.Real); } else if (la.kind == 98) { Get(); - if (la.kind == 9) { - Get(); - Expect(3); - int exp = Int32.Parse(t.val); - Expect(3); - int man = Int32.Parse(t.val); - ty = new FloatType(t, exp, man); - Expect(10); + if (la.kind == 3) { + Expect(3); + switch (Int32.Parse(t.val)) { + case 16: + ty = new FloatType(t, 5, 11); + break; + case 32: + ty = new FloatType(t, 8, 24); + break; + case 64: + ty = new FloatType(t, 11, 53); + break; + case 128: + ty = new FloatType(t, 15, 113); + break; + default: + SynErr(3); + break; + } + } + else { + Expect(19); + Expect(3); + int exp = Int32.Parse(t.val); + Expect(3); + int man = Int32.Parse(t.val); + ty = new FloatType(t, exp, man); + Expect(20); } - else - ty = new FloatType(t, 8, 24); } else if (la.kind == 16) { Get(); ty = new BasicType(t, SimpleType.Bool); @@ -1813,9 +1831,9 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { case 98: { Get(); x = t; - Expect(9); + Expect(19); Expression(out e); - Expect(10); + Expect(20); e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToFloat), new List { e }); break; } @@ -1887,29 +1905,45 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { /// void Float(out BigFloat n) { - //To be modified - string s = ""; try { - if (la.kind == 97) - { - //Expected format = fp (a b) || fp (a b c d) + if (la.kind == 97) { + bool negative = false; + int exp, sig; + BigNum exp_val, sig_val, value; + //Expected format = fp(sign exp_val sig_val) || fp(value) Get(); //Skip the fp token Get(); - if (t.val != "(") { throw new FormatException(); } - while (la.kind == 1 || la.kind == 3 || la.kind == 6 || la.kind == 4 || la.kind == 74 || la.kind == 75) { //Get values between the parens + if (t.val == "(") { Get(); - if (t.val == "-" || t.val == "+") //special sign case (la.kind == 74 or 75) - s += t.val; - else - s += t.val + " "; + negative = Boolean.Parse(t.val); + BvLit(out exp_val, out exp); + BvLit(out sig_val, out sig); + n = new BigFloat(negative, exp_val, sig_val, exp, sig); + } + else if (t.val == "<") { + Expect(14); + exp = Int32.Parse(t.val); + Expect(14); + sig = Int32.Parse(t.val); + int size; + BvLit(out value, out size); + if (size != exp + sig) + { + this.SemErr("The given bitvector size of " + size + "does not match the provided floating-point size of " + (exp + sig)); + n = BigFloat.ZERO(8, 24); + return; + } + n = new BigFloat(t.val, exp, sig); + } + else { + throw new FormatException(); } - Get(); - if (t.val != ")") { throw new FormatException(); } } - else SynErr(137); - - n = BigFloat.FromString(s.Trim()); + else { + n = BigFloat.ZERO(8, 24); + SynErr(137); + } } catch (FormatException) { diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index 7c3ae960..59b6b7e7 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -205,10 +205,10 @@ namespace Microsoft.Boogie.SMTLib { BigFloat lit = ((VCExprFloatLit)node).Val; if (lit.IsSpecialType) { - wr.Write("(_ " + lit.Decimal + " " + lit.ExponentSize.ToString() + " " + lit.MantissaSize.ToString() + ")"); + wr.Write("(_ " + lit.Decimal + " " + lit.ExponentSize.ToString() + " " + lit.SignificandSize.ToString() + ")"); return true; } - wr.Write("((_ to_fp " + lit.ExponentSize.ToString() + " " + lit.MantissaSize.ToString() + ") RNE "); + wr.Write("((_ to_fp " + lit.ExponentSize.ToString() + " " + lit.SignificandSize.ToString() + ") RNE "); if (lit.IsNegative) // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString()); diff --git a/fp_documentation.txt b/fp_documentation.txt index 09e60b9a..d3fafdcb 100644 --- a/fp_documentation.txt +++ b/fp_documentation.txt @@ -10,7 +10,9 @@ Declaring Variables: The syntax for declaring a floating point variable is as follows: var name: float(exp man); Where exp is the size of the float exponent and man is the size of the float mantissa +Please note that +**REMOVE THIS SYNTAX** It is also acceptable to use the following syntax: var name: float(); This syntax assumes the float exponent to be size 8 and the mantissa to be size 24 @@ -23,10 +25,11 @@ Declares a variable called x with a exponent sized 11 and mantissa sized 53 Declaring Constants: All of the following syntax are viable for declaring a floating point constant: -float(dec) -float(exp_val man_val) -float(dec exp man) -float(exp_val man_val exp man) +**REMOVE THE FIRST OF THESE TWO SYNTAXES** +fp(dec) +fp(exp_val man_val) +fp(dec exp man) +fp(exp_val man_val exp man) Where dec is the decimal value of the constant, exp_val/man_value are the integer values of their respective fields, @@ -68,6 +71,8 @@ Where exp and man are the sizes of the exponent and mantissa respectively -------------------------------------------------------------------------------- Known Issues: +float16, float32, float64, and float128 still need to be added + There is currently no way to convert from a floating point to any other data type There is currently no way to convert the value of a variable to a floating point type @@ -76,4 +81,8 @@ var x : real; fp(x); Statements of the following form cause a parser error (parenthesis followed by fp constant) -... (fp(1) + fp(1)); \ No newline at end of file +... (fp(1) + fp(1)); + +Attempts by Boogie to infer the behavior of loops fail when floating points are involved + +Describing loop behavior manually is untested (using loop unroll appears to work) \ No newline at end of file -- cgit v1.2.3 From 51b7e8146f413b83a412572fcc9e3a1a8b302b79 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Thu, 17 Mar 2016 13:01:10 -0600 Subject: modified floating point syntax and modified floating point constants to use bitvector values --- Source/AbsInt/IntervalDomain.cs | 6 ++-- Source/Basetypes/BigFloat.cs | 43 ++++++++++------------------- Source/BoogieDriver/BoogieDriver.cs | 2 +- Source/Core/AbsyExpr.cs | 4 +-- Source/Core/Parser.cs | 46 ++++++++++++++++++------------- Source/Provers/SMTLib/SMTLibLineariser.cs | 12 +------- Source/VCExpr/VCExprAST.cs | 2 +- float_test.bpl | 16 +++++------ 8 files changed, 57 insertions(+), 74 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs index 0c954f9a..d5a5efc9 100644 --- a/Source/AbsInt/IntervalDomain.cs +++ b/Source/AbsInt/IntervalDomain.cs @@ -695,10 +695,10 @@ namespace Microsoft.Boogie.AbstractInterpretation Lo = floor; Hi = ceiling; } else if (node.Val is BigFloat) { - BigInteger floor, ceiling; + BigNum floor, ceiling; ((BigFloat)node.Val).FloorCeiling(out floor, out ceiling); - Lo = floor; - Hi = ceiling; + Lo = floor.ToBigInteger; + Hi = ceiling.ToBigInteger; } else if (node.Val is bool) { if ((bool)node.Val) { // true diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 8cde2cb9..a0ce03a5 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -129,7 +129,7 @@ namespace Microsoft.Basetypes this.exponentSize = exponentSize; this.exponent = exponent; this.significand = significand; - this.significandSize = significandSize; + this.significandSize = significandSize+1; this.isNeg = sign; this.value = ""; } @@ -141,33 +141,6 @@ namespace Microsoft.Basetypes this.significand = BigNum.ZERO; this.value = value; this.isNeg = value[0] == '-'; - //Special cases: - if (this.value.Equals("+oo") || this.value.Equals("-oo") || this.value.Equals("-zero")) - return; - if (this.value.ToLower().Equals("nan")) { - this.value = "NaN"; - return; - } - if (this.value.Equals("INF") || this.value.Equals("+INF")) - { - this.value = "+oo"; - return; - } - if (this.value.Equals("-INF")) - { - this.value = "-oo"; - return; - } - if (this.value.Equals("+zero")) - { - this.value = "0.0"; - return; - } - //End special cases - if (this.value.IndexOf('.') == -1 && this.value.IndexOf('e') == -1) - this.value += ".0"; //Assures that the decimal value is a "real" number - if (this.value.IndexOf('.') == 0) - this.value = "0" + this.value; //Assures that decimals always have a 0 in front } private BigNum maxsignificand() @@ -335,6 +308,18 @@ namespace Microsoft.Basetypes } } + public String ToBVString(){ + if (this.IsSpecialType) { + return "_ " + this.value + " " + this.exponentSize + " " + this.significandSize; + } + else if (this.Value == "") { + return "fp (_ bv" + (this.isNeg ? "1" : "0") + " 1) (_ bv" + this.exponent + " " + this.exponentSize + ") (_ bv" + this.significand + " " + this.significandSize + ")"; + } + else { + return "(_ to_fp " + this.exponentSize + " " + this.significandSize + ") (_ bv" + this.value + " " + (this.exponentSize + this.significandSize).ToString() + ")"; + } + } + [Pure] public string ToDecimalString() { Contract.Ensures(Contract.Result() != null); @@ -430,7 +415,7 @@ namespace Microsoft.Basetypes get { if (value == "") return false; - return (value.Equals("NaN") || value.Equals("+oo") || value.Equals("-oo") || value.Equals("-zero")); + return (value.Equals("NaN") || value.Equals("+oo") || value.Equals("-oo") || value.Equals("zero") || value.Equals("-zero")); } } diff --git a/Source/BoogieDriver/BoogieDriver.cs b/Source/BoogieDriver/BoogieDriver.cs index 2345cc1e..fa038803 100644 --- a/Source/BoogieDriver/BoogieDriver.cs +++ b/Source/BoogieDriver/BoogieDriver.cs @@ -90,7 +90,7 @@ namespace Microsoft.Boogie { } } ExecutionEngine.ProcessFiles(fileList); - return 0; + return 0; END: if (CommandLineOptions.Clo.XmlSink != null) { diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs index ad537288..6b2e1201 100644 --- a/Source/Core/AbsyExpr.cs +++ b/Source/Core/AbsyExpr.cs @@ -561,7 +561,7 @@ namespace Microsoft.Boogie { { Contract.Requires(tok != null); Val = v; - Type = Type.GetFloatType(v.ExponentSize, v.MantissaSize); + Type = Type.GetFloatType(v.ExponentSize, v.SignificandSize); if (immutable) CachedHashCode = ComputeHashCode(); } @@ -639,7 +639,7 @@ namespace Microsoft.Boogie { return Type.Real; } else if (Val is BigFloat) { BigFloat temp = (BigFloat)Val; - return Type.GetFloatType(temp.ExponentSize, temp.MantissaSize); + return Type.GetFloatType(temp.ExponentSize, temp.SignificandSize); } else if (Val is BvConst) { return Type.GetBvType(((BvConst)Val).Bits); } else { diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index bf35ccbe..77100d1c 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -669,7 +669,7 @@ private class BvBounds : Expr { } else if (la.kind == 98) { Get(); if (la.kind == 3) { - Expect(3); + Get(); switch (Int32.Parse(t.val)) { case 16: ty = new FloatType(t, 5, 11); @@ -689,13 +689,14 @@ private class BvBounds : Expr { } } else { - Expect(19); + Expect(19); //< Expect(3); int exp = Int32.Parse(t.val); + Expect(12); //, Expect(3); int man = Int32.Parse(t.val); ty = new FloatType(t, exp, man); - Expect(20); + Expect(20); //> } } else if (la.kind == 16) { Get(); @@ -1909,32 +1910,39 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { { if (la.kind == 97) { bool negative = false; - int exp, sig; + int exp, sig, size; BigNum exp_val, sig_val, value; - //Expected format = fp(sign exp_val sig_val) || fp(value) - Get(); //Skip the fp token - Get(); - if (t.val == "(") { + //Expected format = float(sign exp_val sig_val) || float(value) + Get(); //Skip the float token + if (la.val == "(") { Get(); + Expect(16); //bool negative = Boolean.Parse(t.val); + Expect(12); //, BvLit(out exp_val, out exp); + Expect(12); BvLit(out sig_val, out sig); n = new BigFloat(negative, exp_val, sig_val, exp, sig); + Expect(10); //) } - else if (t.val == "<") { - Expect(14); + else if (la.val == "<") { + Get(); + Expect(3); exp = Int32.Parse(t.val); - Expect(14); + Expect(12); + Expect(3); sig = Int32.Parse(t.val); - int size; - BvLit(out value, out size); - if (size != exp + sig) - { - this.SemErr("The given bitvector size of " + size + "does not match the provided floating-point size of " + (exp + sig)); - n = BigFloat.ZERO(8, 24); - return; + Expect(20); //> + Expect(9); //( + if (la.kind == 4) { + Get(); + n = new BigFloat(t.val, exp, sig); + } + else { + BvLit(out value, out size); + n = new BigFloat(value.ToString(), exp, sig); } - n = new BigFloat(t.val, exp, sig); + Expect(10); //) } else { throw new FormatException(); diff --git a/Source/Provers/SMTLib/SMTLibLineariser.cs b/Source/Provers/SMTLib/SMTLibLineariser.cs index 59b6b7e7..96d5b290 100644 --- a/Source/Provers/SMTLib/SMTLibLineariser.cs +++ b/Source/Provers/SMTLib/SMTLibLineariser.cs @@ -204,17 +204,7 @@ namespace Microsoft.Boogie.SMTLib else if (node is VCExprFloatLit) { BigFloat lit = ((VCExprFloatLit)node).Val; - if (lit.IsSpecialType) { - wr.Write("(_ " + lit.Decimal + " " + lit.ExponentSize.ToString() + " " + lit.SignificandSize.ToString() + ")"); - return true; - } - wr.Write("((_ to_fp " + lit.ExponentSize.ToString() + " " + lit.SignificandSize.ToString() + ") RNE "); - if (lit.IsNegative) - // In SMT2 "-42" is an identifier (SMT2, Sect. 3.2 "Symbols") - wr.Write("(- 0.0 {0})", lit.Abs.ToDecimalString()); - else - wr.Write(lit.ToDecimalString()); - wr.Write(")"); + wr.Write("(" + lit.ToBVString() + ")"); } else { Contract.Assert(false); diff --git a/Source/VCExpr/VCExprAST.cs b/Source/VCExpr/VCExprAST.cs index 3f6e3b7a..b22853ce 100644 --- a/Source/VCExpr/VCExprAST.cs +++ b/Source/VCExpr/VCExprAST.cs @@ -887,7 +887,7 @@ namespace Microsoft.Boogie.VCExprAST { { public readonly BigFloat Val; internal VCExprFloatLit(BigFloat val) - : base(Type.GetFloatType(val.ExponentSize, val.MantissaSize)) + : base(Type.GetFloatType(val.ExponentSize, val.SignificandSize)) { this.Val = val; } diff --git a/float_test.bpl b/float_test.bpl index fbf8e4e3..e893e098 100644 --- a/float_test.bpl +++ b/float_test.bpl @@ -1,13 +1,13 @@ //Translation from addsub_double_exact.c //Should Verify procedure main() returns () { - var x : float(11 53); - var y : float(11 53); - var z : float(11 53); - var r : float(11 53); - x := fp(10000000 11 53); - y := x + fp(1 11 53); - z := x - fp(1 11 53); + var x : float<11, 53>; + var y : float<11, 53>; + var z : float<11, 53>; + var r : float<11, 53>; + x := fp<11, 53> (10000000bv64); + y := x + fp<11, 53>(1bv64); + z := x - fp<11, 53>(1bv64); r := y - z; - assert r == fp(2 11 53); + assert r == fp<11, 53> (2bv64); } \ No newline at end of file -- cgit v1.2.3 From 5cff8cd77c629ec8e48a2498b1e704173306586a Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Mon, 6 Jun 2016 21:09:06 -0600 Subject: finished testing, fixed several minor compiler bugs --- Source/Basetypes/BigFloat.cs | 2 +- Source/Core/Parser.cs | 82 ++++++++++++++++++++-------------- Source/Provers/SMTLib/SMTLibProcess.cs | 2 +- Test/floats/float0.bpl | 14 ++++++ Test/floats/float0.bpl.expect | 8 ++++ Test/floats/float1.bpl | 13 ++++++ Test/floats/float1.bpl.expect | 2 + Test/floats/float10.bpl | 18 ++++++++ Test/floats/float10.bpl.expect | 5 +++ Test/floats/float11.bpl | 22 +++++++++ Test/floats/float11.bpl.expect | 7 +++ Test/floats/float12.bpl | 16 +++++++ Test/floats/float12.bpl.expect | 2 + Test/floats/float13.bpl | 23 ++++++++++ Test/floats/float14.bpl | 17 +++++++ Test/floats/float15.bpl | 36 +++++++++++++++ Test/floats/float16.bpl | 40 +++++++++++++++++ Test/floats/float17.bpl | 38 ++++++++++++++++ Test/floats/float18.bpl | 16 +++++++ Test/floats/float19.bpl | 34 ++++++++++++++ Test/floats/float2.bpl | 15 +++++++ Test/floats/float2.bpl.expect | 7 +++ Test/floats/float20.bpl | 14 ++++++ Test/floats/float21.bpl | 35 +++++++++++++++ Test/floats/float22.bpl | 20 +++++++++ Test/floats/float23.bpl | 8 ++++ Test/floats/float3.bpl | 27 +++++++++++ Test/floats/float3.bpl.expect | 2 + Test/floats/float4.bpl | 11 +++++ Test/floats/float4.bpl.expect | 2 + Test/floats/float5.bpl | 24 ++++++++++ Test/floats/float5.bpl.expect | 9 ++++ Test/floats/float6.bpl | 50 +++++++++++++++++++++ Test/floats/float6.bpl.expect | 2 + Test/floats/float7.bpl | 13 ++++++ Test/floats/float7.bpl.expect | 2 + Test/floats/float8.bpl | 13 ++++++ Test/floats/float8.bpl.expect | 5 +++ Test/floats/float9.bpl | 17 +++++++ Test/floats/float9.bpl.expect | 2 + Test/floats/modpath.py | 13 ++++++ Test/floats/test1.bpl | 13 ------ Test/floats/test10.bpl | 20 --------- Test/floats/test11.bpl | 55 ----------------------- Test/floats/test12.bpl | 43 ------------------ Test/floats/test13.bpl | 19 -------- Test/floats/test14.bpl | 20 --------- Test/floats/test15.bpl | 24 ---------- Test/floats/test16.bpl | 8 ---- Test/floats/test17.bpl | 11 ----- Test/floats/test18.bpl | 36 --------------- Test/floats/test19.bpl | 36 --------------- Test/floats/test2.bpl | 17 ------- Test/floats/test20.bpl | 14 ------ Test/floats/test3.bpl | 13 ------ Test/floats/test4.bpl | 32 ------------- Test/floats/test5.bpl | 36 --------------- Test/floats/test6.bpl | 40 ----------------- Test/floats/test7.bpl | 38 ---------------- Test/floats/test8.bpl | 16 ------- Test/floats/test9.bpl | 34 -------------- 61 files changed, 653 insertions(+), 560 deletions(-) create mode 100644 Test/floats/float0.bpl create mode 100644 Test/floats/float0.bpl.expect create mode 100644 Test/floats/float1.bpl create mode 100644 Test/floats/float1.bpl.expect create mode 100644 Test/floats/float10.bpl create mode 100644 Test/floats/float10.bpl.expect create mode 100644 Test/floats/float11.bpl create mode 100644 Test/floats/float11.bpl.expect create mode 100644 Test/floats/float12.bpl create mode 100644 Test/floats/float12.bpl.expect create mode 100644 Test/floats/float13.bpl create mode 100644 Test/floats/float14.bpl create mode 100644 Test/floats/float15.bpl create mode 100644 Test/floats/float16.bpl create mode 100644 Test/floats/float17.bpl create mode 100644 Test/floats/float18.bpl create mode 100644 Test/floats/float19.bpl create mode 100644 Test/floats/float2.bpl create mode 100644 Test/floats/float2.bpl.expect create mode 100644 Test/floats/float20.bpl create mode 100644 Test/floats/float21.bpl create mode 100644 Test/floats/float22.bpl create mode 100644 Test/floats/float23.bpl create mode 100644 Test/floats/float3.bpl create mode 100644 Test/floats/float3.bpl.expect create mode 100644 Test/floats/float4.bpl create mode 100644 Test/floats/float4.bpl.expect create mode 100644 Test/floats/float5.bpl create mode 100644 Test/floats/float5.bpl.expect create mode 100644 Test/floats/float6.bpl create mode 100644 Test/floats/float6.bpl.expect create mode 100644 Test/floats/float7.bpl create mode 100644 Test/floats/float7.bpl.expect create mode 100644 Test/floats/float8.bpl create mode 100644 Test/floats/float8.bpl.expect create mode 100644 Test/floats/float9.bpl create mode 100644 Test/floats/float9.bpl.expect create mode 100644 Test/floats/modpath.py delete mode 100644 Test/floats/test1.bpl delete mode 100644 Test/floats/test10.bpl delete mode 100644 Test/floats/test11.bpl delete mode 100644 Test/floats/test12.bpl delete mode 100644 Test/floats/test13.bpl delete mode 100644 Test/floats/test14.bpl delete mode 100644 Test/floats/test15.bpl delete mode 100644 Test/floats/test16.bpl delete mode 100644 Test/floats/test17.bpl delete mode 100644 Test/floats/test18.bpl delete mode 100644 Test/floats/test19.bpl delete mode 100644 Test/floats/test2.bpl delete mode 100644 Test/floats/test20.bpl delete mode 100644 Test/floats/test3.bpl delete mode 100644 Test/floats/test4.bpl delete mode 100644 Test/floats/test5.bpl delete mode 100644 Test/floats/test6.bpl delete mode 100644 Test/floats/test7.bpl delete mode 100644 Test/floats/test8.bpl delete mode 100644 Test/floats/test9.bpl (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index a0ce03a5..3c4cc40a 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -313,7 +313,7 @@ namespace Microsoft.Basetypes return "_ " + this.value + " " + this.exponentSize + " " + this.significandSize; } else if (this.Value == "") { - return "fp (_ bv" + (this.isNeg ? "1" : "0") + " 1) (_ bv" + this.exponent + " " + this.exponentSize + ") (_ bv" + this.significand + " " + this.significandSize + ")"; + return "fp (_ bv" + (this.isNeg ? "1" : "0") + " 1) (_ bv" + this.exponent + " " + this.exponentSize + ") (_ bv" + this.significand + " " + (this.significandSize-1) + ")"; } else { return "(_ to_fp " + this.exponentSize + " " + this.significandSize + ") (_ bv" + this.value + " " + (this.exponentSize + this.significandSize).ToString() + ")"; diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 8161544f..7982f594 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -668,35 +668,7 @@ private class BvBounds : Expr { ty = new BasicType(t, SimpleType.Real); } else if (la.kind == 98) { Get(); - if (t.val.Length > 5) { - switch (Int32.Parse(t.val.Substring(5))) { - case 16: - ty = new FloatType(t, 5, 11); - break; - case 32: - ty = new FloatType(t, 8, 24); - break; - case 64: - ty = new FloatType(t, 11, 53); - break; - case 128: - ty = new FloatType(t, 15, 113); - break; - default: - SynErr(3); - break; - } - } - else { - Expect(19); //< - Expect(3); //int - int exp = Int32.Parse(t.val); - Expect(12); //, - Expect(3); //int - int man = Int32.Parse(t.val); - ty = new FloatType(t, exp, man); - Expect(20); //> - } + ty = FType(); } else if (la.kind == 16) { Get(); ty = new BasicType(t, SimpleType.Bool); @@ -707,6 +679,39 @@ private class BvBounds : Expr { } else SynErr(101); } + FloatType FType() { + if (t.val.Length > 5) { + switch (Int32.Parse(t.val.Substring(5))) { + case 16: + return new FloatType(t, 5, 11); + case 32: + return new FloatType(t, 8, 24); + case 64: + return new FloatType(t, 11, 53); + case 128: + return new FloatType(t, 15, 113); + default: + SynErr(3); + return new FloatType(t, 0, 0); + } + } + else { + try { + Expect(19); //< + Expect(3); //int + int exp = Int32.Parse(t.val); + Expect(12); //, + Expect(3); //int + int man = Int32.Parse(t.val); + Expect(20); //> + return new FloatType(t, exp, man); + } + catch (Exception) { + return new FloatType(t, 0, 0); + } + } + } + void Ident(out IToken/*!*/ x) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); Expect(1); @@ -1915,8 +1920,13 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Get(); //Skip the float token if (la.val == "(") { Get(); - Expect(16); //bool - negative = Boolean.Parse(t.val); + if (la.val == "false") + negative = false; + else if (la.val == "true") + negative = true; + else + throw new FormatException(); + Get(); Expect(12); //, BvLit(out exp_val, out exp); Expect(12); @@ -1933,10 +1943,16 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { sig = Int32.Parse(t.val); Expect(20); //> Expect(9); //( - if (la.kind == 4) { + if (la.kind == 1) { //NaN Get(); n = new BigFloat(t.val, exp, sig); } + else if (la.kind == 74 || la.kind == 75) { //+ or - + Get(); + String s = t.val; + Get(); + n = new BigFloat(s + t.val, exp, sig); + } else { BvLit(out value, out size); n = new BigFloat(value.ToString(), exp, sig); @@ -2194,7 +2210,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x}, {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,x,T,x, x,T,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, + {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}, diff --git a/Source/Provers/SMTLib/SMTLibProcess.cs b/Source/Provers/SMTLib/SMTLibProcess.cs index 4982d81e..bc94e253 100644 --- a/Source/Provers/SMTLib/SMTLibProcess.cs +++ b/Source/Provers/SMTLib/SMTLibProcess.cs @@ -93,7 +93,7 @@ namespace Microsoft.Boogie.SMTLib log = log.Replace("\r", "").Replace("\n", " "); Console.WriteLine("[SMT-INP-{0}] {1}", smtProcessId, log); } - Console.WriteLine(cmd); + //Console.WriteLine(cmd); toProver.WriteLine(cmd); } diff --git a/Test/floats/float0.bpl b/Test/floats/float0.bpl new file mode 100644 index 00000000..b1a240be --- /dev/null +++ b/Test/floats/float0.bpl @@ -0,0 +1,14 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure foo(x : real) returns (r : float<8, 24>) +{ + r := 15; // Error + r := 15.0; // Error + r := fp(false, 1bv8, 0bv22); // Error + r := fp<8, 23>(1bv31); // Error + r := x; // Error + r := fp<8, 23>(1bv31) + fp<8, 23>(1bv31); // Error + r := fp<8, 24>(1bv32) + fp<8, 23>(1bv31); // Error + + return; +} \ No newline at end of file diff --git a/Test/floats/float0.bpl.expect b/Test/floats/float0.bpl.expect new file mode 100644 index 00000000..4c934700 --- /dev/null +++ b/Test/floats/float0.bpl.expect @@ -0,0 +1,8 @@ +float0.bpl(5,1): Error: mismatched types in assignment command (cannot assign int to float (8 24)) +float0.bpl(6,1): Error: mismatched types in assignment command (cannot assign real to float (8 24)) +float0.bpl(7,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float0.bpl(8,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float0.bpl(9,1): Error: mismatched types in assignment command (cannot assign real to float (8 24)) +float0.bpl(10,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float0.bpl(11,23): Error: invalid argument types (float (8 24) and float (8 23)) to binary operator + +7 type checking errors detected in float0.bpl diff --git a/Test/floats/float1.bpl b/Test/floats/float1.bpl new file mode 100644 index 00000000..9ed62579 --- /dev/null +++ b/Test/floats/float1.bpl @@ -0,0 +1,13 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure foo(x : float<8, 24>) returns (r : float<8, 24>) +{ + r := fp(false, 1bv8, 0bv23); + r := fp<8, 24>(1bv32); + r := x; + r := x + fp<8, 24>(1bv32); + r := fp<8, 24>(1bv32) + fp<8, 24>(1bv32); + assert(r == fp<8, 24>(2bv32)); + + return; +} \ No newline at end of file diff --git a/Test/floats/float1.bpl.expect b/Test/floats/float1.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float1.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float10.bpl b/Test/floats/float10.bpl new file mode 100644 index 00000000..bf07aec6 --- /dev/null +++ b/Test/floats/float10.bpl @@ -0,0 +1,18 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure double_range_true() returns () { + var x : float64; + havoc x; + if (x >= TO_FLOAT64_REAL(-1e307) && x <= TO_FLOAT64_REAL(1e307)) { + assert(x==x); + } +} + +procedure double_range_false() returns () { + var x : float64; + havoc x; + assert(x==x); +} \ No newline at end of file diff --git a/Test/floats/float10.bpl.expect b/Test/floats/float10.bpl.expect new file mode 100644 index 00000000..cae8d781 --- /dev/null +++ b/Test/floats/float10.bpl.expect @@ -0,0 +1,5 @@ +float10.bpl(17,2): Error BP5001: This assertion might not hold. +Execution trace: + float10.bpl(16,2): anon0 + +Boogie program verifier finished with 1 verified, 1 error diff --git a/Test/floats/float11.bpl b/Test/floats/float11.bpl new file mode 100644 index 00000000..424c5a2d --- /dev/null +++ b/Test/floats/float11.bpl @@ -0,0 +1,22 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); + +procedure main() returns () { + var tick : float32; + var time : float32; + var i: int; + + tick := TO_FLOAT32_INT(1)/TO_FLOAT32_INT(10); + time := TO_FLOAT32_INT(0); + + i := 0; + while (i < 10) + { + time := time + tick; + i := i + 1; + } + assert time == TO_FLOAT32_INT(1); +} \ No newline at end of file diff --git a/Test/floats/float11.bpl.expect b/Test/floats/float11.bpl.expect new file mode 100644 index 00000000..19e55fef --- /dev/null +++ b/Test/floats/float11.bpl.expect @@ -0,0 +1,7 @@ +..\Test\floats\float11.bpl(21,2): Error BP5001: This assertion might not hold. +Execution trace: + ..\Test\floats\float11.bpl(12,7): anon0 + ..\Test\floats\float11.bpl(16,2): anon3_LoopHead + ..\Test\floats\float11.bpl(16,2): anon3_LoopDone + +Boogie program verifier finished with 0 verified, 1 error diff --git a/Test/floats/float12.bpl b/Test/floats/float12.bpl new file mode 100644 index 00000000..349abb41 --- /dev/null +++ b/Test/floats/float12.bpl @@ -0,0 +1,16 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_FLOAT32(float32) returns (float64); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_FLOAT64(float64) returns (float32); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure main() returns () { + var x : float64; + var y : float32; + + x := TO_FLOAT64_REAL(1e20)+TO_FLOAT64_INT(1); + y := TO_FLOAT32_FLOAT64(x); + assert x != TO_FLOAT64_FLOAT32(y); +} \ No newline at end of file diff --git a/Test/floats/float12.bpl.expect b/Test/floats/float12.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float12.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float13.bpl b/Test/floats/float13.bpl new file mode 100644 index 00000000..4fe25140 --- /dev/null +++ b/Test/floats/float13.bpl @@ -0,0 +1,23 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure main() returns () { + var x : float64; + var y : float64; + + havoc x; + assume(x >= TO_FLOAT64_INT(0) && x <= TO_FLOAT64_INT(10)); + + y := x*x - x; + if (y >= TO_FLOAT64_INT(0)) { + y := x / TO_FLOAT64_INT(10); + } + else { + y := x*x + TO_FLOAT64_INT(2); + } + + assert(y >= TO_FLOAT64_INT(0) && y <= TO_FLOAT64_INT(105)); +} \ No newline at end of file diff --git a/Test/floats/float14.bpl b/Test/floats/float14.bpl new file mode 100644 index 00000000..46c1b07d --- /dev/null +++ b/Test/floats/float14.bpl @@ -0,0 +1,17 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure main() returns () { + var x : float64; + var y : float64; + var r : float64; + + x := TO_FLOAT64_INT(77617); + y := TO_FLOAT64_INT(33096); + r := y*y*y*y*y*y * TO_FLOAT64_REAL(333.75) + x*x * (x*x*y*y*TO_FLOAT64_INT(11) - y*y*y*y*y*y - y*y*y*y * TO_FLOAT64_INT(121) - TO_FLOAT64_INT(2)) + y*y*y*y*y*y*y*y * TO_FLOAT64_REAL(5.5) + x / (y*TO_FLOAT64_INT(2)); + + assert(r >= TO_FLOAT64_INT(0)); +} \ No newline at end of file diff --git a/Test/floats/float15.bpl b/Test/floats/float15.bpl new file mode 100644 index 00000000..7536f8fd --- /dev/null +++ b/Test/floats/float15.bpl @@ -0,0 +1,36 @@ +//Translation from filter1.c +//Should Verify + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure main() returns () { + var E0 : float64; + var E1 : float64; + var S : float64); + var i : int; + var rand : int; + + E1 := TO_FLOAT64_INT(0); + S := TO_FLOAT64_INT(0); + + i := 0; + while (i <= 1000000) + { + havoc E0; + assume(E0 >= fp(-1 11 53) && E0 <= fp(1 11 53)); + + havoc rand; + if (rand != 0) { + S := fp(0 11 53); + } + else { + S := fp(0.999 11 53) * S + E0 - E1; + } + E1 := E0; + + //assert(1==0); + assert(S >= fp(-1 11 53) && S <= fp(1 11 53)); + i := i + 1; + } +} \ No newline at end of file diff --git a/Test/floats/float16.bpl b/Test/floats/float16.bpl new file mode 100644 index 00000000..6bef1137 --- /dev/null +++ b/Test/floats/float16.bpl @@ -0,0 +1,40 @@ +//Translation from filter2.c +//Should give an error +//FAILS; doesn't generate terms! + +procedure main() returns () { + var E : float(11 53); + var E0 : float(11 53); + var E1 : float(11 53); + var S : float(11 53); + var S0 : float(11 53); + var S1 : float(11 53); + var i: int; + + havoc E; + havoc E0; + assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); + assume(E0 >= fp(0.0 11 53) && E0 <= fp(1.0 11 53)); + + E1 := fp(0.0 11 53); + S1 := fp(0.0 11 53); + S0 := fp(0.0 11 53); + S := fp(0.0 11 53); + + i := 0; +// while (i <= 1000000) +// { + E1 := E0; + E0 := E; + + havoc E; + assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); + + S1 := S0; + S0 := S; + S := E*fp(0.7 11 53) - E0*fp(1.3 11 53) + E1*fp(1.1 11 53) + S0*fp(1.4 11 53) - S1*fp(0.7 11 53); + + assert(S >= fp(-4.0 11 53) && S <= fp(4.0 11 53)); + //i := i + 1; +// } +} \ No newline at end of file diff --git a/Test/floats/float17.bpl b/Test/floats/float17.bpl new file mode 100644 index 00000000..8e07878d --- /dev/null +++ b/Test/floats/float17.bpl @@ -0,0 +1,38 @@ +//Translation from filter2.c +//Should give an error +//Same as the previous one; it works with reals! + +procedure main() returns () { + var E : real; + var E0 : real; + var E1 : real; + var S : real; + var S0 : real; + var S1 : real; + var i: int; + + havoc E; + havoc E0; + assume(E >= 0.0 && E <= 1.0); + assume(E0 >= 0.0 && E0 <= 1.0); + + S0 := 0.0; + S := 0.0; + + i := 0; + while (i <= 1000000) + { + E1 := E0; + E0 := E; + + havoc E; + assume(E >= 0.0 && E <= 1.0); + + S1 := S0; + S0 := S; + S := E*0.7 - E0*1.3 + E1*1.1 + S0*1.4 - S1*0.7; + + assert(S >= -4.0 && S <= 4.0); + i := i + 1; + } +} \ No newline at end of file diff --git a/Test/floats/float18.bpl b/Test/floats/float18.bpl new file mode 100644 index 00000000..7e78e206 --- /dev/null +++ b/Test/floats/float18.bpl @@ -0,0 +1,16 @@ +//Translation from float_double.c +//Should Verify + +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_FLOAT32(float32) returns (float64); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_FLOAT64(float64) returns (float32); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); + +procedure main() returns () { + var x : float64; + var y : float32; + + x := TO_FLOAT64_REAL(1e20)+TO_FLOAT64_INT(1); + y := TO_FLOAT32_FLOAT64(x); + assert x != TO_FLOAT64_FLOAT32(y); +} \ No newline at end of file diff --git a/Test/floats/float19.bpl b/Test/floats/float19.bpl new file mode 100644 index 00000000..c3a42e6b --- /dev/null +++ b/Test/floats/float19.bpl @@ -0,0 +1,34 @@ +//Translation from feedback_diverge.c +//Should give an error +//Not sure on this one... + +procedure main() returns () { + var A : float; + var B : float; + var X : float; + var i : int; + var rand : int; + + A := fp(0); + B := fp(0); + + i := 0; + while (i < 3600000) { + + havoc rand; + if (rand != 0) { + havoc X; + assume(X >= fp(-20) && X <= fp(20)); + } + else { + X := B; + } + + B := B - (B * fp(2.0) - A - X) * fp(.005); + A := X; + + i := i + 1; + } + + assert(A >= fp(-100) && A <= fp(100)); +} \ No newline at end of file diff --git a/Test/floats/float2.bpl b/Test/floats/float2.bpl new file mode 100644 index 00000000..1a4d02cd --- /dev/null +++ b/Test/floats/float2.bpl @@ -0,0 +1,15 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure foo(x : float16) returns(r : float32) { + var y : float64; + var z : float128; + + r := x; // Error + r := y; // Error + r := z; // Error + y := x; // Error + y := z; // Error + z := x; // Error + + return; +} \ No newline at end of file diff --git a/Test/floats/float2.bpl.expect b/Test/floats/float2.bpl.expect new file mode 100644 index 00000000..62348741 --- /dev/null +++ b/Test/floats/float2.bpl.expect @@ -0,0 +1,7 @@ +float2.bpl(7,1): Error: mismatched types in assignment command (cannot assign float (5 11) to float (8 24)) +float2.bpl(8,1): Error: mismatched types in assignment command (cannot assign float (11 53) to float (8 24)) +float2.bpl(9,1): Error: mismatched types in assignment command (cannot assign float (15 113) to float (8 24)) +float2.bpl(10,1): Error: mismatched types in assignment command (cannot assign float (5 11) to float (11 53)) +float2.bpl(11,1): Error: mismatched types in assignment command (cannot assign float (15 113) to float (11 53)) +float2.bpl(12,1): Error: mismatched types in assignment command (cannot assign float (5 11) to float (15 113)) +6 type checking errors detected in float2.bpl diff --git a/Test/floats/float20.bpl b/Test/floats/float20.bpl new file mode 100644 index 00000000..57c605fd --- /dev/null +++ b/Test/floats/float20.bpl @@ -0,0 +1,14 @@ +//Should return an error? +//Translation from Rump_double.c + +procedure main() returns () { + var x : float(11 53); + var y : float(11 53); + var r : float(11 53); + + x := fp(77617 11 53); + y := fp(33096 11 53); + r := y*y*y*y*y*y * fp(333.75 11 53) + x*x * (x*x*y*y*fp(11 11 53) - y*y*y*y*y*y - y*y*y*y * fp(121 11 53) - fp(2 11 53)) + y*y*y*y*y*y*y*y * fp(5.5 11 53) + x / (y*fp(2 11 53)); + + assert(r >= fp(0 11 53)); +} \ No newline at end of file diff --git a/Test/floats/float21.bpl b/Test/floats/float21.bpl new file mode 100644 index 00000000..5fad5859 --- /dev/null +++ b/Test/floats/float21.bpl @@ -0,0 +1,35 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); + +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + + havoc x; + assume(x >= TO_FLOAT32_INT(-1) && x <= TO_FLOAT32_INT(1)); + + if (x != TO_FLOAT32_INT(0)) { + y := x * x; + assert(y != TO_FLOAT32_INT(0)); + z := TO_FLOAT32_INT(1) / y; + } +} + +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + + havoc x; + assume(x >= TO_FLOAT32_INT(-1) && x <= TO_FLOAT32_INT(1)); + + if (x <= TO_FLOAT32_REAL(-1e-20) || x >= TO_FLOAT32_REAL(1e-20)) { + y := x * x; + assert(y != TO_FLOAT32_INT(0)); + z := TO_FLOAT32_INT(1) / y; + } +} \ No newline at end of file diff --git a/Test/floats/float22.bpl b/Test/floats/float22.bpl new file mode 100644 index 00000000..1505c361 --- /dev/null +++ b/Test/floats/float22.bpl @@ -0,0 +1,20 @@ +//Translation from inv_square_true-unreach-call.c +//Should Verify + +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); + +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + + havoc x; + assume(x >= TO_FLOAT32_INT(-1) && x <= TO_FLOAT32_INT(1)); + + if (x <= TO_FLOAT32_REAL(-1e-20) || x >= TO_FLOAT32_REAL(1e-20)) { + y := x * x; + assert(y != TO_FLOAT32_INT(0)); + z := TO_FLOAT32_INT(1) / y; + } +} \ No newline at end of file diff --git a/Test/floats/float23.bpl b/Test/floats/float23.bpl new file mode 100644 index 00000000..69ae243d --- /dev/null +++ b/Test/floats/float23.bpl @@ -0,0 +1,8 @@ +//Translation from nan_double_false-unreach-call.c +//Should return an error + +procedure main() returns () { + var x : float(11 53); + havoc x; + assert(x==x); +} \ No newline at end of file diff --git a/Test/floats/float3.bpl b/Test/floats/float3.bpl new file mode 100644 index 00000000..34059f80 --- /dev/null +++ b/Test/floats/float3.bpl @@ -0,0 +1,27 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + + z := x + y; + z := x - y; + z := x * y; + assume(y != fp<8, 24>(0bv32)); + z := x / y; + + z := (fp<8, 24>(1bv32) + fp<8, 24>(1bv32)) + fp<8, 24>(0bv32); + assert(z == fp<8, 24>(2bv32)); + + z := fp<8, 24>(2bv32) - fp<8, 24>(1bv32); + assert(z == fp<8, 24>(1bv32)); + + z := fp(false, 127bv8, 0bv23) * fp(false, 127bv8, 0bv23); + assert(z == fp(false, 127bv8, 0bv23)); + + z := fp<8, 24>(1bv32) / fp<8, 24>(1bv32); + assert(z == fp(false, 127bv8, 0bv23)); + + return; +} \ No newline at end of file diff --git a/Test/floats/float3.bpl.expect b/Test/floats/float3.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float3.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float4.bpl b/Test/floats/float4.bpl new file mode 100644 index 00000000..7bb24250 --- /dev/null +++ b/Test/floats/float4.bpl @@ -0,0 +1,11 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure foo() returns (r : float32) { + r := fp<8, 24>(NaN); + r := fp<8, 24>(+oo); + r := fp<8, 24>(-oo); + r := fp<8, 24>(+zero); + r := fp<8, 24>(-zero); + + return; +} \ No newline at end of file diff --git a/Test/floats/float4.bpl.expect b/Test/floats/float4.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float4.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float5.bpl b/Test/floats/float5.bpl new file mode 100644 index 00000000..fd630394 --- /dev/null +++ b/Test/floats/float5.bpl @@ -0,0 +1,24 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 8 23) RNE"} TO_FLOAT823_INT(int) returns (float<8, 23>); +function {:builtin "(_ to_fp 8 23) RNE"} TO_FLOAT823_REAL(real) returns (float<8, 23>); +function {:builtin "(_ to_fp 8 23) RNE"} TO_FLOAT823_BV31(bv31) returns (float<8, 23>); +function {:builtin "(_ to_fp 8 23) RNE"} TO_FLOAT823_BV32(bv32) returns (float<8, 23>); +function {:builtin "(_ to_fp 8 23) RNE"} TO_FLOAT823_FLOAT824(float<8, 24>) returns (float<8, 23>); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT824_FLOAT823(float<8, 23>) returns (float<8, 24>); + +procedure foo(x : float<8, 24>) returns (r : float<8, 24>) { + r := TO_FLOAT823_INT(5); // Error + r := TO_FLOAT823_REAL(5.0); // Error + r := TO_FLOAT823_BV31(0bv31); // Error + r := TO_FLOAT823_BV32(0bv32); // Error + r := TO_FLOAT823_FLOAT824(fp<8, 24>(1bv32)); // Error + r := TO_FLOAT824_FLOAT823(fp<8, 24>(1bv32)); // Error + r := TO_FLOAT824_FLOAT823(fp<8, 23>(1bv31)); + + r := TO_FLOAT823_FLOAT824(x); // Error + r := TO_FLOAT824_FLOAT823(x); // Error + + return; +} \ No newline at end of file diff --git a/Test/floats/float5.bpl.expect b/Test/floats/float5.bpl.expect new file mode 100644 index 00000000..6c0b86af --- /dev/null +++ b/Test/floats/float5.bpl.expect @@ -0,0 +1,9 @@ +float5.bpl(12,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(13,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(14,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(15,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(16,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(17,42): Error: invalid type for argument 0 in application of TO_FLOAT824_FLOAT823: float (8 24) (expected: float (8 23)) +float5.bpl(20,1): Error: mismatched types in assignment command (cannot assign float (8 23) to float (8 24)) +float5.bpl(21,27): Error: invalid type for argument 0 in application of TO_FLOAT824_FLOAT823: float (8 24) (expected: float (8 23)) +8 type checking errors detected in float5.bpl diff --git a/Test/floats/float6.bpl b/Test/floats/float6.bpl new file mode 100644 index 00000000..fe0eab0e --- /dev/null +++ b/Test/floats/float6.bpl @@ -0,0 +1,50 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT824_INT(int) returns (float<8, 24>); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT824_REAL(real) returns (float<8, 24>); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT824_BV32(bv32) returns (float<8, 24>); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT1153_BV64(bv64) returns (float<11, 53>); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT824_FLOAT32(float32) returns (float<8, 24>); //Should just be an identity function +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_FLOAT824(float<8, 24>) returns (float32); //Should just be an identity function +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_FLOAT64(float64) returns (float32); +function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_FLOAT32(float32) returns (float64); + +procedure main() returns () { + var i : int; + var r : real; + var f824 : float<8, 24>; + var f32 : float32; + var f1153 : float<11, 53>; + var f64 : float64; + + f824 := TO_FLOAT824_INT(5); + f32 := TO_FLOAT824_INT(5); + f824 := TO_FLOAT824_REAL(5.0); + f32 := TO_FLOAT824_REAL(5.0); + + f824 := TO_FLOAT824_BV32(0bv32); + f32 := TO_FLOAT824_BV32(0bv32); + f1153 := TO_FLOAT1153_BV64(0bv64); + f64 := TO_FLOAT1153_BV64(0bv64); + + f824 := TO_FLOAT824_FLOAT32(fp<8, 24>(0bv32)); + f32 := TO_FLOAT32_FLOAT824(fp<8, 24>(0bv32)); + f824 := TO_FLOAT32_FLOAT64(fp<11, 53>(0bv32)); + f32 := TO_FLOAT32_FLOAT64(fp<11, 53>(0bv32)); + f1153 := TO_FLOAT64_FLOAT32(fp<8, 24>(0bv32)); + f64 := TO_FLOAT64_FLOAT32(fp<8, 24>(0bv32)); + + f824 := TO_FLOAT824_INT(5); + f32 := TO_FLOAT32_FLOAT824(f824); + assert(f32 == f824); + + f32 := TO_FLOAT824_INT(5); + f824 := TO_FLOAT824_FLOAT32(f32); + assert(f32 == f824); + + f32 := TO_FLOAT32_FLOAT64(f64); + f64 := TO_FLOAT64_FLOAT32(f32); + + return; +} \ No newline at end of file diff --git a/Test/floats/float6.bpl.expect b/Test/floats/float6.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float6.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float7.bpl b/Test/floats/float7.bpl new file mode 100644 index 00000000..f330b2ea --- /dev/null +++ b/Test/floats/float7.bpl @@ -0,0 +1,13 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure main() returns () { + var x : float<11, 53>; + var y : float<11, 53>; + var z : float<11, 53>; + var r : float<11, 53>; + x := fp<11, 53> (10000000bv64); + y := x + fp<11, 53>(1bv64); + z := x - fp<11, 53>(1bv64); + r := y - z; + assert r == fp<11, 53> (2bv64); +} \ No newline at end of file diff --git a/Test/floats/float7.bpl.expect b/Test/floats/float7.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float7.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/float8.bpl b/Test/floats/float8.bpl new file mode 100644 index 00000000..78c11a2b --- /dev/null +++ b/Test/floats/float8.bpl @@ -0,0 +1,13 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + var r : float32; + x := fp<8, 24>(3221225472bv32); + y := x + fp<8, 24>(1bv32); + z := x - fp<8, 24>(1bv32); + r := y - z; + assert r == fp<8, 24>(2bv32); +} \ No newline at end of file diff --git a/Test/floats/float8.bpl.expect b/Test/floats/float8.bpl.expect new file mode 100644 index 00000000..426c21e0 --- /dev/null +++ b/Test/floats/float8.bpl.expect @@ -0,0 +1,5 @@ +float8.bpl(12,2): Error BP5001: This assertion might not hold. +Execution trace: + float8.bpl(8,4): anon0 + +Boogie program verifier finished with 0 verified, 1 error diff --git a/Test/floats/float9.bpl b/Test/floats/float9.bpl new file mode 100644 index 00000000..cb4f3afd --- /dev/null +++ b/Test/floats/float9.bpl @@ -0,0 +1,17 @@ +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" + +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); +function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); + +procedure main() returns () { + var x : float32; + var y : float32; + var z : float32; + var r : float32; + x := TO_FLOAT32_REAL(1e7); + y := x + TO_FLOAT32_INT(1); + z := x - TO_FLOAT32_INT(1); + r := y - z; + assert r == TO_FLOAT32_INT(2); +} \ No newline at end of file diff --git a/Test/floats/float9.bpl.expect b/Test/floats/float9.bpl.expect new file mode 100644 index 00000000..6abb715b --- /dev/null +++ b/Test/floats/float9.bpl.expect @@ -0,0 +1,2 @@ + +Boogie program verifier finished with 1 verified, 0 errors diff --git a/Test/floats/modpath.py b/Test/floats/modpath.py new file mode 100644 index 00000000..90707701 --- /dev/null +++ b/Test/floats/modpath.py @@ -0,0 +1,13 @@ +import sys + +f = open(sys.argv[1], 'r') +to_write = "" + +for i in f: + to_write += i.replace("..\\Test\\floats\\", "") + +f.close() + +f = open(sys.argv[1], 'w') + +f.write(to_write) \ No newline at end of file diff --git a/Test/floats/test1.bpl b/Test/floats/test1.bpl deleted file mode 100644 index e893e098..00000000 --- a/Test/floats/test1.bpl +++ /dev/null @@ -1,13 +0,0 @@ -//Translation from addsub_double_exact.c -//Should Verify -procedure main() returns () { - var x : float<11, 53>; - var y : float<11, 53>; - var z : float<11, 53>; - var r : float<11, 53>; - x := fp<11, 53> (10000000bv64); - y := x + fp<11, 53>(1bv64); - z := x - fp<11, 53>(1bv64); - r := y - z; - assert r == fp<11, 53> (2bv64); -} \ No newline at end of file diff --git a/Test/floats/test10.bpl b/Test/floats/test10.bpl deleted file mode 100644 index 566f7a56..00000000 --- a/Test/floats/test10.bpl +++ /dev/null @@ -1,20 +0,0 @@ -//Translation from loop.c -//Should return an error? (The real case does as well...) - -procedure main() returns () { - var x : float; - var y : float; - var z : float; - - x := fp(1); - y := fp(10000000); - z := fp(42); - - while (x < y) { - x := x + fp(1); - y := y - fp(1); - z := z + fp(1); - } - - assert(z >= fp(0) && z <= fp(10000000)); -} \ No newline at end of file diff --git a/Test/floats/test11.bpl b/Test/floats/test11.bpl deleted file mode 100644 index cee3e36e..00000000 --- a/Test/floats/test11.bpl +++ /dev/null @@ -1,55 +0,0 @@ -//Translation from interpolation.c -//Should Verify -//Returns inconclusive? What does that mean? - -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); -procedure main() returns () { - var i : int; - var z : float32; - var t : float32; - var min : [int] float32; - var max : [int] float32; - - min[0] := TO_FLOAT32_INT(5); - min[1] := TO_FLOAT32_INT(10); - min[2] := TO_FLOAT32_INT(12); - min[3] := TO_FLOAT32_INT(30); - min[4] := TO_FLOAT32_INT(150); - - max[0] := TO_FLOAT32_INT(10); - max[1] := TO_FLOAT32_INT(12); - max[2] := TO_FLOAT32_INT(30); - max[3] := TO_FLOAT32_INT(150); - max[4] := TO_FLOAT32_INT(300); - - havoc t; - assume(t >= min[0] && t <= max[4]); - - i := 0; - //while (i < 5) { - //if (t <= max[i]) { - //break; - //} - //i := i + 1; - //} - - if (t > max[0]) { //1 - i := i + 1; - } - if (t > max[1]) { //2 - i := i + 1; - } - if (t > max[2]) { //3 - i := i + 1; - } - if (t > max[3]) { //4 - i := i + 1; - } - if (t > max[4]) { //5 - i := i + 1; - } - - z := (t - min[i]) / (max[i] - min[i]); - - assert(z >= TO_FLOAT32_INT(0) && z <= TO_FLOAT32_INT(1)); -} \ No newline at end of file diff --git a/Test/floats/test12.bpl b/Test/floats/test12.bpl deleted file mode 100644 index c733b9f4..00000000 --- a/Test/floats/test12.bpl +++ /dev/null @@ -1,43 +0,0 @@ -//Translation from inv_Newton.c -//Should Verify -//Unfinished code! - -procedure inv(float(11 53)) returns(float(11 53)) { - var z : float(11 53); - var t : float(11 53); - var t : float(11 53); - - -} - -procedure main() returns () { - var t : float(11 53); - var t : float(11 53); - - min[0] := fp(5); - min[1] := fp(10); - min[2] := fp(12); - min[3] := fp(30); - min[4] := fp(150); - - max[0] := fp(10); - max[1] := fp(12); - max[2] := fp(30); - max[3] := fp(150); - max[4] := fp(300); - - havoc t; - assume(t >= min[0] && t <= max[4]); - - i := 0; - while (i < 5) { - if (t <= max[i]) { - break; - } - i := i + 1; - } - - z := (t - min[i]) / (max[i] - min[i]); - - assert(z >= fp(0) && z <= fp(1)); -} \ No newline at end of file diff --git a/Test/floats/test13.bpl b/Test/floats/test13.bpl deleted file mode 100644 index e5402539..00000000 --- a/Test/floats/test13.bpl +++ /dev/null @@ -1,19 +0,0 @@ -//Translation from inv_square_false-unreach-call.c -//Should return an error (without crashing) - -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); - -procedure main() returns () { - var x : float32; - var y : float32; - var z : float32; - - havoc x; - assume(x >= TO_FLOAT32_INT(-1) && x <= TO_FLOAT32_INT(1)); - - if (x != TO_FLOAT32_INT(0)) { - y := x * x; - assert(y != TO_FLOAT32_INT(0)); - z := TO_FLOAT32_INT(1) / y; - } -} \ No newline at end of file diff --git a/Test/floats/test14.bpl b/Test/floats/test14.bpl deleted file mode 100644 index 1505c361..00000000 --- a/Test/floats/test14.bpl +++ /dev/null @@ -1,20 +0,0 @@ -//Translation from inv_square_true-unreach-call.c -//Should Verify - -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); - -procedure main() returns () { - var x : float32; - var y : float32; - var z : float32; - - havoc x; - assume(x >= TO_FLOAT32_INT(-1) && x <= TO_FLOAT32_INT(1)); - - if (x <= TO_FLOAT32_REAL(-1e-20) || x >= TO_FLOAT32_REAL(1e-20)) { - y := x * x; - assert(y != TO_FLOAT32_INT(0)); - z := TO_FLOAT32_INT(1) / y; - } -} \ No newline at end of file diff --git a/Test/floats/test15.bpl b/Test/floats/test15.bpl deleted file mode 100644 index 1dc549ac..00000000 --- a/Test/floats/test15.bpl +++ /dev/null @@ -1,24 +0,0 @@ -//Translation from Muller_Kahan.c -//Should Verify -//NOTE: (fp(....)) causes a compiler error! -//FAILS! Heavily... - -procedure main() returns () { - var x0 : float(11 53); - var x1 : float(11 53); - var x2 : float(11 53); - var i : int; - - x0 := fp(11 11 53) / fp(2 11 53); - x1 := fp(61 11 53) / fp(11 11 53); - i := 0; - while (i < 100) { - x2 := fp(1130 11 53) - fp(3000 11 53) / x0; - x2 := fp(111 11 53) - x2 / x1; - x0 := x1; - x1 := x2; - i := i + 1; - } - - assert(x0 >= fp(99 11 53) && x0 <= fp(101 11 53)); -} \ No newline at end of file diff --git a/Test/floats/test16.bpl b/Test/floats/test16.bpl deleted file mode 100644 index 69ae243d..00000000 --- a/Test/floats/test16.bpl +++ /dev/null @@ -1,8 +0,0 @@ -//Translation from nan_double_false-unreach-call.c -//Should return an error - -procedure main() returns () { - var x : float(11 53); - havoc x; - assert(x==x); -} \ No newline at end of file diff --git a/Test/floats/test17.bpl b/Test/floats/test17.bpl deleted file mode 100644 index caa1fa74..00000000 --- a/Test/floats/test17.bpl +++ /dev/null @@ -1,11 +0,0 @@ -//Translation from nan_double_range_true-unreach-call.c -//Should verify -//Uggghhhh, should I add support for e? - -procedure main() returns () { - var x : float(11 53); - havoc x; - if (x >= fp(-100000000000000000000000000 11 53) && x <= fp(100000000000000000000000000 11 53)) { - assert(x==x); - } -} \ No newline at end of file diff --git a/Test/floats/test18.bpl b/Test/floats/test18.bpl deleted file mode 100644 index 71eb5286..00000000 --- a/Test/floats/test18.bpl +++ /dev/null @@ -1,36 +0,0 @@ -//Translation from rlim_exit.c -//Should verify -//Unary - unsupported float operations (on my end)... - -procedure main() returns () { - var X : float; - var Y : float; - var S : float; - var R : float; - var D : float; - var i : int; - - Y := fp(0); - - i := 0; - while (i < 100000) { - havoc X; - havoc D; - assume(X >= fp(-128) && X <= fp(128)); - assume(D >= fp(0) && D <= fp(16)); - - S := Y; - Y := X; - R := X - S; - if (R <= fp(0)-D) { - Y := S - D; - } - else if(R >= D) { - Y := S + D; - } - - i := i + 1; - } - - assert(Y >= fp(-129) && Y <= fp(129)); -} \ No newline at end of file diff --git a/Test/floats/test19.bpl b/Test/floats/test19.bpl deleted file mode 100644 index f00d8a2b..00000000 --- a/Test/floats/test19.bpl +++ /dev/null @@ -1,36 +0,0 @@ -//Translation from flim_invariant.c -//Should verify -//Unary - unsupported float operations (on my end)... - -procedure main() returns () { - var X : float; - var Y : float; - var S : float; - var R : float; - var D : float; - var i : int; - - Y := fp(0); - - i := 0; - while (i < 100000) { - havoc X; - havoc D; - assume(X >= fp(-128) && X <= fp(128)); - assume(D >= fp(0) && D <= fp(16)); - - S := Y; - Y := X; - R := X - S; - if (R <= fp(0)-D) { - Y := S - D; - } - else if(R >= D) { - Y := S + D; - } - - assert(Y >= fp(-129) && Y <= fp(129)); - - i := i + 1; - } -} \ No newline at end of file diff --git a/Test/floats/test2.bpl b/Test/floats/test2.bpl deleted file mode 100644 index d78c339d..00000000 --- a/Test/floats/test2.bpl +++ /dev/null @@ -1,17 +0,0 @@ -//Translation from addsub_float_exact.c -//Should Verify - -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); - -procedure main() returns () { - var x : float32; - var y : float32; - var z : float32; - var r : float32; - x := TO_FLOAT32_REAL(1e7); - y := x + TO_FLOAT32_INT(1); - z := x - TO_FLOAT32_INT(1); - r := y - z; - assert r == TO_FLOAT32_INT(2); -} \ No newline at end of file diff --git a/Test/floats/test20.bpl b/Test/floats/test20.bpl deleted file mode 100644 index 57c605fd..00000000 --- a/Test/floats/test20.bpl +++ /dev/null @@ -1,14 +0,0 @@ -//Should return an error? -//Translation from Rump_double.c - -procedure main() returns () { - var x : float(11 53); - var y : float(11 53); - var r : float(11 53); - - x := fp(77617 11 53); - y := fp(33096 11 53); - r := y*y*y*y*y*y * fp(333.75 11 53) + x*x * (x*x*y*y*fp(11 11 53) - y*y*y*y*y*y - y*y*y*y * fp(121 11 53) - fp(2 11 53)) + y*y*y*y*y*y*y*y * fp(5.5 11 53) + x / (y*fp(2 11 53)); - - assert(r >= fp(0 11 53)); -} \ No newline at end of file diff --git a/Test/floats/test3.bpl b/Test/floats/test3.bpl deleted file mode 100644 index 67c6ba48..00000000 --- a/Test/floats/test3.bpl +++ /dev/null @@ -1,13 +0,0 @@ -//Translation from addsub_float_inexact.c -//Should give an error -procedure main() returns () { - var x : float32; - var y : float32; - var z : float32; - var r : float32; - x := fp<8, 24>(3221225472bv32); - y := x + fp<8, 24>(1bv32); - z := x - fp<8, 24>(1bv32); - r := y - z; - assert r == fp<8, 24>(2bv32); -} \ No newline at end of file diff --git a/Test/floats/test4.bpl b/Test/floats/test4.bpl deleted file mode 100644 index a31aa215..00000000 --- a/Test/floats/test4.bpl +++ /dev/null @@ -1,32 +0,0 @@ -//Translation from drift_tenth.c -//Should Fail - -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_INT(int) returns (float32); -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_REAL(real) returns (float32); - -procedure main() returns () { - var tick : float32; - var time : float32; - var i: int; - - tick := TO_FLOAT32_INT(1)/TO_FLOAT32_INT(10); - time := TO_FLOAT32_INT(0); - - //i := 0; - //while (i < 10) - //{ - // time := time + tick; - // i := i + 1; - //} - time := time + tick;//1 - time := time + tick;//2 - time := time + tick;//3 - time := time + tick;//4 - time := time + tick;//5 - time := time + tick;//6 - time := time + tick;//7 - time := time + tick;//8 - time := time + tick;//9 - time := time + tick;//10 - assert time == TO_FLOAT32_INT(1); -} \ No newline at end of file diff --git a/Test/floats/test5.bpl b/Test/floats/test5.bpl deleted file mode 100644 index 7536f8fd..00000000 --- a/Test/floats/test5.bpl +++ /dev/null @@ -1,36 +0,0 @@ -//Translation from filter1.c -//Should Verify - -function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); -function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); - -procedure main() returns () { - var E0 : float64; - var E1 : float64; - var S : float64); - var i : int; - var rand : int; - - E1 := TO_FLOAT64_INT(0); - S := TO_FLOAT64_INT(0); - - i := 0; - while (i <= 1000000) - { - havoc E0; - assume(E0 >= fp(-1 11 53) && E0 <= fp(1 11 53)); - - havoc rand; - if (rand != 0) { - S := fp(0 11 53); - } - else { - S := fp(0.999 11 53) * S + E0 - E1; - } - E1 := E0; - - //assert(1==0); - assert(S >= fp(-1 11 53) && S <= fp(1 11 53)); - i := i + 1; - } -} \ No newline at end of file diff --git a/Test/floats/test6.bpl b/Test/floats/test6.bpl deleted file mode 100644 index 6bef1137..00000000 --- a/Test/floats/test6.bpl +++ /dev/null @@ -1,40 +0,0 @@ -//Translation from filter2.c -//Should give an error -//FAILS; doesn't generate terms! - -procedure main() returns () { - var E : float(11 53); - var E0 : float(11 53); - var E1 : float(11 53); - var S : float(11 53); - var S0 : float(11 53); - var S1 : float(11 53); - var i: int; - - havoc E; - havoc E0; - assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); - assume(E0 >= fp(0.0 11 53) && E0 <= fp(1.0 11 53)); - - E1 := fp(0.0 11 53); - S1 := fp(0.0 11 53); - S0 := fp(0.0 11 53); - S := fp(0.0 11 53); - - i := 0; -// while (i <= 1000000) -// { - E1 := E0; - E0 := E; - - havoc E; - assume(E >= fp(0.0 11 53) && E <= fp(1.0 11 53)); - - S1 := S0; - S0 := S; - S := E*fp(0.7 11 53) - E0*fp(1.3 11 53) + E1*fp(1.1 11 53) + S0*fp(1.4 11 53) - S1*fp(0.7 11 53); - - assert(S >= fp(-4.0 11 53) && S <= fp(4.0 11 53)); - //i := i + 1; -// } -} \ No newline at end of file diff --git a/Test/floats/test7.bpl b/Test/floats/test7.bpl deleted file mode 100644 index 8e07878d..00000000 --- a/Test/floats/test7.bpl +++ /dev/null @@ -1,38 +0,0 @@ -//Translation from filter2.c -//Should give an error -//Same as the previous one; it works with reals! - -procedure main() returns () { - var E : real; - var E0 : real; - var E1 : real; - var S : real; - var S0 : real; - var S1 : real; - var i: int; - - havoc E; - havoc E0; - assume(E >= 0.0 && E <= 1.0); - assume(E0 >= 0.0 && E0 <= 1.0); - - S0 := 0.0; - S := 0.0; - - i := 0; - while (i <= 1000000) - { - E1 := E0; - E0 := E; - - havoc E; - assume(E >= 0.0 && E <= 1.0); - - S1 := S0; - S0 := S; - S := E*0.7 - E0*1.3 + E1*1.1 + S0*1.4 - S1*0.7; - - assert(S >= -4.0 && S <= 4.0); - i := i + 1; - } -} \ No newline at end of file diff --git a/Test/floats/test8.bpl b/Test/floats/test8.bpl deleted file mode 100644 index 7e78e206..00000000 --- a/Test/floats/test8.bpl +++ /dev/null @@ -1,16 +0,0 @@ -//Translation from float_double.c -//Should Verify - -function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_FLOAT32(float32) returns (float64); -function {:builtin "(_ to_fp 8 24) RNE"} TO_FLOAT32_FLOAT64(float64) returns (float32); -function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_INT(int) returns (float64); -function {:builtin "(_ to_fp 11 53) RNE"} TO_FLOAT64_REAL(real) returns (float64); - -procedure main() returns () { - var x : float64; - var y : float32; - - x := TO_FLOAT64_REAL(1e20)+TO_FLOAT64_INT(1); - y := TO_FLOAT32_FLOAT64(x); - assert x != TO_FLOAT64_FLOAT32(y); -} \ No newline at end of file diff --git a/Test/floats/test9.bpl b/Test/floats/test9.bpl deleted file mode 100644 index c3a42e6b..00000000 --- a/Test/floats/test9.bpl +++ /dev/null @@ -1,34 +0,0 @@ -//Translation from feedback_diverge.c -//Should give an error -//Not sure on this one... - -procedure main() returns () { - var A : float; - var B : float; - var X : float; - var i : int; - var rand : int; - - A := fp(0); - B := fp(0); - - i := 0; - while (i < 3600000) { - - havoc rand; - if (rand != 0) { - havoc X; - assume(X >= fp(-20) && X <= fp(20)); - } - else { - X := B; - } - - B := B - (B * fp(2.0) - A - X) * fp(.005); - A := X; - - i := i + 1; - } - - assert(A >= fp(-100) && A <= fp(100)); -} \ No newline at end of file -- cgit v1.2.3 From f3f704edfb2cd1021d811050c72694767710217f Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Tue, 19 Jul 2016 11:14:41 -0600 Subject: Added and briefly tested the updated syntax. NaN/oo not supported yet --- Source/AbsInt/IntervalDomain.cs | 6 +- Source/Basetypes/BigFloat.cs | 982 +++++++++++++++++++++------------------- Source/Core/AbsyExpr.cs | 12 +- Source/Core/AbsyType.cs | 8 +- Source/Core/BoogiePL.atg | 25 +- Source/Core/Parser.cs | 889 ++++++++++++++++++------------------ Source/Core/Scanner.cs | 385 ++++++++-------- Test/floats/float0.bpl | 8 +- Test/floats/float1.bpl | 24 +- 9 files changed, 1213 insertions(+), 1126 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/AbsInt/IntervalDomain.cs b/Source/AbsInt/IntervalDomain.cs index 9d37476f..1d35b735 100644 --- a/Source/AbsInt/IntervalDomain.cs +++ b/Source/AbsInt/IntervalDomain.cs @@ -695,10 +695,10 @@ namespace Microsoft.Boogie.AbstractInterpretation Lo = floor; Hi = ceiling; } else if (node.Val is BigFloat) { - BigNum floor, ceiling; + BigInteger floor, ceiling; ((BigFloat)node.Val).FloorCeiling(out floor, out ceiling); - Lo = floor.ToBigInteger; - Hi = ceiling.ToBigInteger; + Lo = floor; + Hi = ceiling; } else if (node.Val is bool) { if ((bool)node.Val) { // true diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 3c4cc40a..5f711e70 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -1,475 +1,507 @@ -//----------------------------------------------------------------------------- -// -// Copyright (C) Microsoft Corporation. All Rights Reserved. -// -//----------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Diagnostics.Contracts; -using System.Diagnostics; - -namespace Microsoft.Basetypes -{ - using BIM = System.Numerics.BigInteger; - - /// - /// A representation of a 32-bit floating point value - /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit significand - /// - public struct BigFloat - { - //Please note that this code outline is copy-pasted from BigDec.cs - - // the internal representation - [Rep] - internal readonly BigNum significand; //Note that the significand arrangement matches standard fp arrangement (most significant bit is farthest left) - [Rep] - internal readonly int significandSize; - [Rep] - internal readonly BigNum exponent; //The value of the exponent is always positive as per fp representation requirements - [Rep] - internal readonly int exponentSize; //The bit size of the exponent - [Rep] - internal readonly String value; //Only used with second syntax - [Rep] - internal readonly bool isNeg; - - public BigNum Significand { - get { - return significand; - } - } - - public BigNum Exponent { - get { - return exponent; - } - } - - public int SignificandSize { - get { - return significandSize; - } - } - - public int ExponentSize { - get { - return exponentSize; - } - } - - public bool IsNegative { - get { - return this.isNeg; - } - } - - public String Value { - get { - return value; - } - } - - public static BigFloat ZERO(int exponentSize, int significandSize) { return new BigFloat(false, BigNum.ZERO, BigNum.ZERO, exponentSize, significandSize); } //Does not include negative zero - - private static readonly BigNum two = new BigNum(2); - private static readonly BigNum one = new BigNum(1); - private static BigNum two_n(int n) { - BigNum toReturn = one; - for (int i = 0; i < n; i++) - toReturn = toReturn * two; - return toReturn; - } - - - //////////////////////////////////////////////////////////////////////////// - // Constructors - - //Please note that these constructors will be called throughout boogie - //For a complete summary of where this class has been added, simply view constructor references - - [Pure] - public static BigFloat FromInt(int v) { - return new BigFloat(v.ToString(), 8, 24); - } - - public static BigFloat FromInt(int v, int exponentSize, int significandSize) - { - return new BigFloat(v.ToString(), exponentSize, significandSize); - } - - public static BigFloat FromBigInt(BIM v) { - return new BigFloat(v.ToString(), 8, 24); - } - - public static BigFloat FromBigInt(BIM v, int exponentSize, int significandSize) - { - return new BigFloat(v.ToString(), exponentSize, significandSize); - } - - public static BigFloat FromBigDec(BigDec v) - { - return new BigFloat(v.ToDecimalString(), 8, 24); - } - - public static BigFloat FromBigDec(BigDec v, int exponentSize, int significandSize) - { - return new BigFloat(v.ToDecimalString(), exponentSize, significandSize); - } - - [Pure] - public static BigFloat FromString(String v, int exp, int sig) { //String must be - return new BigFloat(v, exp, sig); - } - - public BigFloat(bool sign, BigNum exponent, BigNum significand, int exponentSize, int significandSize) { - this.exponentSize = exponentSize; - this.exponent = exponent; - this.significand = significand; - this.significandSize = significandSize+1; - this.isNeg = sign; - this.value = ""; - } - - public BigFloat(String value, int exponentSize, int significandSize) { - this.exponentSize = exponentSize; - this.significandSize = significandSize; - this.exponent = BigNum.ZERO; - this.significand = BigNum.ZERO; - this.value = value; - this.isNeg = value[0] == '-'; - } - - private BigNum maxsignificand() - { - BigNum result = one; - for (int i = 0; i < significandSize; i++) - result = result * two; - return result - one; - } - private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } - - - - //////////////////////////////////////////////////////////////////////////// - // Basic object operations - - [Pure] - [Reads(ReadsAttribute.Reads.Nothing)] - public override bool Equals(object obj) { - if (obj == null) - return false; - if (!(obj is BigFloat)) - return false; - - return (this == (BigFloat)obj); - } - - [Pure] - public override int GetHashCode() { - return significand.GetHashCode() * 13 + Exponent.GetHashCode(); - } - - [Pure] - public override string/*!*/ ToString() { - Contract.Ensures(Contract.Result() != null); - return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; - } - - - //////////////////////////////////////////////////////////////////////////// - // Conversion operations - - /// - /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!! - /// Converts the given decimal value (provided as a string) to the nearest floating point approximation - /// the returned fp assumes the given significand and exponent size - /// - /// - /// - /// - /// - public static BigFloat Round(String value, int exponentSize, int significandSize) - { - int i = value.IndexOf('.'); - if (i == -1) - return Round(BigNum.FromString(value), BigNum.ZERO, exponentSize, significandSize); - return Round(i == 0 ? BigNum.ZERO : BigNum.FromString(value.Substring(0, i)), BigNum.FromString(value.Substring(i + 1, value.Length - i - 1)), exponentSize, significandSize); - } - - /// - /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!!! - /// Converts value.dec_value to a the closest float approximation with the given significandSize, exponentSize - /// Returns the result of this calculation - /// - /// - /// - /// - /// - /// - public static BigFloat Round(BigNum value, BigNum dec_value, int exponentSize, int significandSize) - { - int exp = 0; - BigNum one = new BigNum(1); - BigNum ten = new BigNum(10); - BigNum dec_max = new BigNum(0); //represents the order of magnitude of dec_value for carrying during calculations - - //First, determine the exponent - while (value > one) { //Divide by two, increment exponent by 1 - if (!(value % two).IsZero) { //Add "1.0" to the decimal - dec_max = new BigNum(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - dec_value = dec_value + dec_max; - } - value = value / two; - if (!(dec_value % ten).IsZero) - dec_value = dec_value * ten; //Creates excess zeroes to avoid losing data during division - dec_value = dec_value / two; - exp++; - } - if (value.IsZero && !dec_value.IsZero) { - dec_max = new BigNum(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - while (value.IsZero) {//Multiply by two, decrement exponent by 1 - dec_value = dec_value * two; - if (dec_value >= dec_max) { - dec_value = dec_value - dec_max; - value = value + one; - } - exp--; - } - } - - //Second, calculate the significand - value = new BigNum(0); //remove implicit bit - dec_max = new BigNum(10); - while (dec_max < dec_value) - dec_max = dec_max * ten; - for (int i = significandSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the significand is fully calculated - dec_value = dec_value * two; - if (dec_value >= dec_max) { - dec_value = dec_value - dec_max; - value = value + two_n(i); //Note that i is decrementing so that the most significant bit is left-most in the representation - } - } - - return new BigFloat(false, BigNum.ZERO, BigNum.FromString(value.ToString()), exponentSize, significandSize); //Sign not actually checked... - } - - // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). - /// - /// NOTE: THIS PROBABLY WON'T GIVE USEFUL OUTPUT!!! - /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative - /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way. - /// - /// The Floor (rounded towards negative infinity) - /// Ceiling (rounded towards positive infinity) - public void FloorCeiling(out BigNum floor, out BigNum ceiling) { - //TODO: fix for fp functionality - BigNum n = Significand; - BigNum e = Exponent; - if (n.IsZero) { - floor = ceiling = n; - } else if (BigNum.ZERO <= e) { - // it's an integer - for (; BigNum.ZERO < e; e = e - one) - { - n = n * two; - } - floor = ceiling = n; - } else { - // it's a non-zero integer, so the ceiling is one more than the floor - for (; BigNum.ZERO < e && !n.IsZero; e = e + one) - { - n = n / two; // Division rounds towards negative infinity - } - - if (!IsNegative) { - floor = n; - ceiling = n + one; - } else { - ceiling = n; - floor = n - one; - } - } - Debug.Assert(floor <= ceiling, "Invariant was not maintained"); - } - - [Pure] - public String ToDecimalString(int maxDigits) { - //TODO: fix for fp functionality - { - throw new NotImplementedException(); - } - } - - public String ToBVString(){ - if (this.IsSpecialType) { - return "_ " + this.value + " " + this.exponentSize + " " + this.significandSize; - } - else if (this.Value == "") { - return "fp (_ bv" + (this.isNeg ? "1" : "0") + " 1) (_ bv" + this.exponent + " " + this.exponentSize + ") (_ bv" + this.significand + " " + (this.significandSize-1) + ")"; - } - else { - return "(_ to_fp " + this.exponentSize + " " + this.significandSize + ") (_ bv" + this.value + " " + (this.exponentSize + this.significandSize).ToString() + ")"; - } - } - - [Pure] - public string ToDecimalString() { - Contract.Ensures(Contract.Result() != null); - return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; - } - - [Pure] - public static string Zeros(int n) { - //TODO: fix for fp functionality - Contract.Requires(0 <= n); - if (n <= 10) { - var tenZeros = "0000000000"; - return tenZeros.Substring(0, n); - } else { - var d = n / 2; - var s = Zeros(d); - if (n % 2 == 0) { - return s + s; - } else { - return s + s + "0"; - } - } - } - - - //////////////////////////////////////////////////////////////////////////// - // Basic arithmetic operations - - [Pure] - public BigFloat Abs { - get { - return new BigFloat(true, Exponent, Significand, ExponentSize, SignificandSize); - } - } - - [Pure] - public BigFloat Negate { - get { - if (value != "") - return value[0] == '-' ? new BigFloat(value.Remove(0, 1), ExponentSize, significandSize) : new BigFloat("-" + value, ExponentSize, significandSize); - return new BigFloat(!isNeg, Exponent, Significand, ExponentSize, SignificandSize); - } - } - - [Pure] - public static BigFloat operator -(BigFloat x) { - return x.Negate; - } - - [Pure] - public static BigFloat operator +(BigFloat x, BigFloat y) { - //TODO: Modify for correct fp functionality - Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.significandSize == y.significandSize); - BigNum m1 = x.significand; - BigNum e1 = x.Exponent; - BigNum m2 = y.significand; - BigNum e2 = y.Exponent; - m1 = m1 + two_n(x.significandSize + 1); //Add implicit bit - m2 = m2 + two_n(y.significandSize + 1); - if (e2 > e1) { - m1 = y.significand; - e1 = y.Exponent; - m2 = x.significand; - e2 = x.Exponent; - } - - while (e2 < e1) { - m2 = m2 / two; - e2 = e2 + one; - } - - return new BigFloat(false, e1, m1 + m2, x.significandSize, x.ExponentSize); - } - - [Pure] - public static BigFloat operator -(BigFloat x, BigFloat y) { - return x + y.Negate; - } - - [Pure] - public static BigFloat operator *(BigFloat x, BigFloat y) { - Contract.Requires(x.ExponentSize == y.ExponentSize); - Contract.Requires(x.significandSize == y.significandSize); - return new BigFloat(x.isNeg ^ y.isNeg, x.Exponent + y.Exponent, x.significand * y.significand, x.significandSize, x.ExponentSize); - } - - - //////////////////////////////////////////////////////////////////////////// - // Some basic comparison operations - - public bool IsSpecialType { - get { - if (value == "") - return false; - return (value.Equals("NaN") || value.Equals("+oo") || value.Equals("-oo") || value.Equals("zero") || value.Equals("-zero")); - } - } - - public bool IsPositive { - get { - return !IsNegative; - } - } - - public bool IsZero { - get { - return significand.Equals(BigNum.ZERO) && Exponent == BigNum.ZERO; - } - } - - [Pure] - public int CompareTo(BigFloat that) { - if (this.exponent > that.exponent) - return 1; - if (this.exponent < that.exponent) - return -1; - if (this.significand == that.significand) - return 0; - return this.significand > that.significand ? 1 : -1; - } - - [Pure] - public static bool operator ==(BigFloat x, BigFloat y) { - return x.CompareTo(y) == 0; - } - - [Pure] - public static bool operator !=(BigFloat x, BigFloat y) { - return x.CompareTo(y) != 0; - } - - [Pure] - public static bool operator <(BigFloat x, BigFloat y) { - return x.CompareTo(y) < 0; - } - - [Pure] - public static bool operator >(BigFloat x, BigFloat y) { - return x.CompareTo(y) > 0; - } - - [Pure] - public static bool operator <=(BigFloat x, BigFloat y) { - return x.CompareTo(y) <= 0; - } - - [Pure] - public static bool operator >=(BigFloat x, BigFloat y) { - return x.CompareTo(y) >= 0; - } - } -} +//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.Diagnostics; + +namespace Microsoft.Basetypes +{ + using BIM = System.Numerics.BigInteger; + + /// + /// A representation of a 32-bit floating point value + /// Note that this value has a 1-bit sign, 8-bit exponent, and 24-bit significand + /// + public struct BigFloat + { + //Please note that this code outline is copy-pasted from BigDec.cs + + // the internal representation + [Rep] + internal readonly BIM significand; //Note that the significand arrangement matches standard fp arrangement (most significant bit is farthest left) + [Rep] + internal readonly int significandSize; + [Rep] + internal readonly BIM exponent; //The value of the exponent is always positive as per fp representation requirements + [Rep] + internal readonly int exponentSize; //The bit size of the exponent + [Rep] + internal readonly String value; //Only used with second syntax + [Rep] + internal readonly bool isNeg; + + public BIM Significand { + get { + return significand; + } + } + + public BIM Exponent { + get { + return exponent; + } + } + + public int SignificandSize { + get { + return significandSize; + } + } + + public int ExponentSize { + get { + return exponentSize; + } + } + + public bool IsNegative { + get { + return this.isNeg; + } + } + + public String Value { + get { + return value; + } + } + + public static BigFloat ZERO = new BigFloat(false, BIM.Zero, BIM.Zero, 24, 8); //Does not include negative zero + + private static readonly BIM two = new BIM(2); + private static readonly BIM one = new BIM(1); + private static BIM two_n(int n) { + BIM toReturn = one; + for (int i = 0; i < n; i++) + toReturn = toReturn * two; + return toReturn; + } + + + //////////////////////////////////////////////////////////////////////////// + // Constructors + + //Please note that these constructors will be called throughout boogie + //For a complete summary of where this class has been added, simply view constructor references + + [Pure] + public static BigFloat FromInt(int v) { + return new BigFloat(v.ToString(), 24, 8); + } + + public static BigFloat FromInt(int v, int significandSize, int exponentSize) + { + return new BigFloat(v.ToString(), significandSize, exponentSize); + } + + public static BigFloat FromBigInt(BIM v) { + return new BigFloat(v.ToString(), 24, 8); + } + + public static BigFloat FromBigInt(BIM v, int significandSize, int exponentSize) + { + return new BigFloat(v.ToString(), significandSize, exponentSize); + } + + public static BigFloat FromBigDec(BigDec v) + { + return new BigFloat(v.ToDecimalString(), 24, 8); + } + + public static BigFloat FromBigDec(BigDec v, int significandSize, int exponentSize) + { + return new BigFloat(v.ToDecimalString(), significandSize, exponentSize); + } + + [Pure] + public static BigFloat FromString(String s) { + /* + * String must be either of the format *e*f*e* + * or of the special value formats: 0NaN*e* 0nan*e* 0+oo*e* 0-oo*e* + * Where * indicates an integer value (digit) + */ + BIM sig, exp; + int sigSize, expSize; + bool isNeg; + + if (s.IndexOf('f') == -1) { + String val = s; + sigSize = int.Parse(s.Substring(4, s.IndexOf('e')-4)); + expSize = int.Parse(s.Substring(s.IndexOf('e') + 1)); + if (sigSize <= 0 || expSize <= 0) + throw new FormatException("Significand and Exponent sizes must be greater than 0"); + return new BigFloat(val, sigSize, expSize); + } + + sig = BIM.Parse(s.Substring(0, s.IndexOf('e'))); + exp = BIM.Parse(s.Substring(s.IndexOf('e') + 1, s.IndexOf('f') - s.IndexOf('e') - 1)); + sigSize = int.Parse(s.Substring(s.IndexOf('f') + 1, s.IndexOf('e', s.IndexOf('e') + 1) - s.IndexOf('f') - 1)); + expSize = int.Parse(s.Substring(s.IndexOf('e', s.IndexOf('e') + 1) + 1)); + + if (sigSize <= 0 || expSize <= 0) + throw new FormatException("Significand and Exponent sizes must be greater than 0"); + + sigSize = sigSize - 1; //Get rid of sign bit + isNeg = sig < 0; + sig = BIM.Abs(sig); + exp = exp + BIM.Pow(new BIM(2), expSize-1) - BIM.One; + + if (exp < 0 || exp >= BIM.Pow(new BIM(2), expSize)) + throw new FormatException("The given exponent " + exp + " cannot fit in the bit size " + expSize); + + if (sig >= BIM.Pow(new BIM(2), sigSize)) + throw new FormatException("The given significand " + sig + " cannot fit in the bit size " + (sigSize+1)); + + return new BigFloat(isNeg, sig, exp, sigSize, expSize); + } + + public BigFloat(bool isNeg, BIM significand, BIM exponent, int significandSize, int exponentSize) { + this.exponentSize = exponentSize; + this.exponent = exponent; + this.significand = significand; + this.significandSize = significandSize+1; + this.isNeg = isNeg; + this.value = ""; + } + + public BigFloat(String value, int significandSize, int exponentSize) { + this.exponentSize = exponentSize; + this.significandSize = significandSize; + this.exponent = BIM.Zero; + this.significand = BIM.Zero; + this.value = value; + if (value.Equals("nan")) + this.value = "NaN"; + this.isNeg = value[0] == '-'; + } + + private BIM maxsignificand() + { + BIM result = one; + for (int i = 0; i < significandSize; i++) + result = result * two; + return result - one; + } + private int maxExponent() { return (int)Math.Pow(2, exponentSize) - 1; } + + + + //////////////////////////////////////////////////////////////////////////// + // Basic object operations + + [Pure] + [Reads(ReadsAttribute.Reads.Nothing)] + public override bool Equals(object obj) { + if (obj == null) + return false; + if (!(obj is BigFloat)) + return false; + + return (this == (BigFloat)obj); + } + + [Pure] + public override int GetHashCode() { + return significand.GetHashCode() * 13 + Exponent.GetHashCode(); + } + + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result() != null); + return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; + } + + + //////////////////////////////////////////////////////////////////////////// + // Conversion operations + + /// + /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!! + /// Converts the given decimal value (provided as a string) to the nearest floating point approximation + /// the returned fp assumes the given significand and exponent size + /// + /// + /// + /// + /// + public static BigFloat Round(String value, int exponentSize, int significandSize) + { + int i = value.IndexOf('.'); + if (i == -1) + return Round(BIM.Parse(value), BIM.Zero, exponentSize, significandSize); + return Round(i == 0 ? BIM.Zero : BIM.Parse(value.Substring(0, i)), BIM.Parse(value.Substring(i + 1, value.Length - i - 1)), exponentSize, significandSize); + } + + /// + /// NOTE: THIS METHOD MAY NOT WORK AS EXPECTED!!!! + /// Converts value.dec_value to a the closest float approximation with the given significandSize, exponentSize + /// Returns the result of this calculation + /// + /// + /// + /// + /// + /// + public static BigFloat Round(BIM value, BIM dec_value, int exponentSize, int significandSize) + { + int exp = 0; + BIM one = new BIM(1); + BIM ten = new BIM(10); + BIM dec_max = new BIM(0); //represents the order of magnitude of dec_value for carrying during calculations + + //First, determine the exponent + while (value > one) { //Divide by two, increment exponent by 1 + if (!(value % two).IsZero) { //Add "1.0" to the decimal + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + dec_value = dec_value + dec_max; + } + value = value / two; + if (!(dec_value % ten).IsZero) + dec_value = dec_value * ten; //Creates excess zeroes to avoid losing data during division + dec_value = dec_value / two; + exp++; + } + if (value.IsZero && !dec_value.IsZero) { + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + while (value.IsZero) {//Multiply by two, decrement exponent by 1 + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + one; + } + exp--; + } + } + + //Second, calculate the significand + value = new BIM(0); //remove implicit bit + dec_max = new BIM(10); + while (dec_max < dec_value) + dec_max = dec_max * ten; + for (int i = significandSize; i > 0 && !dec_value.IsZero; i--) { //Multiply by two until the significand is fully calculated + dec_value = dec_value * two; + if (dec_value >= dec_max) { + dec_value = dec_value - dec_max; + value = value + two_n(i); //Note that i is decrementing so that the most significant bit is left-most in the representation + } + } + + return new BigFloat(false, BIM.Zero, BIM.Parse(value.ToString()), exponentSize, significandSize); //Sign not actually checked... + } + + // ``floor`` rounds towards negative infinity (like SMT-LIBv2's to_int). + /// + /// NOTE: This may give wrong results, it hasn't been tested extensively + /// If you're getting weird bugs, you may want to check this function out... + /// Computes the floor and ceiling of this BigFloat. Note the choice of rounding towards negative + /// infinity rather than zero for floor is because SMT-LIBv2's to_int function floors this way. + /// + /// The Floor (rounded towards negative infinity) + /// Ceiling (rounded towards positive infinity) + public void FloorCeiling(out BIM floor, out BIM ceiling) + { + BIM two = new BIM(2); + + BIM sig = Significand + BIM.Pow(two, SignificandSize); //Add hidden bit + BIM exp = Exponent - BIM.Pow(two, ExponentSize); + sig = sig >> ExponentSize; + + while (exp > BIM.Zero) { + exp--; + sig = sig >> 1; + } + + if (isNeg) { + ceiling = -sig + 1; + floor = -sig; + } + else { + ceiling = sig + 1; + floor = sig; + } + } + + [Pure] + public String ToDecimalString(int maxDigits) { + //TODO: fix for fp functionality + { + throw new NotImplementedException(); + } + } + + public String ToBVString(){ + if (this.IsSpecialType) { + return "_ " + this.value + " " + this.exponentSize + " " + this.significandSize; + } + else if (this.Value == "") { + return "fp (_ bv" + (this.isNeg ? "1" : "0") + " 1) (_ bv" + this.exponent + " " + this.exponentSize + ") (_ bv" + this.significand + " " + (this.significandSize-1) + ")"; + } + else { + return "(_ to_fp " + this.exponentSize + " " + this.significandSize + ") (_ bv" + this.value + " " + (this.exponentSize + this.significandSize).ToString() + ")"; + } + } + + [Pure] + public string ToDecimalString() { + Contract.Ensures(Contract.Result() != null); + return value=="" ? String.Format("{0}x2^{1}", significand.ToString(), Exponent.ToString()) : value; + } + + [Pure] + public static string Zeros(int n) { + //TODO: fix for fp functionality + Contract.Requires(0 <= n); + if (n <= 10) { + var tenZeros = "0000000000"; + return tenZeros.Substring(0, n); + } else { + var d = n / 2; + var s = Zeros(d); + if (n % 2 == 0) { + return s + s; + } else { + return s + s + "0"; + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Basic arithmetic operations + + [Pure] + public BigFloat Abs { + get { + return new BigFloat(true, Exponent, Significand, ExponentSize, SignificandSize); + } + } + + [Pure] + public BigFloat Negate { + get { + if (value != "") + return value[0] == '-' ? new BigFloat(value.Remove(0, 1), ExponentSize, significandSize) : new BigFloat("-" + value, ExponentSize, significandSize); + return new BigFloat(!isNeg, Exponent, Significand, ExponentSize, SignificandSize); + } + } + + [Pure] + public static BigFloat operator -(BigFloat x) { + return x.Negate; + } + + [Pure] + public static BigFloat operator +(BigFloat x, BigFloat y) { + //TODO: Modify for correct fp functionality + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.significandSize == y.significandSize); + BIM m1 = x.significand; + BIM e1 = x.Exponent; + BIM m2 = y.significand; + BIM e2 = y.Exponent; + m1 = m1 + two_n(x.significandSize + 1); //Add implicit bit + m2 = m2 + two_n(y.significandSize + 1); + if (e2 > e1) { + m1 = y.significand; + e1 = y.Exponent; + m2 = x.significand; + e2 = x.Exponent; + } + + while (e2 < e1) { + m2 = m2 / two; + e2 = e2 + one; + } + + return new BigFloat(false, e1, m1 + m2, x.significandSize, x.ExponentSize); + } + + [Pure] + public static BigFloat operator -(BigFloat x, BigFloat y) { + return x + y.Negate; + } + + [Pure] + public static BigFloat operator *(BigFloat x, BigFloat y) { + Contract.Requires(x.ExponentSize == y.ExponentSize); + Contract.Requires(x.significandSize == y.significandSize); + return new BigFloat(x.isNeg ^ y.isNeg, x.Exponent + y.Exponent, x.significand * y.significand, x.significandSize, x.ExponentSize); + } + + + //////////////////////////////////////////////////////////////////////////// + // Some basic comparison operations + + public bool IsSpecialType { + get { + if (value == "") + return false; + return (value.Equals("NaN") || value.Equals("+oo") || value.Equals("-oo") || value.Equals("zero") || value.Equals("-zero")); + } + } + + public bool IsPositive { + get { + return !IsNegative; + } + } + + public bool IsZero { + get { + return significand.Equals(BigNum.ZERO) && Exponent == BIM.Zero; + } + } + + [Pure] + public int CompareTo(BigFloat that) { + if (this.exponent > that.exponent) + return 1; + if (this.exponent < that.exponent) + return -1; + if (this.significand == that.significand) + return 0; + return this.significand > that.significand ? 1 : -1; + } + + [Pure] + public static bool operator ==(BigFloat x, BigFloat y) { + return x.CompareTo(y) == 0; + } + + [Pure] + public static bool operator !=(BigFloat x, BigFloat y) { + return x.CompareTo(y) != 0; + } + + [Pure] + public static bool operator <(BigFloat x, BigFloat y) { + return x.CompareTo(y) < 0; + } + + [Pure] + public static bool operator >(BigFloat x, BigFloat y) { + return x.CompareTo(y) > 0; + } + + [Pure] + public static bool operator <=(BigFloat x, BigFloat y) { + return x.CompareTo(y) <= 0; + } + + [Pure] + public static bool operator >=(BigFloat x, BigFloat y) { + return x.CompareTo(y) >= 0; + } + } +} diff --git a/Source/Core/AbsyExpr.cs b/Source/Core/AbsyExpr.cs index bc2b4391..409254d0 100644 --- a/Source/Core/AbsyExpr.cs +++ b/Source/Core/AbsyExpr.cs @@ -584,7 +584,7 @@ namespace Microsoft.Boogie { { Contract.Requires(tok != null); Val = v; - Type = Type.GetFloatType(v.ExponentSize, v.SignificandSize); + Type = Type.GetFloatType(v.SignificandSize, v.ExponentSize); if (immutable) CachedHashCode = ComputeHashCode(); } @@ -662,7 +662,7 @@ namespace Microsoft.Boogie { return Type.Real; } else if (Val is BigFloat) { BigFloat temp = (BigFloat)Val; - return Type.GetFloatType(temp.ExponentSize, temp.SignificandSize); + return Type.GetFloatType(temp.SignificandSize, temp.ExponentSize); } else if (Val is BvConst) { return Type.GetBvType(((BvConst)Val).Bits); } else { @@ -1724,10 +1724,10 @@ namespace Microsoft.Boogie { return Type.Real; } if (arg0type.IsFloat && arg0type.Unify(arg1type)) { - return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatSignificand); + return Type.GetFloatType(arg0.Type.FloatSignificand, arg0.Type.FloatExponent); } if (arg1type.IsFloat && arg1type.Unify(arg0type)) { - return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatSignificand); + return Type.GetFloatType(arg1.Type.FloatSignificand, arg1.Type.FloatExponent); } goto BAD_TYPE; case Opcode.Div: @@ -1742,10 +1742,10 @@ namespace Microsoft.Boogie { return Type.Real; } if (arg0type.IsFloat && arg0type.Unify(arg1type)) { - return Type.GetFloatType(arg0.Type.FloatExponent, arg0.Type.FloatSignificand); + return Type.GetFloatType(arg0.Type.FloatSignificand, arg0.Type.FloatExponent); } if (arg1type.IsFloat && arg1type.Unify(arg0type)) { - return Type.GetFloatType(arg1.Type.FloatExponent, arg1.Type.FloatSignificand); + return Type.GetFloatType(arg1.Type.FloatSignificand, arg1.Type.FloatExponent); } goto BAD_TYPE; case Opcode.Pow: diff --git a/Source/Core/AbsyType.cs b/Source/Core/AbsyType.cs index 08cf37cc..ab6ef5e9 100644 --- a/Source/Core/AbsyType.cs +++ b/Source/Core/AbsyType.cs @@ -386,12 +386,12 @@ namespace Microsoft.Boogie { } } - static public FloatType GetFloatType(int exp, int man) { + static public FloatType GetFloatType(int sig, int exp) { Contract.Requires(0 <= exp); - Contract.Requires(0 <= man); + Contract.Requires(0 <= sig); Contract.Ensures(Contract.Result() != null); - return new FloatType(exp, man); + return new FloatType(sig, exp); } //------------ Match formal argument types on actual argument types @@ -1094,7 +1094,7 @@ namespace Microsoft.Boogie { public override string ToString() { Contract.Ensures(Contract.Result() != null); - return "float (" + Exponent + " " + Significand + ")"; + return "float" + Significand + "e" + Exponent; } //----------- Equality ---------------------------------- diff --git a/Source/Core/BoogiePL.atg b/Source/Core/BoogiePL.atg index 091ceeb0..31823110 100644 --- a/Source/Core/BoogiePL.atg +++ b/Source/Core/BoogiePL.atg @@ -144,7 +144,8 @@ TOKENS string = quote { regularStringChar | "\\\"" } quote. decimal = digit {digit} 'e' [ '-' ] digit {digit} . - float = digit {digit} '.' digit {digit} [ 'e' [ '-' ] digit {digit} ] . + dec_float = digit {digit} '.' digit {digit} [ 'e' [ '-' ] digit {digit} ] . + float = digit {digit} 'e' digit {digit} 'f' digit {digit} 'e' digit {digit} . COMMENTS FROM "/*" TO "*/" NESTED COMMENTS FROM "//" TO lf @@ -330,7 +331,7 @@ TypeAtom ( "int" (. ty = new BasicType(t, SimpleType.Int); .) | "real" (. ty = new BasicType(t, SimpleType.Real); .) | "bool" (. ty = new BasicType(t, SimpleType.Bool); .) - /* note: bitvectors are handled in UnresolvedTypeIdentifier */ + /* note: bitvectors and floats are handled in UnresolvedTypeIdentifier */ | "(" Type @@ -1252,7 +1253,7 @@ ArrayExpression /*------------------------------------------------------------------------*/ AtomExpression -= (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; += (. Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; BigFloat bf; List/*!*/ es; List/*!*/ ds; Trigger trig; List/*!*/ typeParams; IdentifierExpr/*!*/ id; @@ -1265,6 +1266,7 @@ AtomExpression | "true" (. e = new LiteralExpr(t, true); .) | Nat (. e = new LiteralExpr(t, bn); .) | Dec (. e = new LiteralExpr(t, bd); .) + | Float (. e = new LiteralExpr(t, bf); .) | BvLit (. e = new LiteralExpr(t, bn, n); .) | Ident (. id = new IdentifierExpr(x, x.val); e = id; .) @@ -1479,7 +1481,7 @@ Dec ( decimal (. s = t.val; .) | - float (. s = t.val; .) + dec_float (. s = t.val; .) ) (. try { n = BigDec.FromString(s); @@ -1508,4 +1510,19 @@ BvLit } .) . + +Float += (. string s = ""; .) + ( + float (. s = t.val; .) + ) + (. try { + n = BigFloat.FromString(s); + } catch (FormatException) { + this.SemErr("incorrectly formatted number"); + n = BigFloat.ZERO; + } + .) + . + END BoogiePL. diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 78823b61..a5e2921e 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -23,8 +23,9 @@ public class Parser { public const int _digits = 3; public const int _string = 4; public const int _decimal = 5; - public const int _float = 6; - public const int maxT = 96; + public const int _dec_float = 6; + public const int _float = 7; + public const int maxT = 97; const bool T = true; const bool x = false; @@ -117,7 +118,7 @@ private class BvBounds : Expr { public BigNum Lower; public BigNum Upper; public BvBounds(IToken/*!*/ tok, BigNum lower, BigNum upper) - : base(tok, /*immutable*/ false) { + : base(tok, /*immutable=*/ false) { Contract.Requires(tok != null); this.Lower = lower; this.Upper = upper; @@ -132,8 +133,7 @@ private class BvBounds : Expr { Contract.Assert(false);throw new cce.UnreachableException(); } public override void ComputeFreeVariables(GSet/*!*/ freeVars) { Contract.Assert(false);throw new cce.UnreachableException(); } - public override int ComputeHashCode() - { + public override int ComputeHashCode() { return base.GetHashCode(); } } @@ -220,7 +220,7 @@ private class BvBounds : Expr { while (StartOf(1)) { switch (la.kind) { - case 21: { + case 22: { Consts(out vs); foreach(Bpl.Variable/*!*/ v in vs){ Contract.Assert(v != null); @@ -229,7 +229,7 @@ private class BvBounds : Expr { break; } - case 25: { + case 26: { Function(out ds); foreach(Bpl.Declaration/*!*/ d in ds){ Contract.Assert(d != null); @@ -238,12 +238,12 @@ private class BvBounds : Expr { break; } - case 29: { + case 30: { Axiom(out ax); Pgm.AddTopLevelDeclaration(ax); break; } - case 30: { + case 31: { UserDefinedTypes(out ts); foreach(Declaration/*!*/ td in ts){ Contract.Assert(td != null); @@ -252,7 +252,7 @@ private class BvBounds : Expr { break; } - case 7: { + case 8: { GlobalVars(out vs); foreach(Bpl.Variable/*!*/ v in vs){ Contract.Assert(v != null); @@ -261,7 +261,7 @@ private class BvBounds : Expr { break; } - case 32: { + case 33: { Procedure(out pr, out im); Pgm.AddTopLevelDeclaration(pr); if (im != null) { @@ -270,7 +270,7 @@ private class BvBounds : Expr { break; } - case 33: { + case 34: { Implementation(out nnim); Pgm.AddTopLevelDeclaration(nnim); break; @@ -286,17 +286,17 @@ private class BvBounds : Expr { bool u = false; QKeyValue kv = null; bool ChildrenComplete = false; List Parents = null; - Expect(21); + Expect(22); y = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } - if (la.kind == 22) { + if (la.kind == 23) { Get(); u = true; } IdsType(out xs); - if (la.kind == 23) { + if (la.kind == 24) { OrderSpec(out ChildrenComplete, out Parents); } bool makeClone = false; @@ -320,7 +320,7 @@ private class BvBounds : Expr { ds.Add(new Constant(y, x, u, ParentsClone, ChildrenComplete, kv)); } - Expect(8); + Expect(9); } void Function(out List/*!*/ ds) { @@ -337,44 +337,44 @@ private class BvBounds : Expr { Expr definition = null; Expr/*!*/ tmp; - Expect(25); - while (la.kind == 27) { + Expect(26); + while (la.kind == 28) { Attribute(ref kv); } Ident(out z); - if (la.kind == 19) { + if (la.kind == 20) { TypeParams(out typeParamTok, out typeParams); } - Expect(9); + Expect(10); if (StartOf(2)) { VarOrType(out tyd, out argKv); arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); - while (la.kind == 12) { + while (la.kind == 13) { Get(); VarOrType(out tyd, out argKv); arguments.Add(new Formal(tyd.tok, tyd, true, argKv)); } } - Expect(10); + Expect(11); argKv = null; - if (la.kind == 26) { + if (la.kind == 27) { Get(); - Expect(9); - VarOrType(out retTyd, out argKv); Expect(10); - } else if (la.kind == 11) { + VarOrType(out retTyd, out argKv); + Expect(11); + } else if (la.kind == 12) { Get(); Type(out retTy); retTyd = new TypedIdent(retTy.tok, TypedIdent.NoName, retTy); - } else SynErr(97); - if (la.kind == 27) { + } else SynErr(98); + if (la.kind == 28) { Get(); Expression(out tmp); definition = tmp; - Expect(28); - } else if (la.kind == 8) { + Expect(29); + } else if (la.kind == 9) { Get(); - } else SynErr(98); + } else SynErr(99); if (retTyd == null) { // construct a dummy type for the case of syntax error retTyd = new TypedIdent(t, TypedIdent.NoName, new BasicType(t, SimpleType.Int)); @@ -429,30 +429,30 @@ private class BvBounds : Expr { void Axiom(out Axiom/*!*/ m) { Contract.Ensures(Contract.ValueAtReturn(out m) != null); Expr/*!*/ e; QKeyValue kv = null; - Expect(29); - while (la.kind == 27) { + Expect(30); + while (la.kind == 28) { Attribute(ref kv); } IToken/*!*/ x = t; Proposition(out e); - Expect(8); + Expect(9); m = new Axiom(x,e, null, kv); } void UserDefinedTypes(out List/*!*/ ts) { Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out ts))); Declaration/*!*/ decl; QKeyValue kv = null; ts = new List (); - Expect(30); - while (la.kind == 27) { + Expect(31); + while (la.kind == 28) { Attribute(ref kv); } UserDefinedType(out decl, kv); ts.Add(decl); - while (la.kind == 12) { + while (la.kind == 13) { Get(); UserDefinedType(out decl, kv); ts.Add(decl); } - Expect(8); + Expect(9); } void GlobalVars(out List/*!*/ ds) { @@ -461,12 +461,12 @@ private class BvBounds : Expr { ds = new List(); var dsx = ds; - Expect(7); - while (la.kind == 27) { + Expect(8); + while (la.kind == 28) { Attribute(ref kv); } IdsTypeWheres(true, "global variables", delegate(TypedIdent tyd) { dsx.Add(new GlobalVariable(tyd.tok, tyd, kv)); } ); - Expect(8); + Expect(9); } void Procedure(out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl) { @@ -482,9 +482,9 @@ private class BvBounds : Expr { QKeyValue kv = null; impl = null; - Expect(32); + Expect(33); ProcSignature(true, out x, out typeParams, out ins, out outs, out kv); - if (la.kind == 8) { + if (la.kind == 9) { Get(); while (StartOf(3)) { Spec(pre, mods, post); @@ -497,7 +497,7 @@ private class BvBounds : Expr { impl = new Implementation(x, x.val, typeParams, Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors); - } else SynErr(99); + } else SynErr(100); proc = new Procedure(x, x.val, typeParams, ins, outs, pre, mods, post, kv); } @@ -509,7 +509,7 @@ private class BvBounds : Expr { StmtList/*!*/ stmtList; QKeyValue kv; - Expect(33); + Expect(34); ProcSignature(false, out x, out typeParams, out ins, out outs, out kv); ImplBody(out locals, out stmtList); impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); @@ -523,7 +523,7 @@ private class BvBounds : Expr { void IdsTypeWheres(bool allowWhereClauses, string context, System.Action action ) { IdsTypeWhere(allowWhereClauses, context, action); - while (la.kind == 12) { + while (la.kind == 13) { Get(); IdsTypeWhere(allowWhereClauses, context, action); } @@ -533,12 +533,12 @@ private class BvBounds : Expr { Contract.Ensures(Contract.ValueAtReturn(out ds) != null); QKeyValue kv = null; - Expect(7); - while (la.kind == 27) { + Expect(8); + while (la.kind == 28) { Attribute(ref kv); } IdsTypeWheres(true, "local variables", delegate(TypedIdent tyd) { ds.Add(new LocalVariable(tyd.tok, tyd, kv)); } ); - Expect(8); + Expect(9); } void ProcFormals(bool incoming, bool allowWhereClauses, out List/*!*/ ds) { @@ -547,16 +547,16 @@ private class BvBounds : Expr { var dsx = ds; var context = allowWhereClauses ? "procedure formals" : "the 'implementation' copies of formals"; - Expect(9); - if (la.kind == 1 || la.kind == 27) { + Expect(10); + if (la.kind == 1 || la.kind == 28) { AttrsIdsTypeWheres(allowWhereClauses, allowWhereClauses, context, delegate(TypedIdent tyd, QKeyValue kv) { dsx.Add(new Formal(tyd.tok, tyd, incoming, kv)); }); } - Expect(10); + Expect(11); } void AttrsIdsTypeWheres(bool allowAttributes, bool allowWhereClauses, string context, System.Action action ) { AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action); - while (la.kind == 12) { + while (la.kind == 13) { Get(); AttributesIdsTypeWhere(allowAttributes, allowWhereClauses, context, action); } @@ -575,7 +575,7 @@ private class BvBounds : Expr { void IdsType(out List/*!*/ tyds) { Contract.Ensures(Contract.ValueAtReturn(out tyds) != null); List/*!*/ ids; Bpl.Type/*!*/ ty; Idents(out ids); - Expect(11); + Expect(12); Type(out ty); tyds = new List(); foreach(Token/*!*/ id in ids){ @@ -589,7 +589,7 @@ private class BvBounds : Expr { Contract.Ensures(Contract.ValueAtReturn(out xs) != null); IToken/*!*/ id; xs = new List(); Ident(out id); xs.Add(id); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Ident(out id); xs.Add(id); @@ -607,14 +607,14 @@ private class BvBounds : Expr { TypeArgs(args); } ty = new UnresolvedTypeIdentifier (tok, tok.val, args); - } else if (la.kind == 17 || la.kind == 19) { + } else if (la.kind == 18 || la.kind == 20) { MapType(out ty); - } else SynErr(100); + } else SynErr(101); } void AttributesIdsTypeWhere(bool allowAttributes, bool allowWhereClauses, string context, System.Action action ) { QKeyValue kv = null; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); if (!allowAttributes) { kv = null; @@ -628,9 +628,9 @@ private class BvBounds : Expr { void IdsTypeWhere(bool allowWhereClauses, string context, System.Action action ) { List/*!*/ ids; Bpl.Type/*!*/ ty; Expr wh = null; Expr/*!*/ nne; Idents(out ids); - Expect(11); + Expect(12); Type(out ty); - if (la.kind == 13) { + if (la.kind == 14) { Get(); Expression(out nne); if (!allowWhereClauses) { @@ -650,7 +650,7 @@ private class BvBounds : Expr { void Expression(out Expr/*!*/ e0) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; ImpliesExpression(false, out e0); - while (la.kind == 55 || la.kind == 56) { + while (la.kind == 56 || la.kind == 57) { EquivOp(); x = t; ImpliesExpression(false, out e1); @@ -660,20 +660,20 @@ private class BvBounds : Expr { void TypeAtom(out Bpl.Type/*!*/ ty) { Contract.Ensures(Contract.ValueAtReturn(out ty) != null); ty = dummyType; - if (la.kind == 14) { + if (la.kind == 15) { Get(); ty = new BasicType(t, SimpleType.Int); - } else if (la.kind == 15) { + } else if (la.kind == 16) { Get(); ty = new BasicType(t, SimpleType.Real); - } else if (la.kind == 16) { + } else if (la.kind == 17) { Get(); ty = new BasicType(t, SimpleType.Bool); - } else if (la.kind == 9) { + } else if (la.kind == 10) { Get(); Type(out ty); - Expect(10); - } else SynErr(101); + Expect(11); + } else SynErr(102); } void Ident(out IToken/*!*/ x) { @@ -700,10 +700,10 @@ private class BvBounds : Expr { if (StartOf(6)) { TypeArgs(ts); } - } else if (la.kind == 17 || la.kind == 19) { + } else if (la.kind == 18 || la.kind == 20) { MapType(out ty); ts.Add(ty); - } else SynErr(102); + } else SynErr(103); } void MapType(out Bpl.Type/*!*/ ty) { @@ -713,16 +713,16 @@ private class BvBounds : Expr { Bpl.Type/*!*/ result; List/*!*/ typeParameters = new List(); - if (la.kind == 19) { + if (la.kind == 20) { TypeParams(out nnTok, out typeParameters); tok = nnTok; } - Expect(17); + Expect(18); if (tok == null) tok = t; if (StartOf(6)) { Types(arguments); } - Expect(18); + Expect(19); Type(out result); ty = new MapType(tok, typeParameters, arguments, result); @@ -730,10 +730,10 @@ private class BvBounds : Expr { void TypeParams(out IToken/*!*/ tok, out List/*!*/ typeParams) { Contract.Ensures(Contract.ValueAtReturn(out tok) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); List/*!*/ typeParamToks; - Expect(19); + Expect(20); tok = t; Idents(out typeParamToks); - Expect(20); + Expect(21); typeParams = new List (); foreach(Token/*!*/ id in typeParamToks){ Contract.Assert(id != null); @@ -745,7 +745,7 @@ private class BvBounds : Expr { Contract.Requires(ts != null); Bpl.Type/*!*/ ty; Type(out ty); ts.Add(ty); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Type(out ty); ts.Add(ty); @@ -757,21 +757,21 @@ private class BvBounds : Expr { Parents = null; bool u; IToken/*!*/ parent; - Expect(23); + Expect(24); Parents = new List (); u = false; - if (la.kind == 1 || la.kind == 22) { - if (la.kind == 22) { + if (la.kind == 1 || la.kind == 23) { + if (la.kind == 23) { Get(); u = true; } Ident(out parent); Parents.Add(new ConstantParent ( new IdentifierExpr(parent, parent.val), u)); - while (la.kind == 12) { + while (la.kind == 13) { Get(); u = false; - if (la.kind == 22) { + if (la.kind == 23) { Get(); u = true; } @@ -780,7 +780,7 @@ private class BvBounds : Expr { new IdentifierExpr(parent, parent.val), u)); } } - if (la.kind == 24) { + if (la.kind == 25) { Get(); ChildrenComplete = true; } @@ -793,12 +793,12 @@ private class BvBounds : Expr { IToken/*!*/ tok; kv = null; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Type(out ty); tok = ty.tok; - if (la.kind == 11) { + if (la.kind == 12) { Get(); var uti = ty as UnresolvedTypeIdentifier; if (uti != null && uti.Arguments.Count == 0) { @@ -824,7 +824,7 @@ private class BvBounds : Expr { if (la.kind == 1) { WhiteSpaceIdents(out paramTokens); } - if (la.kind == 31) { + if (la.kind == 32) { Get(); Type(out body); synonym = true; @@ -856,15 +856,15 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Contract.Ensures(Contract.ValueAtReturn(out name) != null); Contract.Ensures(Contract.ValueAtReturn(out typeParams) != null); Contract.Ensures(Contract.ValueAtReturn(out ins) != null); Contract.Ensures(Contract.ValueAtReturn(out outs) != null); IToken/*!*/ typeParamTok; typeParams = new List(); outs = new List(); kv = null; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Ident(out name); - if (la.kind == 19) { + if (la.kind == 20) { TypeParams(out typeParamTok, out typeParams); } ProcFormals(true, allowWhereClausesOnFormals, out ins); - if (la.kind == 26) { + if (la.kind == 27) { Get(); ProcFormals(false, allowWhereClausesOnFormals, out outs); } @@ -872,7 +872,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { void Spec(List/*!*/ pre, List/*!*/ mods, List/*!*/ post) { Contract.Requires(pre != null); Contract.Requires(mods != null); Contract.Requires(post != null); List/*!*/ ms; - if (la.kind == 34) { + if (la.kind == 35) { Get(); if (la.kind == 1) { Idents(out ms); @@ -882,19 +882,19 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } } - Expect(8); - } else if (la.kind == 35) { + Expect(9); + } else if (la.kind == 36) { Get(); SpecPrePost(true, pre, post); - } else if (la.kind == 36 || la.kind == 37) { + } else if (la.kind == 37 || la.kind == 38) { SpecPrePost(false, pre, post); - } else SynErr(103); + } else SynErr(104); } void ImplBody(out List/*!*/ locals, out StmtList/*!*/ stmtList) { Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(Contract.ValueAtReturn(out stmtList) != null); locals = new List(); - Expect(27); - while (la.kind == 7) { + Expect(28); + while (la.kind == 8) { LocalVars(locals); } StmtList(out stmtList); @@ -902,25 +902,25 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { void SpecPrePost(bool free, List/*!*/ pre, List/*!*/ post) { Contract.Requires(pre != null); Contract.Requires(post != null); Expr/*!*/ e; Token tok = null; QKeyValue kv = null; - if (la.kind == 36) { + if (la.kind == 37) { Get(); tok = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); - Expect(8); + Expect(9); pre.Add(new Requires(tok, free, e, null, kv)); - } else if (la.kind == 37) { + } else if (la.kind == 38) { Get(); tok = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); - Expect(8); + Expect(9); post.Add(new Ensures(tok, free, e, null, kv)); - } else SynErr(104); + } else SynErr(105); } void StmtList(out StmtList/*!*/ stmtList) { @@ -957,7 +957,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { cs = new List(); } - } else if (la.kind == 40 || la.kind == 42 || la.kind == 45) { + } else if (la.kind == 41 || la.kind == 43 || la.kind == 46) { StructuredCmd(out ecn); ec = ecn; if (startToken == null) { startToken = ec.tok; cs = new List(); } @@ -977,7 +977,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } } - Expect(28); + Expect(29); IToken/*!*/ endCurly = t; if (startToken == null && bigblocks.Count == 0) { startToken = t; cs = new List(); @@ -1005,33 +1005,33 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { LabelOrAssign(out c, out label); break; } - case 46: { + case 47: { Get(); x = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssertCmd(x, e, kv); - Expect(8); + Expect(9); break; } - case 47: { + case 48: { Get(); x = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssumeCmd(x, e, kv); - Expect(8); + Expect(9); break; } - case 48: { + case 49: { Get(); x = t; Idents(out xs); - Expect(8); + Expect(9); ids = new List(); foreach(IToken/*!*/ y in xs){ Contract.Assert(y != null); @@ -1041,25 +1041,25 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { break; } - case 35: case 51: case 52: { + case 36: case 52: case 53: { CallCmd(out cn); - Expect(8); + Expect(9); c = cn; break; } - case 53: { + case 54: { ParCallCmd(out cn); c = cn; break; } - case 49: { + case 50: { Get(); x = t; - Expect(8); + Expect(9); c = new YieldCmd(x); break; } - default: SynErr(105); break; + default: SynErr(106); break; } } @@ -1067,16 +1067,16 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Contract.Ensures(Contract.ValueAtReturn(out ec) != null); ec = dummyStructuredCmd; Contract.Assume(cce.IsPeerConsistent(ec)); IfCmd/*!*/ ifcmd; WhileCmd/*!*/ wcmd; BreakCmd/*!*/ bcmd; - if (la.kind == 40) { + if (la.kind == 41) { IfCmd(out ifcmd); ec = ifcmd; - } else if (la.kind == 42) { + } else if (la.kind == 43) { WhileCmd(out wcmd); ec = wcmd; - } else if (la.kind == 45) { + } else if (la.kind == 46) { BreakCmd(out bcmd); ec = bcmd; - } else SynErr(106); + } else SynErr(107); } void TransferCmd(out TransferCmd/*!*/ tc) { @@ -1084,7 +1084,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Token y; List/*!*/ xs; List ss = new List(); - if (la.kind == 38) { + if (la.kind == 39) { Get(); y = t; Idents(out xs); @@ -1093,11 +1093,11 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { ss.Add(s.val); } tc = new GotoCmd(y, ss); - } else if (la.kind == 39) { + } else if (la.kind == 40) { Get(); tc = new ReturnCmd(t); - } else SynErr(107); - Expect(8); + } else SynErr(108); + Expect(9); } void IfCmd(out IfCmd/*!*/ ifcmd) { @@ -1107,21 +1107,21 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { IfCmd/*!*/ elseIf; IfCmd elseIfOption = null; StmtList/*!*/ els; StmtList elseOption = null; - Expect(40); + Expect(41); x = t; Guard(out guard); - Expect(27); + Expect(28); StmtList(out thn); - if (la.kind == 41) { + if (la.kind == 42) { Get(); - if (la.kind == 40) { + if (la.kind == 41) { IfCmd(out elseIf); elseIfOption = elseIf; - } else if (la.kind == 27) { + } else if (la.kind == 28) { Get(); StmtList(out els); elseOption = els; - } else SynErr(108); + } else SynErr(109); } ifcmd = new IfCmd(x, guard, thn, elseIfOption, elseOption); } @@ -1133,18 +1133,18 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { StmtList/*!*/ body; QKeyValue kv = null; - Expect(42); + Expect(43); x = t; Guard(out guard); Contract.Assume(guard == null || cce.Owner.None(guard)); - while (la.kind == 35 || la.kind == 43) { + while (la.kind == 36 || la.kind == 44) { isFree = false; z = la/*lookahead token*/; - if (la.kind == 35) { + if (la.kind == 36) { Get(); isFree = true; } - Expect(43); - while (la.kind == 27) { + Expect(44); + while (la.kind == 28) { Attribute(ref kv); } Expression(out e); @@ -1155,9 +1155,9 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } kv = null; - Expect(8); + Expect(9); } - Expect(27); + Expect(28); StmtList(out body); wcmd = new WhileCmd(x, guard, invariants, body); } @@ -1166,27 +1166,27 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Contract.Ensures(Contract.ValueAtReturn(out bcmd) != null); IToken/*!*/ x; IToken/*!*/ y; string breakLabel = null; - Expect(45); + Expect(46); x = t; if (la.kind == 1) { Ident(out y); breakLabel = y.val; } - Expect(8); + Expect(9); bcmd = new BreakCmd(x, breakLabel); } void Guard(out Expr e) { Expr/*!*/ ee; e = null; - Expect(9); - if (la.kind == 44) { + Expect(10); + if (la.kind == 45) { Get(); e = null; } else if (StartOf(9)) { Expression(out ee); e = ee; - } else SynErr(109); - Expect(10); + } else SynErr(110); + Expect(11); } void LabelOrAssign(out Cmd c, out IToken label) { @@ -1199,40 +1199,40 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Ident(out id); x = t; - if (la.kind == 11) { + if (la.kind == 12) { Get(); c = null; label = x; - } else if (la.kind == 12 || la.kind == 17 || la.kind == 50) { + } else if (la.kind == 13 || la.kind == 18 || la.kind == 51) { lhss = new List(); lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); - while (la.kind == 17) { + while (la.kind == 18) { MapAssignIndex(out y, out indexes); lhs = new MapAssignLhs(y, lhs, indexes); } lhss.Add(lhs); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Ident(out id); lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); - while (la.kind == 17) { + while (la.kind == 18) { MapAssignIndex(out y, out indexes); lhs = new MapAssignLhs(y, lhs, indexes); } lhss.Add(lhs); } - Expect(50); + Expect(51); x = t; /* use location of := */ Expression(out e0); rhss = new List (); rhss.Add(e0); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out e0); rhss.Add(e0); } - Expect(8); + Expect(9); c = new AssignCmd(x, lhss, rhss); - } else SynErr(110); + } else SynErr(111); } void CallCmd(out Cmd c) { @@ -1243,17 +1243,17 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { QKeyValue kv = null; c = null; - if (la.kind == 51) { + if (la.kind == 52) { Get(); isAsync = true; } - if (la.kind == 35) { + if (la.kind == 36) { Get(); isFree = true; } - Expect(52); + Expect(53); x = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } CallParams(isAsync, isFree, kv, x, out c); @@ -1267,19 +1267,19 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Cmd c = null; List callCmds = new List(); - Expect(53); + Expect(54); x = t; - while (la.kind == 27) { + while (la.kind == 28) { Attribute(ref kv); } CallParams(false, false, kv, x, out c); callCmds.Add((CallCmd)c); - while (la.kind == 54) { + while (la.kind == 55) { Get(); CallParams(false, false, kv, x, out c); callCmds.Add((CallCmd)c); } - Expect(8); + Expect(9); d = new ParCallCmd(x, callCmds, kv); } @@ -1287,18 +1287,18 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out indexes))); indexes = new List (); Expr/*!*/ e; - Expect(17); + Expect(18); x = t; if (StartOf(9)) { Expression(out e); indexes.Add(e); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out e); indexes.Add(e); } } - Expect(18); + Expect(19); } void CallParams(bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c) { @@ -1310,53 +1310,53 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { c = null; Ident(out first); - if (la.kind == 9) { + if (la.kind == 10) { Get(); if (StartOf(9)) { Expression(out en); es.Add(en); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out en); es.Add(en); } } - Expect(10); + Expect(11); c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; - } else if (la.kind == 12 || la.kind == 50) { + } else if (la.kind == 13 || la.kind == 51) { ids.Add(new IdentifierExpr(first, first.val)); - if (la.kind == 12) { + if (la.kind == 13) { Get(); Ident(out p); ids.Add(new IdentifierExpr(p, p.val)); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Ident(out p); ids.Add(new IdentifierExpr(p, p.val)); } } - Expect(50); + Expect(51); Ident(out first); - Expect(9); + Expect(10); if (StartOf(9)) { Expression(out en); es.Add(en); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out en); es.Add(en); } } - Expect(10); + Expect(11); c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; - } else SynErr(111); + } else SynErr(112); } void Expressions(out List/*!*/ es) { Contract.Ensures(Contract.ValueAtReturn(out es) != null); Expr/*!*/ e; es = new List(); Expression(out e); es.Add(e); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out e); es.Add(e); @@ -1367,7 +1367,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; LogicalExpression(out e0); if (StartOf(10)) { - if (la.kind == 57 || la.kind == 58) { + if (la.kind == 58 || la.kind == 59) { ImpliesOp(); x = t; ImpliesExpression(true, out e1); @@ -1379,7 +1379,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { x = t; LogicalExpression(out e1); e0 = Expr.Binary(x, BinaryOperator.Opcode.Imp, e1, e0); - while (la.kind == 59 || la.kind == 60) { + while (la.kind == 60 || la.kind == 61) { ExpliesOp(); x = t; LogicalExpression(out e1); @@ -1390,23 +1390,23 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } void EquivOp() { - if (la.kind == 55) { + if (la.kind == 56) { Get(); - } else if (la.kind == 56) { + } else if (la.kind == 57) { Get(); - } else SynErr(112); + } else SynErr(113); } void LogicalExpression(out Expr/*!*/ e0) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; RelationalExpression(out e0); if (StartOf(11)) { - if (la.kind == 61 || la.kind == 62) { + if (la.kind == 62 || la.kind == 63) { AndOp(); x = t; RelationalExpression(out e1); e0 = Expr.Binary(x, BinaryOperator.Opcode.And, e0, e1); - while (la.kind == 61 || la.kind == 62) { + while (la.kind == 62 || la.kind == 63) { AndOp(); x = t; RelationalExpression(out e1); @@ -1417,7 +1417,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { x = t; RelationalExpression(out e1); e0 = Expr.Binary(x, BinaryOperator.Opcode.Or, e0, e1); - while (la.kind == 63 || la.kind == 64) { + while (la.kind == 64 || la.kind == 65) { OrOp(); x = t; RelationalExpression(out e1); @@ -1428,19 +1428,19 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } void ImpliesOp() { - if (la.kind == 57) { + if (la.kind == 58) { Get(); - } else if (la.kind == 58) { + } else if (la.kind == 59) { Get(); - } else SynErr(113); + } else SynErr(114); } void ExpliesOp() { - if (la.kind == 59) { + if (la.kind == 60) { Get(); - } else if (la.kind == 60) { + } else if (la.kind == 61) { Get(); - } else SynErr(114); + } else SynErr(115); } void RelationalExpression(out Expr/*!*/ e0) { @@ -1454,25 +1454,25 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } void AndOp() { - if (la.kind == 61) { + if (la.kind == 62) { Get(); - } else if (la.kind == 62) { + } else if (la.kind == 63) { Get(); - } else SynErr(115); + } else SynErr(116); } void OrOp() { - if (la.kind == 63) { + if (la.kind == 64) { Get(); - } else if (la.kind == 64) { + } else if (la.kind == 65) { Get(); - } else SynErr(116); + } else SynErr(117); } void BvTerm(out Expr/*!*/ e0) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; Term(out e0); - while (la.kind == 73) { + while (la.kind == 74) { Get(); x = t; Term(out e1); @@ -1483,64 +1483,64 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { void RelOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; switch (la.kind) { - case 65: { + case 66: { Get(); x = t; op=BinaryOperator.Opcode.Eq; break; } - case 19: { + case 20: { Get(); x = t; op=BinaryOperator.Opcode.Lt; break; } - case 20: { + case 21: { Get(); x = t; op=BinaryOperator.Opcode.Gt; break; } - case 66: { + case 67: { Get(); x = t; op=BinaryOperator.Opcode.Le; break; } - case 67: { + case 68: { Get(); x = t; op=BinaryOperator.Opcode.Ge; break; } - case 68: { + case 69: { Get(); x = t; op=BinaryOperator.Opcode.Neq; break; } - case 69: { + case 70: { Get(); x = t; op=BinaryOperator.Opcode.Subtype; break; } - case 70: { + case 71: { Get(); x = t; op=BinaryOperator.Opcode.Neq; break; } - case 71: { + case 72: { Get(); x = t; op=BinaryOperator.Opcode.Le; break; } - case 72: { + case 73: { Get(); x = t; op=BinaryOperator.Opcode.Ge; break; } - default: SynErr(117); break; + default: SynErr(118); break; } } void Term(out Expr/*!*/ e0) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; BinaryOperator.Opcode op; Factor(out e0); - while (la.kind == 74 || la.kind == 75) { + while (la.kind == 75 || la.kind == 76) { AddOp(out x, out op); Factor(out e1); e0 = Expr.Binary(x, op, e0, e1); @@ -1559,19 +1559,19 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { void AddOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; - if (la.kind == 74) { + if (la.kind == 75) { Get(); x = t; op=BinaryOperator.Opcode.Add; - } else if (la.kind == 75) { + } else if (la.kind == 76) { Get(); x = t; op=BinaryOperator.Opcode.Sub; - } else SynErr(118); + } else SynErr(119); } void Power(out Expr/*!*/ e0) { Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expr/*!*/ e1; UnaryExpression(out e0); - if (la.kind == 79) { + if (la.kind == 80) { Get(); x = t; Power(out e1); @@ -1581,46 +1581,46 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { void MulOp(out IToken/*!*/ x, out BinaryOperator.Opcode op) { Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryOperator.Opcode.Add/*(dummy)*/; - if (la.kind == 44) { + if (la.kind == 45) { Get(); x = t; op=BinaryOperator.Opcode.Mul; - } else if (la.kind == 76) { + } else if (la.kind == 77) { Get(); x = t; op=BinaryOperator.Opcode.Div; - } else if (la.kind == 77) { + } else if (la.kind == 78) { Get(); x = t; op=BinaryOperator.Opcode.Mod; - } else if (la.kind == 78) { + } else if (la.kind == 79) { Get(); x = t; op=BinaryOperator.Opcode.RealDiv; - } else SynErr(119); + } else SynErr(120); } void UnaryExpression(out Expr/*!*/ e) { Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr; - if (la.kind == 75) { + if (la.kind == 76) { Get(); x = t; UnaryExpression(out e); e = Expr.Unary(x, UnaryOperator.Opcode.Neg, e); - } else if (la.kind == 80 || la.kind == 81) { + } else if (la.kind == 81 || la.kind == 82) { NegOp(); x = t; UnaryExpression(out e); e = Expr.Unary(x, UnaryOperator.Opcode.Not, e); } else if (StartOf(14)) { CoercionExpression(out e); - } else SynErr(120); + } else SynErr(121); } void NegOp() { - if (la.kind == 80) { + if (la.kind == 81) { Get(); - } else if (la.kind == 81) { + } else if (la.kind == 82) { Get(); - } else SynErr(121); + } else SynErr(122); } void CoercionExpression(out Expr/*!*/ e) { @@ -1629,7 +1629,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { BigNum bn; ArrayExpression(out e); - while (la.kind == 11) { + while (la.kind == 12) { Get(); x = t; if (StartOf(6)) { @@ -1644,7 +1644,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { e = new BvBounds(x, bn, ((LiteralExpr)e).asBigNum); } - } else SynErr(122); + } else SynErr(123); } } @@ -1655,7 +1655,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { List/*!*/ allArgs = dummyExprSeq; AtomExpression(out e); - while (la.kind == 17) { + while (la.kind == 18) { Get(); x = t; allArgs = new List (); allArgs.Add(e); @@ -1668,7 +1668,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { else allArgs.Add(index0); - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out e1); if (bvExtract || e1 is BvBounds) @@ -1676,7 +1676,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { allArgs.Add(e1); } - if (la.kind == 50) { + if (la.kind == 51) { Get(); Expression(out e1); if (bvExtract || e1 is BvBounds) @@ -1690,7 +1690,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { allArgs.Add(e1); store = true; } } - Expect(18); + Expect(19); if (store) e = new NAryExpr(x, new MapStore(x, allArgs.Count - 2), allArgs); else if (bvExtract) @@ -1715,7 +1715,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } void AtomExpression(out Expr/*!*/ e) { - Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; + Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; int n; BigNum bn; BigDec bd; BigFloat bf; List/*!*/ es; List/*!*/ ds; Trigger trig; List/*!*/ typeParams; IdentifierExpr/*!*/ id; @@ -1725,12 +1725,12 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { List/*!*/ blocks; switch (la.kind) { - case 82: { + case 83: { Get(); e = new LiteralExpr(t, false); break; } - case 83: { + case 84: { Get(); e = new LiteralExpr(t, true); break; @@ -1745,6 +1745,11 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { e = new LiteralExpr(t, bd); break; } + case 7: { + Float(out bf); + e = new LiteralExpr(t, bf); + break; + } case 2: { BvLit(out bn, out n); e = new LiteralExpr(t, bn, n); @@ -1753,65 +1758,65 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { case 1: { Ident(out x); id = new IdentifierExpr(x, x.val); e = id; - if (la.kind == 9) { + if (la.kind == 10) { Get(); if (StartOf(9)) { Expressions(out es); e = new NAryExpr(x, new FunctionCall(id), es); - } else if (la.kind == 10) { + } else if (la.kind == 11) { e = new NAryExpr(x, new FunctionCall(id), new List()); - } else SynErr(123); - Expect(10); + } else SynErr(124); + Expect(11); } break; } - case 84: { + case 85: { Get(); x = t; - Expect(9); - Expression(out e); Expect(10); + Expression(out e); + Expect(11); e = new OldExpr(x, e); break; } - case 14: { + case 15: { Get(); x = t; - Expect(9); - Expression(out e); Expect(10); + Expression(out e); + Expect(11); e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToInt), new List{ e }); break; } - case 15: { + case 16: { Get(); x = t; - Expect(9); - Expression(out e); Expect(10); + Expression(out e); + Expect(11); e = new NAryExpr(x, new ArithmeticCoercion(x, ArithmeticCoercion.CoercionType.ToReal), new List{ e }); break; } - case 9: { + case 10: { Get(); if (StartOf(9)) { Expression(out e); if (e is BvBounds) this.SemErr("parentheses around bitvector bounds " + "are not allowed"); - } else if (la.kind == 88 || la.kind == 89) { + } else if (la.kind == 89 || la.kind == 90) { Forall(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); if (typeParams.Count + ds.Count > 0) e = new ForallExpr(x, typeParams, ds, kv, trig, e); - } else if (la.kind == 90 || la.kind == 91) { + } else if (la.kind == 91 || la.kind == 92) { Exists(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); if (typeParams.Count + ds.Count > 0) e = new ExistsExpr(x, typeParams, ds, kv, trig, e); - } else if (la.kind == 92 || la.kind == 93) { + } else if (la.kind == 93 || la.kind == 94) { Lambda(); x = t; QuantifierBody(x, out typeParams, out ds, out kv, out trig, out e); @@ -1819,20 +1824,20 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { SemErr("triggers not allowed in lambda expressions"); if (typeParams.Count + ds.Count > 0) e = new LambdaExpr(x, typeParams, ds, kv, e); - } else SynErr(124); - Expect(10); + } else SynErr(125); + Expect(11); break; } - case 40: { + case 41: { IfThenElseExpression(out e); break; } - case 85: { + case 86: { CodeExpression(out locals, out blocks); e = new CodeExpr(locals, blocks); break; } - default: SynErr(125); break; + default: SynErr(126); break; } } @@ -1844,7 +1849,7 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } else if (la.kind == 6) { Get(); s = t.val; - } else SynErr(126); + } else SynErr(127); try { n = BigDec.FromString(s); } catch (FormatException) { @@ -1854,6 +1859,19 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } + void Float(out BigFloat n) { + string s = ""; + Expect(7); + s = t.val; + try { + n = BigFloat.FromString(s); + } catch (FormatException e) { + this.SemErr("incorrectly formatted floating point: " + e.Message); + n = BigFloat.ZERO; + } + + } + void BvLit(out BigNum n, out int m) { Expect(2); int pos = t.val.IndexOf("bv"); @@ -1871,11 +1889,11 @@ out List/*!*/ ins, out List/*!*/ outs, out QKeyValue kv) { } void Forall() { - if (la.kind == 88) { + if (la.kind == 89) { Get(); - } else if (la.kind == 89) { + } else if (la.kind == 90) { Get(); - } else SynErr(127); + } else SynErr(128); } void QuantifierBody(IToken/*!*/ q, out List/*!*/ typeParams, out List/*!*/ ds, @@ -1886,35 +1904,35 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { kv = null; ds = new List (); - if (la.kind == 19) { + if (la.kind == 20) { TypeParams(out tok, out typeParams); - if (la.kind == 1 || la.kind == 27) { + if (la.kind == 1 || la.kind == 28) { BoundVars(q, out ds); } - } else if (la.kind == 1 || la.kind == 27) { + } else if (la.kind == 1 || la.kind == 28) { BoundVars(q, out ds); - } else SynErr(128); + } else SynErr(129); QSep(); - while (la.kind == 27) { + while (la.kind == 28) { AttributeOrTrigger(ref kv, ref trig); } Expression(out body); } void Exists() { - if (la.kind == 90) { + if (la.kind == 91) { Get(); - } else if (la.kind == 91) { + } else if (la.kind == 92) { Get(); - } else SynErr(129); + } else SynErr(130); } void Lambda() { - if (la.kind == 92) { + if (la.kind == 93) { Get(); - } else if (la.kind == 93) { + } else if (la.kind == 94) { Get(); - } else SynErr(130); + } else SynErr(131); } void IfThenElseExpression(out Expr/*!*/ e) { @@ -1922,12 +1940,12 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { IToken/*!*/ tok; Expr/*!*/ e0, e1, e2; e = dummyExpr; - Expect(40); + Expect(41); tok = t; Expression(out e0); - Expect(87); + Expect(88); Expression(out e1); - Expect(41); + Expect(42); Expression(out e2); e = new NAryExpr(tok, new IfThenElse(tok), new List{ e0, e1, e2 }); } @@ -1936,8 +1954,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { Contract.Ensures(Contract.ValueAtReturn(out locals) != null); Contract.Ensures(cce.NonNullElements(Contract.ValueAtReturn(out blocks))); locals = new List(); Block/*!*/ b; blocks = new List(); - Expect(85); - while (la.kind == 7) { + Expect(86); + while (la.kind == 8) { LocalVars(locals); } SpecBlock(out b); @@ -1946,7 +1964,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { SpecBlock(out b); blocks.Add(b); } - Expect(86); + Expect(87); } void SpecBlock(out Block/*!*/ b) { @@ -1959,7 +1977,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { Expr/*!*/ e; Ident(out x); - Expect(11); + Expect(12); while (StartOf(8)) { LabelOrCmd(out c, out label); if (c != null) { @@ -1971,7 +1989,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { } } - if (la.kind == 38) { + if (la.kind == 39) { Get(); y = t; Idents(out xs); @@ -1980,12 +1998,12 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { ss.Add(s.val); } b = new Block(x,x.val,cs,new GotoCmd(y,ss)); - } else if (la.kind == 39) { + } else if (la.kind == 40) { Get(); Expression(out e); b = new Block(x,x.val,cs,new ReturnExprCmd(t,e)); - } else SynErr(131); - Expect(8); + } else SynErr(132); + Expect(9); } void AttributeOrTrigger(ref QKeyValue kv, ref Trigger trig) { @@ -1993,16 +2011,16 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { string key; List parameters; object/*!*/ param; - Expect(27); + Expect(28); tok = t; - if (la.kind == 11) { + if (la.kind == 12) { Get(); Expect(1); key = t.val; parameters = new List(); if (StartOf(16)) { AttributeParameter(out param); parameters.Add(param); - while (la.kind == 12) { + while (la.kind == 13) { Get(); AttributeParameter(out param); parameters.Add(param); @@ -2030,7 +2048,7 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { } else if (StartOf(9)) { Expression(out e); es = new List { e }; - while (la.kind == 12) { + while (la.kind == 13) { Get(); Expression(out e); es.Add(e); @@ -2041,8 +2059,8 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { trig.AddLast(new Trigger(tok, true, es, null)); } - } else SynErr(132); - Expect(28); + } else SynErr(133); + Expect(29); } void AttributeParameter(out object/*!*/ o) { @@ -2056,15 +2074,15 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { } else if (StartOf(9)) { Expression(out e); o = e; - } else SynErr(133); + } else SynErr(134); } void QSep() { - if (la.kind == 94) { + if (la.kind == 95) { Get(); - } else if (la.kind == 95) { + } else if (la.kind == 96) { Get(); - } else SynErr(134); + } else SynErr(135); } @@ -2080,23 +2098,23 @@ out QKeyValue kv, out Trigger trig, out Expr/*!*/ body) { } static readonly bool[,]/*!*/ set = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,T,x,x, x,T,T,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,x,x, x,x,x,x, x,T,x,x, x,x,T,T, T,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,T, T,x,T,x, x,T,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,T,T, x,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,T,T, T,T,T,x, x,T,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x} + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,T,T, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,T,T,x, T,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,T,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, T,T,x,T, x,x,T,T, T,T,T,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, x,T,T,T, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, x,T,T,T, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, x,T,T,T, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x}, + {x,T,T,T, T,T,T,T, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x} }; } // end Parser @@ -2127,135 +2145,136 @@ public class Errors { case 3: s = "digits expected"; break; case 4: s = "string expected"; break; case 5: s = "decimal expected"; break; - case 6: s = "float expected"; break; - case 7: s = "\"var\" expected"; break; - case 8: s = "\";\" expected"; break; - case 9: s = "\"(\" expected"; break; - case 10: s = "\")\" expected"; break; - case 11: s = "\":\" expected"; break; - case 12: s = "\",\" expected"; break; - case 13: s = "\"where\" expected"; break; - case 14: s = "\"int\" expected"; break; - case 15: s = "\"real\" expected"; break; - case 16: s = "\"bool\" expected"; break; - case 17: s = "\"[\" expected"; break; - case 18: s = "\"]\" expected"; break; - case 19: s = "\"<\" expected"; break; - case 20: s = "\">\" expected"; break; - case 21: s = "\"const\" expected"; break; - case 22: s = "\"unique\" expected"; break; - case 23: s = "\"extends\" expected"; break; - case 24: s = "\"complete\" expected"; break; - case 25: s = "\"function\" expected"; break; - case 26: s = "\"returns\" expected"; break; - case 27: s = "\"{\" expected"; break; - case 28: s = "\"}\" expected"; break; - case 29: s = "\"axiom\" expected"; break; - case 30: s = "\"type\" expected"; break; - case 31: s = "\"=\" expected"; break; - case 32: s = "\"procedure\" expected"; break; - case 33: s = "\"implementation\" expected"; break; - case 34: s = "\"modifies\" expected"; break; - case 35: s = "\"free\" expected"; break; - case 36: s = "\"requires\" expected"; break; - case 37: s = "\"ensures\" expected"; break; - case 38: s = "\"goto\" expected"; break; - case 39: s = "\"return\" expected"; break; - case 40: s = "\"if\" expected"; break; - case 41: s = "\"else\" expected"; break; - case 42: s = "\"while\" expected"; break; - case 43: s = "\"invariant\" expected"; break; - case 44: s = "\"*\" expected"; break; - case 45: s = "\"break\" expected"; break; - case 46: s = "\"assert\" expected"; break; - case 47: s = "\"assume\" expected"; break; - case 48: s = "\"havoc\" expected"; break; - case 49: s = "\"yield\" expected"; break; - case 50: s = "\":=\" expected"; break; - case 51: s = "\"async\" expected"; break; - case 52: s = "\"call\" expected"; break; - case 53: s = "\"par\" expected"; break; - case 54: s = "\"|\" expected"; break; - case 55: s = "\"<==>\" expected"; break; - case 56: s = "\"\\u21d4\" expected"; break; - case 57: s = "\"==>\" expected"; break; - case 58: s = "\"\\u21d2\" expected"; break; - case 59: s = "\"<==\" expected"; break; - case 60: s = "\"\\u21d0\" expected"; break; - case 61: s = "\"&&\" expected"; break; - case 62: s = "\"\\u2227\" expected"; break; - case 63: s = "\"||\" expected"; break; - case 64: s = "\"\\u2228\" expected"; break; - case 65: s = "\"==\" expected"; break; - case 66: s = "\"<=\" expected"; break; - case 67: s = "\">=\" expected"; break; - case 68: s = "\"!=\" expected"; break; - case 69: s = "\"<:\" expected"; break; - case 70: s = "\"\\u2260\" expected"; break; - case 71: s = "\"\\u2264\" expected"; break; - case 72: s = "\"\\u2265\" expected"; break; - case 73: s = "\"++\" expected"; break; - case 74: s = "\"+\" expected"; break; - case 75: s = "\"-\" expected"; break; - case 76: s = "\"div\" expected"; break; - case 77: s = "\"mod\" expected"; break; - case 78: s = "\"/\" expected"; break; - case 79: s = "\"**\" expected"; break; - case 80: s = "\"!\" expected"; break; - case 81: s = "\"\\u00ac\" expected"; break; - case 82: s = "\"false\" expected"; break; - case 83: s = "\"true\" expected"; break; - case 84: s = "\"old\" expected"; break; - case 85: s = "\"|{\" expected"; break; - case 86: s = "\"}|\" expected"; break; - case 87: s = "\"then\" expected"; break; - case 88: s = "\"forall\" expected"; break; - case 89: s = "\"\\u2200\" expected"; break; - case 90: s = "\"exists\" expected"; break; - case 91: s = "\"\\u2203\" expected"; break; - case 92: s = "\"lambda\" expected"; break; - case 93: s = "\"\\u03bb\" expected"; break; - case 94: s = "\"::\" expected"; break; - case 95: s = "\"\\u2022\" expected"; break; - case 96: s = "??? expected"; break; - case 97: s = "invalid Function"; break; + case 6: s = "dec_float expected"; break; + case 7: s = "float expected"; break; + case 8: s = "\"var\" expected"; break; + case 9: s = "\";\" expected"; break; + case 10: s = "\"(\" expected"; break; + case 11: s = "\")\" expected"; break; + case 12: s = "\":\" expected"; break; + case 13: s = "\",\" expected"; break; + case 14: s = "\"where\" expected"; break; + case 15: s = "\"int\" expected"; break; + case 16: s = "\"real\" expected"; break; + case 17: s = "\"bool\" expected"; break; + case 18: s = "\"[\" expected"; break; + case 19: s = "\"]\" expected"; break; + case 20: s = "\"<\" expected"; break; + case 21: s = "\">\" expected"; break; + case 22: s = "\"const\" expected"; break; + case 23: s = "\"unique\" expected"; break; + case 24: s = "\"extends\" expected"; break; + case 25: s = "\"complete\" expected"; break; + case 26: s = "\"function\" expected"; break; + case 27: s = "\"returns\" expected"; break; + case 28: s = "\"{\" expected"; break; + case 29: s = "\"}\" expected"; break; + case 30: s = "\"axiom\" expected"; break; + case 31: s = "\"type\" expected"; break; + case 32: s = "\"=\" expected"; break; + case 33: s = "\"procedure\" expected"; break; + case 34: s = "\"implementation\" expected"; break; + case 35: s = "\"modifies\" expected"; break; + case 36: s = "\"free\" expected"; break; + case 37: s = "\"requires\" expected"; break; + case 38: s = "\"ensures\" expected"; break; + case 39: s = "\"goto\" expected"; break; + case 40: s = "\"return\" expected"; break; + case 41: s = "\"if\" expected"; break; + case 42: s = "\"else\" expected"; break; + case 43: s = "\"while\" expected"; break; + case 44: s = "\"invariant\" expected"; break; + case 45: s = "\"*\" expected"; break; + case 46: s = "\"break\" expected"; break; + case 47: s = "\"assert\" expected"; break; + case 48: s = "\"assume\" expected"; break; + case 49: s = "\"havoc\" expected"; break; + case 50: s = "\"yield\" expected"; break; + case 51: s = "\":=\" expected"; break; + case 52: s = "\"async\" expected"; break; + case 53: s = "\"call\" expected"; break; + case 54: s = "\"par\" expected"; break; + case 55: s = "\"|\" expected"; break; + case 56: s = "\"<==>\" expected"; break; + case 57: s = "\"\\u21d4\" expected"; break; + case 58: s = "\"==>\" expected"; break; + case 59: s = "\"\\u21d2\" expected"; break; + case 60: s = "\"<==\" expected"; break; + case 61: s = "\"\\u21d0\" expected"; break; + case 62: s = "\"&&\" expected"; break; + case 63: s = "\"\\u2227\" expected"; break; + case 64: s = "\"||\" expected"; break; + case 65: s = "\"\\u2228\" expected"; break; + case 66: s = "\"==\" expected"; break; + case 67: s = "\"<=\" expected"; break; + case 68: s = "\">=\" expected"; break; + case 69: s = "\"!=\" expected"; break; + case 70: s = "\"<:\" expected"; break; + case 71: s = "\"\\u2260\" expected"; break; + case 72: s = "\"\\u2264\" expected"; break; + case 73: s = "\"\\u2265\" expected"; break; + case 74: s = "\"++\" expected"; break; + case 75: s = "\"+\" expected"; break; + case 76: s = "\"-\" expected"; break; + case 77: s = "\"div\" expected"; break; + case 78: s = "\"mod\" expected"; break; + case 79: s = "\"/\" expected"; break; + case 80: s = "\"**\" expected"; break; + case 81: s = "\"!\" expected"; break; + case 82: s = "\"\\u00ac\" expected"; break; + case 83: s = "\"false\" expected"; break; + case 84: s = "\"true\" expected"; break; + case 85: s = "\"old\" expected"; break; + case 86: s = "\"|{\" expected"; break; + case 87: s = "\"}|\" expected"; break; + case 88: s = "\"then\" expected"; break; + case 89: s = "\"forall\" expected"; break; + case 90: s = "\"\\u2200\" expected"; break; + case 91: s = "\"exists\" expected"; break; + case 92: s = "\"\\u2203\" expected"; break; + case 93: s = "\"lambda\" expected"; break; + case 94: s = "\"\\u03bb\" expected"; break; + case 95: s = "\"::\" expected"; break; + case 96: s = "\"\\u2022\" expected"; break; + case 97: s = "??? expected"; break; case 98: s = "invalid Function"; break; - case 99: s = "invalid Procedure"; break; - case 100: s = "invalid Type"; break; - case 101: s = "invalid TypeAtom"; break; - case 102: s = "invalid TypeArgs"; break; - case 103: s = "invalid Spec"; break; - case 104: s = "invalid SpecPrePost"; break; - case 105: s = "invalid LabelOrCmd"; break; - case 106: s = "invalid StructuredCmd"; break; - case 107: s = "invalid TransferCmd"; break; - case 108: s = "invalid IfCmd"; break; - case 109: s = "invalid Guard"; break; - case 110: s = "invalid LabelOrAssign"; break; - case 111: s = "invalid CallParams"; break; - case 112: s = "invalid EquivOp"; break; - case 113: s = "invalid ImpliesOp"; break; - case 114: s = "invalid ExpliesOp"; break; - case 115: s = "invalid AndOp"; break; - case 116: s = "invalid OrOp"; break; - case 117: s = "invalid RelOp"; break; - case 118: s = "invalid AddOp"; break; - case 119: s = "invalid MulOp"; break; - case 120: s = "invalid UnaryExpression"; break; - case 121: s = "invalid NegOp"; break; - case 122: s = "invalid CoercionExpression"; break; - case 123: s = "invalid AtomExpression"; break; + case 99: s = "invalid Function"; break; + case 100: s = "invalid Procedure"; break; + case 101: s = "invalid Type"; break; + case 102: s = "invalid TypeAtom"; break; + case 103: s = "invalid TypeArgs"; break; + case 104: s = "invalid Spec"; break; + case 105: s = "invalid SpecPrePost"; break; + case 106: s = "invalid LabelOrCmd"; break; + case 107: s = "invalid StructuredCmd"; break; + case 108: s = "invalid TransferCmd"; break; + case 109: s = "invalid IfCmd"; break; + case 110: s = "invalid Guard"; break; + case 111: s = "invalid LabelOrAssign"; break; + case 112: s = "invalid CallParams"; break; + case 113: s = "invalid EquivOp"; break; + case 114: s = "invalid ImpliesOp"; break; + case 115: s = "invalid ExpliesOp"; break; + case 116: s = "invalid AndOp"; break; + case 117: s = "invalid OrOp"; break; + case 118: s = "invalid RelOp"; break; + case 119: s = "invalid AddOp"; break; + case 120: s = "invalid MulOp"; break; + case 121: s = "invalid UnaryExpression"; break; + case 122: s = "invalid NegOp"; break; + case 123: s = "invalid CoercionExpression"; break; case 124: s = "invalid AtomExpression"; break; case 125: s = "invalid AtomExpression"; break; - case 126: s = "invalid Dec"; break; - case 127: s = "invalid Forall"; break; - case 128: s = "invalid QuantifierBody"; break; - case 129: s = "invalid Exists"; break; - case 130: s = "invalid Lambda"; break; - case 131: s = "invalid SpecBlock"; break; - case 132: s = "invalid AttributeOrTrigger"; break; - case 133: s = "invalid AttributeParameter"; break; - case 134: s = "invalid QSep"; break; + case 126: s = "invalid AtomExpression"; break; + case 127: s = "invalid Dec"; break; + case 128: s = "invalid Forall"; break; + case 129: s = "invalid QuantifierBody"; break; + case 130: s = "invalid Exists"; break; + case 131: s = "invalid Lambda"; break; + case 132: s = "invalid SpecBlock"; break; + case 133: s = "invalid AttributeOrTrigger"; break; + case 134: s = "invalid AttributeParameter"; break; + case 135: s = "invalid QSep"; break; default: s = "error " + n; break; } diff --git a/Source/Core/Scanner.cs b/Source/Core/Scanner.cs index e068fc4b..1185963f 100644 --- a/Source/Core/Scanner.cs +++ b/Source/Core/Scanner.cs @@ -211,8 +211,8 @@ public class UTF8Buffer: Buffer { public class Scanner { const char EOL = '\n'; const int eofSym = 0; /* pdt */ - const int maxT = 96; - const int noSym = 96; + const int maxT = 97; + const int noSym = 97; [ContractInvariantMethod] @@ -267,41 +267,41 @@ public class Scanner { for (int i = 65; i <= 90; ++i) start[i] = 2; for (int i = 94; i <= 122; ++i) start[i] = 2; for (int i = 126; i <= 126; ++i) start[i] = 2; - for (int i = 48; i <= 57; ++i) start[i] = 16; + for (int i = 48; i <= 57; ++i) start[i] = 19; for (int i = 34; i <= 34; ++i) start[i] = 6; start[92] = 1; - start[59] = 19; - start[40] = 20; - start[41] = 21; - start[58] = 55; - start[44] = 22; - start[91] = 23; - start[93] = 24; - start[60] = 56; - start[62] = 57; - start[123] = 25; - start[125] = 58; - start[61] = 59; - start[42] = 60; - start[124] = 61; - start[8660] = 28; - start[8658] = 30; - start[8656] = 31; - start[38] = 32; - start[8743] = 34; - start[8744] = 36; - start[33] = 62; - start[8800] = 40; - start[8804] = 41; - start[8805] = 42; - start[43] = 63; - start[45] = 44; - start[47] = 45; - start[172] = 47; - start[8704] = 50; - start[8707] = 51; - start[955] = 52; - start[8226] = 54; + start[59] = 24; + start[40] = 25; + start[41] = 26; + start[58] = 60; + start[44] = 27; + start[91] = 28; + start[93] = 29; + start[60] = 61; + start[62] = 62; + start[123] = 30; + start[125] = 63; + start[61] = 64; + start[42] = 65; + start[124] = 66; + start[8660] = 33; + start[8658] = 35; + start[8656] = 36; + start[38] = 37; + start[8743] = 39; + start[8744] = 41; + start[33] = 67; + start[8800] = 45; + start[8804] = 46; + start[8805] = 47; + start[43] = 68; + start[45] = 49; + start[47] = 50; + start[172] = 52; + start[8704] = 55; + start[8707] = 56; + start[955] = 57; + start[8226] = 59; start[Buffer.EOF] = -1; } @@ -503,48 +503,48 @@ public class Scanner { void CheckLiteral() { switch (t.val) { - case "var": t.kind = 7; break; - case "where": t.kind = 13; break; - case "int": t.kind = 14; break; - case "real": t.kind = 15; break; - case "bool": t.kind = 16; break; - case "const": t.kind = 21; break; - case "unique": t.kind = 22; break; - case "extends": t.kind = 23; break; - case "complete": t.kind = 24; break; - case "function": t.kind = 25; break; - case "returns": t.kind = 26; break; - case "axiom": t.kind = 29; break; - case "type": t.kind = 30; break; - case "procedure": t.kind = 32; break; - case "implementation": t.kind = 33; break; - case "modifies": t.kind = 34; break; - case "free": t.kind = 35; break; - case "requires": t.kind = 36; break; - case "ensures": t.kind = 37; break; - case "goto": t.kind = 38; break; - case "return": t.kind = 39; break; - case "if": t.kind = 40; break; - case "else": t.kind = 41; break; - case "while": t.kind = 42; break; - case "invariant": t.kind = 43; break; - case "break": t.kind = 45; break; - case "assert": t.kind = 46; break; - case "assume": t.kind = 47; break; - case "havoc": t.kind = 48; break; - case "yield": t.kind = 49; break; - case "async": t.kind = 51; break; - case "call": t.kind = 52; break; - case "par": t.kind = 53; break; - case "div": t.kind = 76; break; - case "mod": t.kind = 77; break; - case "false": t.kind = 82; break; - case "true": t.kind = 83; break; - case "old": t.kind = 84; break; - case "then": t.kind = 87; break; - case "forall": t.kind = 88; break; - case "exists": t.kind = 90; break; - case "lambda": t.kind = 92; break; + case "var": t.kind = 8; break; + case "where": t.kind = 14; break; + case "int": t.kind = 15; break; + case "real": t.kind = 16; break; + case "bool": t.kind = 17; break; + case "const": t.kind = 22; break; + case "unique": t.kind = 23; break; + case "extends": t.kind = 24; break; + case "complete": t.kind = 25; break; + case "function": t.kind = 26; break; + case "returns": t.kind = 27; break; + case "axiom": t.kind = 30; break; + case "type": t.kind = 31; break; + case "procedure": t.kind = 33; break; + case "implementation": t.kind = 34; break; + case "modifies": t.kind = 35; break; + case "free": t.kind = 36; break; + case "requires": t.kind = 37; break; + case "ensures": t.kind = 38; break; + case "goto": t.kind = 39; break; + case "return": t.kind = 40; break; + case "if": t.kind = 41; break; + case "else": t.kind = 42; break; + case "while": t.kind = 43; break; + case "invariant": t.kind = 44; break; + case "break": t.kind = 46; break; + case "assert": t.kind = 47; break; + case "assume": t.kind = 48; break; + case "havoc": t.kind = 49; break; + case "yield": t.kind = 50; break; + case "async": t.kind = 52; break; + case "call": t.kind = 53; break; + case "par": t.kind = 54; break; + case "div": t.kind = 77; break; + case "mod": t.kind = 78; break; + case "false": t.kind = 83; break; + case "true": t.kind = 84; break; + case "old": t.kind = 85; break; + case "then": t.kind = 88; break; + case "forall": t.kind = 89; break; + case "exists": t.kind = 91; break; + case "lambda": t.kind = 93; break; default: break; } } @@ -597,182 +597,201 @@ public class Scanner { case 6: if (ch == '"') {AddCh(); goto case 7;} else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;} - else if (ch == 92) {AddCh(); goto case 17;} + else if (ch == 92) {AddCh(); goto case 20;} else {goto case 0;} case 7: {t.kind = 4; break;} case 8: - if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;} - else if (ch == '-') {AddCh(); goto case 9;} + if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;} else {goto case 0;} case 9: - if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;} - else {goto case 0;} - case 10: recEnd = pos; recKind = 5; - if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;} + if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;} else {t.kind = 5; break;} - case 11: - if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;} + case 10: + if (ch >= '0' && ch <= '9') {AddCh(); goto case 11;} else {goto case 0;} - case 12: + case 11: recEnd = pos; recKind = 6; - if (ch >= '0' && ch <= '9') {AddCh(); goto case 12;} - else if (ch == 'e') {AddCh(); goto case 13;} + if (ch >= '0' && ch <= '9') {AddCh(); goto case 11;} + else if (ch == 'e') {AddCh(); goto case 12;} else {t.kind = 6; break;} + case 12: + if (ch >= '0' && ch <= '9') {AddCh(); goto case 14;} + else if (ch == '-') {AddCh(); goto case 13;} + else {goto case 0;} case 13: - if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;} - else if (ch == '-') {AddCh(); goto case 14;} + if (ch >= '0' && ch <= '9') {AddCh(); goto case 14;} else {goto case 0;} case 14: - if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;} - else {goto case 0;} - case 15: recEnd = pos; recKind = 6; - if (ch >= '0' && ch <= '9') {AddCh(); goto case 15;} + if (ch >= '0' && ch <= '9') {AddCh(); goto case 14;} else {t.kind = 6; break;} + case 15: + if (ch >= '0' && ch <= '9') {AddCh(); goto case 16;} + else {goto case 0;} case 16: - recEnd = pos; recKind = 3; if (ch >= '0' && ch <= '9') {AddCh(); goto case 16;} + else if (ch == 'e') {AddCh(); goto case 17;} + else {goto case 0;} + case 17: + if (ch >= '0' && ch <= '9') {AddCh(); goto case 18;} + else {goto case 0;} + case 18: + recEnd = pos; recKind = 7; + if (ch >= '0' && ch <= '9') {AddCh(); goto case 18;} + else {t.kind = 7; break;} + case 19: + recEnd = pos; recKind = 3; + if (ch >= '0' && ch <= '9') {AddCh(); goto case 19;} else if (ch == 'b') {AddCh(); goto case 3;} - else if (ch == 'e') {AddCh(); goto case 8;} - else if (ch == '.') {AddCh(); goto case 11;} + else if (ch == 'e') {AddCh(); goto case 21;} + else if (ch == '.') {AddCh(); goto case 10;} else {t.kind = 3; break;} - case 17: - if (ch == '"') {AddCh(); goto case 18;} + case 20: + if (ch == '"') {AddCh(); goto case 22;} else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;} - else if (ch == 92) {AddCh(); goto case 17;} + else if (ch == 92) {AddCh(); goto case 20;} else {goto case 0;} - case 18: + case 21: + if (ch >= '0' && ch <= '9') {AddCh(); goto case 23;} + else if (ch == '-') {AddCh(); goto case 8;} + else {goto case 0;} + case 22: recEnd = pos; recKind = 4; if (ch == '"') {AddCh(); goto case 7;} else if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); goto case 6;} - else if (ch == 92) {AddCh(); goto case 17;} + else if (ch == 92) {AddCh(); goto case 20;} else {t.kind = 4; break;} - case 19: - {t.kind = 8; break;} - case 20: - {t.kind = 9; break;} - case 21: - {t.kind = 10; break;} - case 22: - {t.kind = 12; break;} case 23: - {t.kind = 17; break;} + recEnd = pos; recKind = 5; + if (ch >= '0' && ch <= '9') {AddCh(); goto case 23;} + else if (ch == 'f') {AddCh(); goto case 15;} + else {t.kind = 5; break;} case 24: - {t.kind = 18; break;} + {t.kind = 9; break;} case 25: - {t.kind = 27; break;} + {t.kind = 10; break;} case 26: - {t.kind = 50; break;} + {t.kind = 11; break;} case 27: - {t.kind = 55; break;} + {t.kind = 13; break;} case 28: - {t.kind = 56; break;} + {t.kind = 18; break;} case 29: - {t.kind = 57; break;} + {t.kind = 19; break;} case 30: - {t.kind = 58; break;} + {t.kind = 28; break;} case 31: - {t.kind = 60; break;} + {t.kind = 51; break;} case 32: - if (ch == '&') {AddCh(); goto case 33;} - else {goto case 0;} + {t.kind = 56; break;} case 33: - {t.kind = 61; break;} + {t.kind = 57; break;} case 34: - {t.kind = 62; break;} + {t.kind = 58; break;} case 35: - {t.kind = 63; break;} + {t.kind = 59; break;} case 36: - {t.kind = 64; break;} + {t.kind = 61; break;} case 37: - {t.kind = 67; break;} + if (ch == '&') {AddCh(); goto case 38;} + else {goto case 0;} case 38: - {t.kind = 68; break;} + {t.kind = 62; break;} case 39: - {t.kind = 69; break;} + {t.kind = 63; break;} case 40: - {t.kind = 70; break;} + {t.kind = 64; break;} case 41: - {t.kind = 71; break;} + {t.kind = 65; break;} case 42: - {t.kind = 72; break;} + {t.kind = 68; break;} case 43: - {t.kind = 73; break;} + {t.kind = 69; break;} case 44: - {t.kind = 75; break;} + {t.kind = 70; break;} case 45: - {t.kind = 78; break;} + {t.kind = 71; break;} case 46: - {t.kind = 79; break;} + {t.kind = 72; break;} case 47: - {t.kind = 81; break;} + {t.kind = 73; break;} case 48: - {t.kind = 85; break;} + {t.kind = 74; break;} case 49: - {t.kind = 86; break;} + {t.kind = 76; break;} case 50: - {t.kind = 89; break;} + {t.kind = 79; break;} case 51: - {t.kind = 91; break;} + {t.kind = 80; break;} case 52: - {t.kind = 93; break;} + {t.kind = 82; break;} case 53: - {t.kind = 94; break;} + {t.kind = 86; break;} case 54: - {t.kind = 95; break;} + {t.kind = 87; break;} case 55: - recEnd = pos; recKind = 11; - if (ch == '=') {AddCh(); goto case 26;} - else if (ch == ':') {AddCh(); goto case 53;} - else {t.kind = 11; break;} + {t.kind = 90; break;} case 56: - recEnd = pos; recKind = 19; - if (ch == '=') {AddCh(); goto case 64;} - else if (ch == ':') {AddCh(); goto case 39;} - else {t.kind = 19; break;} + {t.kind = 92; break;} case 57: - recEnd = pos; recKind = 20; - if (ch == '=') {AddCh(); goto case 37;} - else {t.kind = 20; break;} + {t.kind = 94; break;} case 58: - recEnd = pos; recKind = 28; - if (ch == '|') {AddCh(); goto case 49;} - else {t.kind = 28; break;} + {t.kind = 95; break;} case 59: - recEnd = pos; recKind = 31; - if (ch == '=') {AddCh(); goto case 65;} - else {t.kind = 31; break;} + {t.kind = 96; break;} case 60: - recEnd = pos; recKind = 44; - if (ch == '*') {AddCh(); goto case 46;} - else {t.kind = 44; break;} + recEnd = pos; recKind = 12; + if (ch == '=') {AddCh(); goto case 31;} + else if (ch == ':') {AddCh(); goto case 58;} + else {t.kind = 12; break;} case 61: - recEnd = pos; recKind = 54; - if (ch == '|') {AddCh(); goto case 35;} - else if (ch == '{') {AddCh(); goto case 48;} - else {t.kind = 54; break;} + recEnd = pos; recKind = 20; + if (ch == '=') {AddCh(); goto case 69;} + else if (ch == ':') {AddCh(); goto case 44;} + else {t.kind = 20; break;} case 62: - recEnd = pos; recKind = 80; - if (ch == '=') {AddCh(); goto case 38;} - else {t.kind = 80; break;} + recEnd = pos; recKind = 21; + if (ch == '=') {AddCh(); goto case 42;} + else {t.kind = 21; break;} case 63: - recEnd = pos; recKind = 74; - if (ch == '+') {AddCh(); goto case 43;} - else {t.kind = 74; break;} + recEnd = pos; recKind = 29; + if (ch == '|') {AddCh(); goto case 54;} + else {t.kind = 29; break;} case 64: - recEnd = pos; recKind = 66; - if (ch == '=') {AddCh(); goto case 66;} - else {t.kind = 66; break;} + recEnd = pos; recKind = 32; + if (ch == '=') {AddCh(); goto case 70;} + else {t.kind = 32; break;} case 65: - recEnd = pos; recKind = 65; - if (ch == '>') {AddCh(); goto case 29;} - else {t.kind = 65; break;} + recEnd = pos; recKind = 45; + if (ch == '*') {AddCh(); goto case 51;} + else {t.kind = 45; break;} case 66: - recEnd = pos; recKind = 59; - if (ch == '>') {AddCh(); goto case 27;} - else {t.kind = 59; break;} + recEnd = pos; recKind = 55; + if (ch == '|') {AddCh(); goto case 40;} + else if (ch == '{') {AddCh(); goto case 53;} + else {t.kind = 55; break;} + case 67: + recEnd = pos; recKind = 81; + if (ch == '=') {AddCh(); goto case 43;} + else {t.kind = 81; break;} + case 68: + recEnd = pos; recKind = 75; + if (ch == '+') {AddCh(); goto case 48;} + else {t.kind = 75; break;} + case 69: + recEnd = pos; recKind = 67; + if (ch == '=') {AddCh(); goto case 71;} + else {t.kind = 67; break;} + case 70: + recEnd = pos; recKind = 66; + if (ch == '>') {AddCh(); goto case 34;} + else {t.kind = 66; break;} + case 71: + recEnd = pos; recKind = 60; + if (ch == '>') {AddCh(); goto case 32;} + else {t.kind = 60; break;} } t.val = new String(tval, 0, tlen); diff --git a/Test/floats/float0.bpl b/Test/floats/float0.bpl index 1a642835..d7faa4b0 100644 --- a/Test/floats/float0.bpl +++ b/Test/floats/float0.bpl @@ -4,11 +4,11 @@ procedure foo(x : real) returns (r : float8e24) { r := 15; // Error r := 15.0; // Error - r := fp(false, 1bv8, 0bv22); // Error - r := fp<8, 23>(1bv31); // Error + r := 0e1f22e8; // Error + r := 1e0f23e8; // Error r := x; // Error - r := fp<8, 23>(1bv31) + fp<8, 23>(1bv31); // Error - r := fp<8, 24>(1bv32) + fp<8, 23>(1bv31); // Error + r := 1e0f23e8 + 1e0f23e8; // Error + r := 1e0f24e8 + 1e0f23e8; // Error return; } \ No newline at end of file diff --git a/Test/floats/float1.bpl b/Test/floats/float1.bpl index 9ed62579..2b901c94 100644 --- a/Test/floats/float1.bpl +++ b/Test/floats/float1.bpl @@ -1,13 +1,13 @@ -// RUN: %boogie -proverWarnings:1 "%s" > "%t" -// RUN: %diff "%s.expect" "%t" -procedure foo(x : float<8, 24>) returns (r : float<8, 24>) -{ - r := fp(false, 1bv8, 0bv23); - r := fp<8, 24>(1bv32); - r := x; - r := x + fp<8, 24>(1bv32); - r := fp<8, 24>(1bv32) + fp<8, 24>(1bv32); - assert(r == fp<8, 24>(2bv32)); - - return; +// RUN: %boogie -proverWarnings:1 "%s" > "%t" +// RUN: %diff "%s.expect" "%t" +procedure foo(x : float24e8) returns (r : float24e8) +{ + r := 0e1f24e8; + r := 1e0f24e8; + r := x; + r := x + 1e0f24e8; + r := 0e0f24e8 + 0e0f24e8; + assert(r == 0e1f24e8); + + return; } \ No newline at end of file -- cgit v1.2.3 From 6bf5043aeab0430325c4ccde3e6ca3bd82d96704 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Tue, 19 Jul 2016 11:56:01 -0600 Subject: fixed floatceiling function --- Source/Basetypes/BigFloat.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 5f711e70..3816a22d 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -314,14 +314,15 @@ namespace Microsoft.Basetypes BIM two = new BIM(2); BIM sig = Significand + BIM.Pow(two, SignificandSize); //Add hidden bit - BIM exp = Exponent - BIM.Pow(two, ExponentSize); - sig = sig >> ExponentSize; + BIM exp = Exponent - BIM.Pow(two, ExponentSize-1) + 1; while (exp > BIM.Zero) { exp--; - sig = sig >> 1; + sig = sig << 1; } + sig = sig >> SignificandSize; + if (isNeg) { ceiling = -sig + 1; floor = -sig; -- cgit v1.2.3 From 07c34b257ba84db8ec26cba283aae74f87087181 Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Fri, 22 Jul 2016 10:29:55 -0600 Subject: Removed automatic exponent shifting --- Source/Basetypes/BigFloat.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index 3816a22d..d27a3b00 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -151,7 +151,8 @@ namespace Microsoft.Basetypes sigSize = sigSize - 1; //Get rid of sign bit isNeg = sig < 0; sig = BIM.Abs(sig); - exp = exp + BIM.Pow(new BIM(2), expSize-1) - BIM.One; + //Uncomment if you want to shift the exponent for the user (i.e. 0e-1f24e8 --> 0e126f24e8) + //exp = exp + BIM.Pow(new BIM(2), expSize-1) - BIM.One; if (exp < 0 || exp >= BIM.Pow(new BIM(2), expSize)) throw new FormatException("The given exponent " + exp + " cannot fit in the bit size " + expSize); -- cgit v1.2.3 From 2b64144fb02b68d00188ee81c27afa5fbc026b5b Mon Sep 17 00:00:00 2001 From: Checkmate50 Date: Sat, 23 Jul 2016 14:27:23 -0600 Subject: fixed an error where a -0 was not interpreted as a negative number --- Source/Basetypes/BigFloat.cs | 4 ++-- Test/floats/float13.bpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Basetypes/BigFloat.cs') diff --git a/Source/Basetypes/BigFloat.cs b/Source/Basetypes/BigFloat.cs index d27a3b00..cb248340 100644 --- a/Source/Basetypes/BigFloat.cs +++ b/Source/Basetypes/BigFloat.cs @@ -144,13 +144,13 @@ namespace Microsoft.Basetypes exp = BIM.Parse(s.Substring(s.IndexOf('e') + 1, s.IndexOf('f') - s.IndexOf('e') - 1)); sigSize = int.Parse(s.Substring(s.IndexOf('f') + 1, s.IndexOf('e', s.IndexOf('e') + 1) - s.IndexOf('f') - 1)); expSize = int.Parse(s.Substring(s.IndexOf('e', s.IndexOf('e') + 1) + 1)); + isNeg = s[0] == '-'; //We do this so that -0 is parsed correctly if (sigSize <= 0 || expSize <= 0) throw new FormatException("Significand and Exponent sizes must be greater than 0"); sigSize = sigSize - 1; //Get rid of sign bit - isNeg = sig < 0; - sig = BIM.Abs(sig); + sig = BIM.Abs(sig); //sig must be positive //Uncomment if you want to shift the exponent for the user (i.e. 0e-1f24e8 --> 0e126f24e8) //exp = exp + BIM.Pow(new BIM(2), expSize-1) - BIM.One; diff --git a/Test/floats/float13.bpl b/Test/floats/float13.bpl index 4aab608a..9c99a30b 100644 --- a/Test/floats/float13.bpl +++ b/Test/floats/float13.bpl @@ -17,7 +17,7 @@ procedure main() returns () { assert(f == fc); f := -0e126f24e8; - fc := TO_FLOAT32_REAL(0.5); + fc := TO_FLOAT32_REAL(-0.5); assert(f == fc); f := 1048576e128f24e8; -- cgit v1.2.3