/*++ Copyright (c) 2015 Microsoft Corporation --*/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using Microsoft.Z3; using Microsoft.SolverFoundation.Common; namespace Microsoft.SolverFoundation.Plugin.Z3 { public class Utils { /// /// Returns the Z3 term corresponding to the MSF rational number. /// /// The MSF rational /// The Z3 term public static ArithExpr GetNumeral(Context context, Rational rational, Sort sort = null) { try { sort = rational.IsInteger() ? ((Sort)context.IntSort) : (sort == null ? (Sort)context.RealSort : sort); return (ArithExpr)context.MkNumeral(rational.ToString(), sort); } catch (Z3Exception e) { Console.Error.WriteLine("Conversion of {0} failed:\n {1}", rational, e); throw new NotSupportedException(); } } private static long BASE = 10 ^ 18; private static Rational ToRational(System.Numerics.BigInteger bi) { if (System.Numerics.BigInteger.Abs(bi) <= BASE) { return (Rational)((long)bi); } return BASE * ToRational(bi / BASE) + ToRational(bi % BASE); } public static Rational ToRational(IntNum i) { return ToRational(i.BigInteger); } public static Rational ToRational(RatNum r) { return ToRational(r.BigIntNumerator) / ToRational(r.BigIntDenominator); } public static Rational ToRational(Expr expr) { Debug.Assert(expr is ArithExpr, "Only accept ArithExpr for now."); var e = expr as ArithExpr; if (e is IntNum) { Debug.Assert(expr.IsIntNum, "Number should be an integer."); return ToRational(expr as IntNum); } if (e is RatNum) { Debug.Assert(expr.IsRatNum, "Number should be a rational."); return ToRational(expr as RatNum); } if (e.IsAdd) { Rational r = Rational.Zero; foreach (var arg in e.Args) { r += ToRational(arg); } return r; } if (e.IsMul) { Rational r = Rational.One; foreach (var arg in e.Args) { r *= ToRational(arg); } return r; } if (e.IsUMinus) { return -ToRational(e.Args[0]); } if (e.IsDiv) { return ToRational(e.Args[0]) / ToRational(e.Args[1]); } if (e.IsSub) { Rational r = ToRational(e.Args[0]); for (int i = 1; i < e.Args.Length; ++i) { r -= ToRational(e.Args[i]); } return r; } if (e.IsConst && e.FuncDecl.Name.ToString() == "oo") { return Rational.PositiveInfinity; } if (e.IsConst && e.FuncDecl.Name.ToString() == "epsilon") { return Rational.One/Rational.PositiveInfinity; } Debug.Assert(false, "Should not happen"); return Rational.One; } } }