Project

General

Profile

3 krennw
/**
*
* 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)
{ }
}



}