Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / math / Operations.cs

1 3 krennw
/**
2
  *
3
  *                      OOAS Compiler (Deprecated)
4
  *
5
  * Copyright 2015, Institute for Software Technology, Graz University of
6
  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
7
  * of Technology. All rights reserved.
8
  *
9
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
10
  *
11
  * Please notice that this version of the OOAS compiler is considered de-
12
  * precated. Only the Java version is maintained.
13
  *
14
  * Contributors:
15
  *               Willibald Krenn (TU Graz/AIT)
16
  *               Stefan Tiran (TU Graz/AIT)
17
  */
18
19
using System;
20
using System.Collections.Generic;
21
using System.Text;
22
23
namespace TUG.Mogentes
24
{
25
    public abstract class AbstractOperations
26
    {
27
        public abstract AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op);
28
    }
29
30
    public class Operations<T> : AbstractOperations
31
    {
32
        public delegate T opUnary(T input);
33
        public delegate T opBinary(T inputA, T inputB);
34
        public delegate bool opBinRel(T inputA, T intputB);
35
36
        public opUnary unaryNotImplemented = p => { throw new NotImplementedException(); };
37
        public opBinary binaryNotImplemented = (a, b) => { throw new NotImplementedException(); };
38
        public opBinRel binrelNotImplemented = (a, b) => { throw new NotImplementedException(); };
39
40
        // not all operations may be defined, then there needs to be some excpetion..
41
        public opUnary unMinus;
42
        public opBinary minus;
43
        public opBinary plus;
44
        public opBinary div;
45
        public opBinary pow;
46
        public opBinary prod;
47
        public opBinary mod;
48
        public opBinRel equal;
49
        public opBinRel smaller;
50
        public opBinRel greater;
51
52
        public override AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op)
53
        {
54
            Range<T> a = type1 as Range<T>;
55
            Range<T> b = type2 as Range<T>;
56
57
            if (a == null || b == null)
58
                throw new ArgumentException();
59
60
            return GenericArithmeticCover(a, b, op);
61
        }
62
63
        public Range<T> GenericArithmeticCover(Range<T> type1, Range<T> type2, ExpressionKind op)
64
        {
65
            Range<T> result = type1.Create(default(T), default(T));
66
            Operations<T> o = this; // remove this if method remains in this class..
67
68
            switch (op)
69
            {
70
                case ExpressionKind.unminus:
71
                    result.min = o.unMinus(type1.max);
72
                    result.max = o.unMinus(type1.min);
73
                    break;
74
                case ExpressionKind.unplus:
75
                    break;
76
77
                case ExpressionKind.minus:
78
                    System.Diagnostics.Debug.Assert(type2 != null);
79
                    // we do some sort of resulttype = type1 - type2
80
                    // hence, do the unminus stuff with type 2
81
                    T spare = type2.max;
82
                    type2.max = o.unMinus(type2.min);
83
                    type2.min = o.unMinus(spare);
84
                    // now it's the same with sum.. but c# does not let us fall through..
85
                    result.min = o.plus(type1.min, type2.min);
86
                    result.max = o.plus(type1.max, type2.max);
87
                    break;
88
                case ExpressionKind.sum:
89
                    System.Diagnostics.Debug.Assert(type2 != null);
90
                    result.min = o.plus(type1.min, type2.min);
91
                    result.max = o.plus(type1.max, type2.max);
92
                    break;
93
                case ExpressionKind.idiv:
94
                case ExpressionKind.div:
95
                    System.Diagnostics.Debug.Assert(type2 != null);
96
                    type2.min = o.equal(type2.min, default(T)) ? o.unMinus(type2.precision) : type2.min;
97
                    type2.max = o.equal(type2.max, default(T)) ? type2.precision : type2.max;
98
                    // hmm, brute force.. is there some formula?
99
                    result.max = o.div(type1.min, type2.min);
100
                    result.min = result.max;
101
102
                    T tmp = o.div(type1.max, type2.min);
103
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
104
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
105
106
                    tmp = o.div(type1.min, type2.max);
107
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
108
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
109
110
                    tmp = o.div(type1.max, type2.max);
111
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
112
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
113
                    break;
114
                case ExpressionKind.mod:
115
                    throw new ArgumentException(); // do this one level up
116
                case ExpressionKind.pow:
117
                    // ok, this is bad. - just give up here
118
                    result.max = result.typemax;
119
                    result.min = result.typemin;
120
                    break;
121
                case ExpressionKind.prod:
122
                    // hmm, brute force.. is there some formula?
123
                    result.max = o.prod(type1.min, type2.min);
124
                    result.min = result.max;
125
126
                    tmp = o.prod(type1.max, type2.min);
127
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
128
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
129
130
                    tmp = o.prod(type1.min, type2.max);
131
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
132
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
133
134
                    tmp = o.prod(type1.max, type2.max);
135
                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
136
                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
137
                    break;
138
139
                default:
140
                    throw new NotImplementedException();
141
            }
142
            return result;
143
        }
144
145
146
        public Operations()
147
        {
148
            unMinus = unaryNotImplemented;
149
            minus = binaryNotImplemented;
150
            plus = binaryNotImplemented;
151
            div = binaryNotImplemented;
152
            pow = binaryNotImplemented;
153
            prod = binaryNotImplemented;
154
            mod = binaryNotImplemented;
155
            equal = binrelNotImplemented;
156
            smaller = binrelNotImplemented;
157
            greater = binrelNotImplemented;
158
        }
159
160
        public Operations(opUnary aUnMinus,
161
            opBinary aMinus,
162
            opBinary aPlus,
163
            opBinary aDiv,
164
            opBinary aPow,
165
            opBinary aProd,
166
            opBinary aMod,
167
            opBinRel aEquality,
168
            opBinRel aSmaller,
169
            opBinRel aGreater)
170
        {
171
            unMinus = aUnMinus;
172
            minus = aMinus;
173
            plus = aPlus;
174
            div = aDiv;
175
            pow = aPow;
176
            prod = aProd;
177
            mod = aMod;
178
            equal = aEquality;
179
            smaller = aSmaller;
180
            greater = aGreater;
181
        }
182
    }
183
184
185
    public sealed class IntegerOperations : Operations<int>
186
    {
187
        public IntegerOperations()
188
            : base(p => -p,
189
            (a, b) => a - b,
190
            (a, b) => a + b,
191
            (a, b) => a / b,
192
            (a, b) => (int)Math.Pow(a, b),
193
            (a, b) => a * b,
194
            (a, b) => a % b,
195
            (a, b) => a == b,
196
            (a, b) => a < b,
197
            (a, b) => a > b)
198
        { }
199
    }
200
201
202
    public sealed class CheckedIntegerOperations : Operations<int>
203
    {
204
        public CheckedIntegerOperations()
205
            : base(p => { checked { return -p; } },
206
            (a, b) => { checked { return a - b; } },
207
            (a, b) => { checked { return a + b; } },
208
            (a, b) => { checked { return a / b; } },
209
            (a, b) => { checked { return (int)Math.Pow(a, b); } },
210
            (a, b) => { checked { return a * b; } },
211
            (a, b) => a % b,
212
            (a, b) => a == b,
213
            (a, b) => a < b,
214
            (a, b) => a > b)
215
        { }
216
    }
217
218
219
    public sealed class SaturatedIntegerOperations : Operations<int>
220
    {
221
        private static int SatUnMinus(int input)
222
        {
223
            return input == int.MinValue ? int.MaxValue : -input;
224
        }
225
226
        private static int Subtraction(int a, int b)
227
        {
228
            if (b < 0)
229
                return (a > int.MaxValue + b) ? int.MaxValue : a - b;
230
            else
231
                return (a < int.MinValue + b) ? int.MinValue : a - b;
232
        }
233
234
        private static int Addition(int a, int b)
235
        {
236
            if (b < 0)
237
                return (a < int.MinValue - b) ? int.MinValue : a + b;
238
            else
239
                return (a > int.MaxValue - b) ? int.MaxValue : a + b;
240
        }
241
242
        private static int Division(int a, int b)
243
        {
244
            checked { return a / b; };
245
        }
246
247
        private static int Power(int a, int b)
248
        {
249
            Int64 tmp = (Int64)Math.Pow(a, b);
250
            if (tmp < int.MinValue) return int.MinValue;
251
            else if (tmp > int.MaxValue) return int.MaxValue;
252
            else return (int)tmp;
253
        }
254
255
        private static int Multiplication(int a, int b)
256
        {
257
            Int64 tmp = Math.BigMul(a, b);
258
            if (tmp < int.MinValue) return int.MinValue;
259
            else if (tmp > int.MaxValue) return int.MaxValue;
260
            else return (int)tmp;
261
        }
262
263
        public SaturatedIntegerOperations()
264
            : base(SatUnMinus, Subtraction, Addition, Division, Power, Multiplication,
265
            (a, b) => a % b,
266
            (a, b) => a == b,
267
            (a, b) => a < b,
268
            (a, b) => a > b)
269
        { }
270
    }
271
272
273
274
    public sealed class DoubleOperations : Operations<double>
275
    {
276
        public DoubleOperations()
277
            : base(p => -p,
278
            (a, b) => a - b,
279
            (a, b) => a + b,
280
            (a, b) => a / b,
281
            (a, b) => Math.Pow(a, b),
282
            (a, b) => a * b,
283
            (a, b) => a % b,
284
            (a, b) => a == b,
285
            (a, b) => a < b,
286
            (a, b) => a > b)
287
        { }
288
    }
289
290
291
292
    public sealed class SaturatedDoubleOperations : Operations<double>
293
    {
294
295
        private static double checkRange(double aValue)
296
        {
297
            if (aValue == double.PositiveInfinity)
298
                return double.MaxValue;
299
            else if (aValue == double.NegativeInfinity)
300
                return double.MinValue;
301
            else
302
                return aValue;
303
        }
304
305
        private static double SatUnMinus(double input)
306
        {
307
            return checkRange(-input);
308
        }
309
310
        private static double Subtraction(double a, double b)
311
        {
312
            return checkRange(a - b);
313
        }
314
315
        private static double Addition(double a, double b)
316
        {
317
            return checkRange(a + b);
318
        }
319
320
        private static double Division(double a, double b)
321
        {
322
            return checkRange(a / b);
323
        }
324
325
        private static double Power(double a, double b)
326
        {
327
            return checkRange(Math.Pow(a, b));
328
        }
329
330
        private static double Multiplication(double a, double b)
331
        {
332
333
            return checkRange(a * b);
334
        }
335
336
        private static double Reminder(double a, double b)
337
        {
338
            return checkRange(a % b);
339
        }
340
341
        public SaturatedDoubleOperations()
342
            : base(SatUnMinus,
343
            Subtraction,
344
            Addition,
345
            Division,
346
            Power,
347
            Multiplication,
348
            Reminder,
349
            (a, b) => a == b,
350
            (a, b) => a < b,
351
            (a, b) => a > b)
352
        { }
353
    }
354
355
356
357
}