1 using System;
  2 using System.Numerics.Multiprecision;
  3 
  4 namespace BigNumCalc
  5 {
  6     public enum BigNumKind
  7     {
  8         bigIntbigRationalbigFloat
  9     }
 10 
 11     public nothrow BigNumKind CommonType(BigNumKind leftBigNumKind right)
 12     {
 13         switch (left)
 14         {
 15             case BigNumKind.bigInt:
 16             {
 17                 switch (right)
 18                 {
 19                     case BigNumKind.bigInt: return BigNumKind.bigInt;
 20                     case BigNumKind.bigRational: return BigNumKind.bigRational;
 21                     case BigNumKind.bigFloat: return BigNumKind.bigFloat;
 22                 }
 23                 break;
 24             }
 25             case BigNumKind.bigRational:
 26             {
 27                 switch (right)
 28                 {
 29                     case BigNumKind.bigInt: return BigNumKind.bigRational;
 30                     case BigNumKind.bigRational: return BigNumKind.bigRational;
 31                     case BigNumKind.bigFloat: return BigNumKind.bigFloat;
 32                 }
 33                 break;
 34             }
 35             case BigNumKind.bigFloat:
 36             {
 37                 switch (right)
 38                 {
 39                     case BigNumKind.bigInt: return BigNumKind.bigFloat;
 40                     case BigNumKind.bigRational: return BigNumKind.bigFloat;
 41                     case BigNumKind.bigFloat: return BigNumKind.bigFloat;
 42                 }
 43                 break;
 44             }
 45         }
 46         return BigNumKind.bigInt;
 47     }
 48 
 49     public abstract class BigValue
 50     {
 51         public virtual default ~BigValue();
 52         public abstract nothrow BigNumKind Kind() const;
 53         public abstract BigValue* As(BigNumKind kind) const;
 54         public abstract string ToString() const;
 55     }
 56 
 57     public class BigIntValue : BigValue
 58     {
 59         public typedef BigInt OperandType;
 60         public nothrow BigIntValue() : value()
 61         {
 62         }
 63         public explicit nothrow BigIntValue(const BigInt& value_) : value(value_)
 64         {
 65         }
 66         public override nothrow BigNumKind Kind() const
 67         {
 68             return BigNumKind.bigInt;
 69         }
 70         public override BigValue* As(BigNumKind kind) const
 71         {
 72             switch (kind)
 73             {
 74                 case BigNumKind.bigInt:
 75                 {
 76                     return new BigIntValue(value);
 77                 }
 78                 case BigNumKind.bigRational:
 79                 {
 80                     BigRational val(value);
 81                     return new BigRationalValue(val);
 82                 }
 83                 case BigNumKind.bigFloat:
 84                 {
 85                     BigFloat val(value);
 86                     return new BigFloatValue(val);
 87                 }
 88             }
 89             return null;
 90         }
 91         public override string ToString() const
 92         {
 93             return value.ToString();
 94         }
 95         public inline nothrow const BigInt& Get() const
 96         {
 97             return value;
 98         }
 99         private BigInt value;
100     }
101 
102     public class BigRationalValue : BigValue
103     {
104         public typedef BigRational OperandType;
105         public nothrow BigRationalValue() : value()
106         {
107         }
108         public explicit nothrow BigRationalValue(const BigRational& value_) : value(value_)
109         {
110         }
111         public override nothrow BigNumKind Kind() const
112         {
113             return BigNumKind.bigRational;
114         }
115         public override BigValue* As(BigNumKind kind) const
116         {
117             switch (kind)
118             {
119                 case BigNumKind.bigRational:
120                 {
121                     return new BigRationalValue(value);
122                 }
123                 case BigNumKind.bigFloat:
124                 {
125                     BigFloat val(value);
126                     return new BigFloatValue(val);
127                 }
128             }
129             return null;
130         }
131         public override string ToString() const
132         {
133             return "[" + value.ToString() + "]";
134         }
135         public inline nothrow const BigRational& Get() const
136         {
137             return value;
138         }
139         private BigRational value;
140     }
141 
142     public class BigFloatValue : BigValue
143     {
144         public typedef BigFloat OperandType;
145         public nothrow BigFloatValue() : value()
146         {
147         }
148         public explicit nothrow BigFloatValue(const BigFloat& value_) : value(value_)
149         {
150         }
151         public override nothrow BigNumKind Kind() const
152         {
153             return BigNumKind.bigFloat;
154         }
155         public override BigValue* As(BigNumKind kind) const
156         {
157             switch (kind)
158             {
159                 case BigNumKind.bigFloat:
160                 {
161                     return new BigFloatValue(value);
162                 }
163             }
164             return null;
165         }
166         public override string ToString() const
167         {
168             return value.ToString();
169         }
170         public inline nothrow const BigFloat& Get() const
171         {
172             return value;
173         }
174         private BigFloat value;
175     }
176 }
177