root/branches/compiler/cSharp/ooasCompiler/src/math/Operations.cs
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)
|
|||
{ }
|
|||
}
|
|||
}
|