|
/**
|
|
*
|
|
* 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<T> : 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<T> a = type1 as Range<T>;
|
|
Range<T> b = type2 as Range<T>;
|
|
|
|
if (a == null || b == null)
|
|
throw new ArgumentException();
|
|
|
|
return GenericArithmeticCover(a, b, op);
|
|
}
|
|
|
|
public Range<T> GenericArithmeticCover(Range<T> type1, Range<T> type2, ExpressionKind op)
|
|
{
|
|
Range<T> result = type1.Create(default(T), default(T));
|
|
Operations<T> 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<int>
|
|
{
|
|
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<int>
|
|
{
|
|
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<int>
|
|
{
|
|
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<double>
|
|
{
|
|
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<double>
|
|
{
|
|
|
|
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)
|
|
{ }
|
|
}
|
|
|
|
|
|
|
|
}
|