/** * * OOAS Compiler (Deprecated) * * Copyright 2015, Institute for Software Technology, Graz University of * Technology. Portions are copyright 2015 by the AIT Austrian Institute * of Technology. All rights reserved. * * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED. * * Please notice that this version of the OOAS compiler is considered de- * precated. Only the Java version is maintained. * * Contributors: * Willibald Krenn (TU Graz/AIT) * Stefan Tiran (TU Graz/AIT) */ using System; using System.Collections.Generic; using System.Text; namespace TUG.Mogentes { public abstract class AbstractOperations { public abstract AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op); } public class Operations : AbstractOperations { public delegate T opUnary(T input); public delegate T opBinary(T inputA, T inputB); public delegate bool opBinRel(T inputA, T intputB); public opUnary unaryNotImplemented = p => { throw new NotImplementedException(); }; public opBinary binaryNotImplemented = (a, b) => { throw new NotImplementedException(); }; public opBinRel binrelNotImplemented = (a, b) => { throw new NotImplementedException(); }; // not all operations may be defined, then there needs to be some excpetion.. public opUnary unMinus; public opBinary minus; public opBinary plus; public opBinary div; public opBinary pow; public opBinary prod; public opBinary mod; public opBinRel equal; public opBinRel smaller; public opBinRel greater; public override AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op) { Range a = type1 as Range; Range b = type2 as Range; if (a == null || b == null) throw new ArgumentException(); return GenericArithmeticCover(a, b, op); } public Range GenericArithmeticCover(Range type1, Range type2, ExpressionKind op) { Range result = type1.Create(default(T), default(T)); Operations o = this; // remove this if method remains in this class.. switch (op) { case ExpressionKind.unminus: result.min = o.unMinus(type1.max); result.max = o.unMinus(type1.min); break; case ExpressionKind.unplus: break; case ExpressionKind.minus: System.Diagnostics.Debug.Assert(type2 != null); // we do some sort of resulttype = type1 - type2 // hence, do the unminus stuff with type 2 T spare = type2.max; type2.max = o.unMinus(type2.min); type2.min = o.unMinus(spare); // now it's the same with sum.. but c# does not let us fall through.. result.min = o.plus(type1.min, type2.min); result.max = o.plus(type1.max, type2.max); break; case ExpressionKind.sum: System.Diagnostics.Debug.Assert(type2 != null); result.min = o.plus(type1.min, type2.min); result.max = o.plus(type1.max, type2.max); break; case ExpressionKind.idiv: case ExpressionKind.div: System.Diagnostics.Debug.Assert(type2 != null); type2.min = o.equal(type2.min, default(T)) ? o.unMinus(type2.precision) : type2.min; type2.max = o.equal(type2.max, default(T)) ? type2.precision : type2.max; // hmm, brute force.. is there some formula? result.max = o.div(type1.min, type2.min); result.min = result.max; T tmp = o.div(type1.max, type2.min); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; tmp = o.div(type1.min, type2.max); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; tmp = o.div(type1.max, type2.max); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; break; case ExpressionKind.mod: throw new ArgumentException(); // do this one level up case ExpressionKind.pow: // ok, this is bad. - just give up here result.max = result.typemax; result.min = result.typemin; break; case ExpressionKind.prod: // hmm, brute force.. is there some formula? result.max = o.prod(type1.min, type2.min); result.min = result.max; tmp = o.prod(type1.max, type2.min); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; tmp = o.prod(type1.min, type2.max); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; tmp = o.prod(type1.max, type2.max); result.max = o.smaller(result.max, tmp) ? tmp : result.max; result.min = o.greater(result.min, tmp) ? tmp : result.min; break; default: throw new NotImplementedException(); } return result; } public Operations() { unMinus = unaryNotImplemented; minus = binaryNotImplemented; plus = binaryNotImplemented; div = binaryNotImplemented; pow = binaryNotImplemented; prod = binaryNotImplemented; mod = binaryNotImplemented; equal = binrelNotImplemented; smaller = binrelNotImplemented; greater = binrelNotImplemented; } public Operations(opUnary aUnMinus, opBinary aMinus, opBinary aPlus, opBinary aDiv, opBinary aPow, opBinary aProd, opBinary aMod, opBinRel aEquality, opBinRel aSmaller, opBinRel aGreater) { unMinus = aUnMinus; minus = aMinus; plus = aPlus; div = aDiv; pow = aPow; prod = aProd; mod = aMod; equal = aEquality; smaller = aSmaller; greater = aGreater; } } public sealed class IntegerOperations : Operations { public IntegerOperations() : base(p => -p, (a, b) => a - b, (a, b) => a + b, (a, b) => a / b, (a, b) => (int)Math.Pow(a, b), (a, b) => a * b, (a, b) => a % b, (a, b) => a == b, (a, b) => a < b, (a, b) => a > b) { } } public sealed class CheckedIntegerOperations : Operations { public CheckedIntegerOperations() : base(p => { checked { return -p; } }, (a, b) => { checked { return a - b; } }, (a, b) => { checked { return a + b; } }, (a, b) => { checked { return a / b; } }, (a, b) => { checked { return (int)Math.Pow(a, b); } }, (a, b) => { checked { return a * b; } }, (a, b) => a % b, (a, b) => a == b, (a, b) => a < b, (a, b) => a > b) { } } public sealed class SaturatedIntegerOperations : Operations { private static int SatUnMinus(int input) { return input == int.MinValue ? int.MaxValue : -input; } private static int Subtraction(int a, int b) { if (b < 0) return (a > int.MaxValue + b) ? int.MaxValue : a - b; else return (a < int.MinValue + b) ? int.MinValue : a - b; } private static int Addition(int a, int b) { if (b < 0) return (a < int.MinValue - b) ? int.MinValue : a + b; else return (a > int.MaxValue - b) ? int.MaxValue : a + b; } private static int Division(int a, int b) { checked { return a / b; }; } private static int Power(int a, int b) { Int64 tmp = (Int64)Math.Pow(a, b); if (tmp < int.MinValue) return int.MinValue; else if (tmp > int.MaxValue) return int.MaxValue; else return (int)tmp; } private static int Multiplication(int a, int b) { Int64 tmp = Math.BigMul(a, b); if (tmp < int.MinValue) return int.MinValue; else if (tmp > int.MaxValue) return int.MaxValue; else return (int)tmp; } public SaturatedIntegerOperations() : base(SatUnMinus, Subtraction, Addition, Division, Power, Multiplication, (a, b) => a % b, (a, b) => a == b, (a, b) => a < b, (a, b) => a > b) { } } public sealed class DoubleOperations : Operations { public DoubleOperations() : base(p => -p, (a, b) => a - b, (a, b) => a + b, (a, b) => a / b, (a, b) => Math.Pow(a, b), (a, b) => a * b, (a, b) => a % b, (a, b) => a == b, (a, b) => a < b, (a, b) => a > b) { } } public sealed class SaturatedDoubleOperations : Operations { private static double checkRange(double aValue) { if (aValue == double.PositiveInfinity) return double.MaxValue; else if (aValue == double.NegativeInfinity) return double.MinValue; else return aValue; } private static double SatUnMinus(double input) { return checkRange(-input); } private static double Subtraction(double a, double b) { return checkRange(a - b); } private static double Addition(double a, double b) { return checkRange(a + b); } private static double Division(double a, double b) { return checkRange(a / b); } private static double Power(double a, double b) { return checkRange(Math.Pow(a, b)); } private static double Multiplication(double a, double b) { return checkRange(a * b); } private static double Reminder(double a, double b) { return checkRange(a % b); } public SaturatedDoubleOperations() : base(SatUnMinus, Subtraction, Addition, Division, Power, Multiplication, Reminder, (a, b) => a == b, (a, b) => a < b, (a, b) => a > b) { } } }