/****************************************************************************** * Copyright (c) 2009 - 2015 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ /** * */ package com.ibm.wala.memsat.representation; import java.util.ArrayList; import java.util.Collection; import java.util.List; import com.ibm.wala.memsat.frontEnd.IRType; import kodkod.ast.Expression; import kodkod.ast.Formula; import kodkod.ast.IntConstant; import kodkod.ast.IntExpression; import kodkod.engine.Evaluator; import kodkod.instance.Bounds; import kodkod.instance.TupleSet; /** * Wraps a Kodkod representation of a real number. * * @author Emina Torlak */ public final class RealExpression { private final IntExpression value; /** * Constructs a new real expression for the given float constant. * This implementation simply rounds the constant to the nearest * integer and represents it using an IntExpression. */ RealExpression(float real) { value = IntConstant.constant((int)Math.round(real)); } /** * Constructs a new real expression from the given int expression. */ private RealExpression(IntExpression expr) { this.value = expr; } /** * Returns a number interpreter for real expressions, based on the given * interpreter for the int expressions. * @return a number interpreter for real expressions, based on the given * interpreter for the int expressions */ static Interpreter<RealExpression> interpreter(final Interpreter<IntExpression> intInterpreter) { return new Interpreter<RealExpression>() { final RealExpression zero = new RealExpression(intInterpreter.defaultValue()); public IRType type() { return IRType.REAL; } public Expression toObj(RealExpression t) { return intInterpreter.toObj(t.value); } public RealExpression fromObj(Expression e) { return new RealExpression(intInterpreter.fromObj(e)); } public Expression defaultObj() { return intInterpreter.defaultObj(); } public RealExpression guardedValue(Formula guard, RealExpression value) { return fromIntExpr(intInterpreter.guardedValue(guard, value.value)); } public RealExpression defaultValue() { return zero; } public Float evaluate(RealExpression value, Evaluator eval) { return value.evaluate(eval); } public boolean singletonEncoding() { return intInterpreter.singletonEncoding(); } RealExpression phi(Collection<? extends RealExpression> phis) { final List<IntExpression> ints = new ArrayList<IntExpression>(phis.size()); for(RealExpression real : phis) { ints.add(real.toIntExpr()); } return fromIntExpr(intInterpreter.phi(ints)); } }; } /** * Returns the set of all reals representable in the * context of the given bounds. * @return set of all reals representable in the * context of the given bounds */ static TupleSet reals(Bounds b) { final TupleSet reals = b.universe().factory().noneOf(1); for(TupleSet ibound : b.intBounds().values()) { reals.addAll(ibound); } return reals; } /** * Returns the set of all reals representable with the * given set of integers. * @requires allInts.arity = 1 * @return set of all reals representable with the * given set of integers. */ static TupleSet allReals(TupleSet allInts) { return allInts; } /** * Returns a real expression that represents a real number * with the same value as the given intExpr. * @return { r: RealExpression | [[r]] = [[intExpr]] } */ public static RealExpression fromIntExpr(IntExpression intExpr) { assert intExpr != null; return new RealExpression(intExpr); } /** * Returns a Formula that evaluates to true if this and * the given real expression represent the same number. * @return { f: Fromula | [[f]] = ([[this]] = [[other]]) } */ public final Formula eq(RealExpression other) { return value.eq(other.value); } /** * Returns a Formula that evaluates to true if the value * of this is greater than the value of the given real expression. * @return { f: Fromula | [[f]] = ([[this]] > [[other]]) } */ public final Formula gt(RealExpression other){ return value.gt(other.value); } /** * Returns a Formula that evaluates to true if the value * of this is greater than or equal to the value of the given real expression. * @return { f: Fromula | [[f]] = ([[this]] >= [[other]]) } */ public final Formula gte(RealExpression other){ return value.gte(other.value); } /** * Returns a Formula that evaluates to true if the value * of this is less than the value of the given real expression. * @return { f: Fromula | [[f]] = ([[this]] < [[other]]) } */ public final Formula lt(RealExpression other){ return value.lt(other.value); } /** * Returns a Formula that evaluates to true if the value * of this is less than or equal to the value of the given real expression. * @return { f: Fromula | [[f]] = ([[this]] <= [[other]]) } */ public final Formula lte(RealExpression other){ return value.lte(other.value); } /** * Returns a real expression that evaluates to the sum * of this and the given real expression. * @return { r: RealExpression | [[r]] = [[this]] + [[other]] } */ public final RealExpression plus(RealExpression other){ return new RealExpression(value.plus(other.value)); } /** * Returns a real expression that evaluates to the difference * of this and the given real expression. * @return { r: RealExpression | [[r]] = [[this]] - [[other]] } */ public final RealExpression minus(RealExpression other){ return new RealExpression(value.minus(other.value)); } /** * Returns a real expression that evaluates to the product * of this and the given real expression. * @return { r: RealExpression | [[r]] = [[this]] * [[other]] } */ public final RealExpression multiply(RealExpression other){ return new RealExpression(value.multiply(other.value)); } /** * Returns a real expression that evaluates to the ratio * of this and the given real expression. * @return { r: RealExpression | [[r]] = [[this]] \ [[other]] } */ public final RealExpression divide(RealExpression other){ return new RealExpression(value.divide(other.value)); } /** * Returns a real expression that evaluates to this modulo * the given real expression. * @return { r: RealExpression | [[r]] = [[this]] % [[other]] } */ public final RealExpression modulo(RealExpression other){ return new RealExpression(value.modulo(other.value)); } /** * Returns a real expression that represents the negation of this real expression. * @return { r: RealExpression | [[r]] = -[[this]] } */ public final RealExpression negate() { return new RealExpression(value.negate()); } /** * Returns the int expression that represents the integer * part of this real value. * @return { i: IntExpression | [[i]] = (int) [[this]] } */ public final IntExpression toIntExpr() { return value; } /** * Returns the float value of this RealExpression, * as given by the specified evaluator. * @requires the given evaluator's instance has bindings * for all relations (if any) at the leaves of this real expression. * @return [[ this ]] w.r.t. eval */ public final float evaluate(Evaluator eval) { return eval.evaluate(value); } /** * Returns the string representation of this real. * @return string representation of this real. * @see java.lang.Object#toString() */ public String toString() { return value.toString(); } }