22 namespace Deveel.Data.Sql.Objects {
48 if (value != null && value.Scale == 0) {
49 BigInteger bint = value.ToBigInteger();
50 int bitCount = bint.BitLength;
52 valueAsLong = bint.ToInt64();
54 }
else if (bitCount < 60) {
55 valueAsLong = bint.ToInt64();
65 : this(new BigDecimal(new BigInteger(bytes), scale)) {
68 public SqlNumber(byte[] bytes,
int scale,
int precision)
69 : this(new BigDecimal(new BigInteger(bytes), scale, new MathContext(precision))) {
73 : this(new BigDecimal(value, new MathContext(precision))) {
77 : this(value, MathContext.Decimal32.Precision) {
81 : this(new BigDecimal(value, new MathContext(precision))) {
85 : this(value, MathContext.Decimal64.Precision) {
89 : this(value, MathContext.Decimal128.Precision) {
93 : this(new BigDecimal(value, new MathContext(precision))) {
101 var bytes = data.
GetValue<byte[]>(
"Bytes");
103 var precision = data.
GetInt32(
"Precision");
105 innerValue =
new BigDecimal(
new BigInteger(bytes), scale,
new MathContext(precision));
113 public bool CanBeInt64 {
114 get {
return byteCount <= 8; }
117 public bool CanBeInt32 {
118 get {
return byteCount <= 4; }
122 get {
return State ==
NumericState.None ? innerValue.Scale : 0; }
125 public int Precision {
126 get {
return State ==
NumericState.None ? innerValue.Precision : 0; }
129 private MathContext MathContext {
130 get {
return State ==
NumericState.None ?
new MathContext(Precision) : null; }
134 get {
return State ==
NumericState.None ? innerValue.Sign : 0; }
138 data.
SetValue(
"State", (byte)State);
141 var bytes = innerValue.UnscaledValue.ToByteArray();
142 var scale = innerValue.Scale;
143 var precision = innerValue.Precision;
147 data.
SetValue(
"Precision", precision);
151 int IComparable.CompareTo(
object obj) {
153 throw new ArgumentException();
155 return CompareTo((SqlNumber) obj);
160 throw new ArgumentException();
162 return CompareTo((SqlNumber) other);
166 get {
return State ==
NumericState.None && innerValue == null; }
192 if (IsNull && other.
IsNull)
194 if (IsNull && !other.
IsNull)
196 if (!IsNull && other.
IsNull)
199 return innerValue.CompareTo(other.
innerValue) == 0;
202 public override bool Equals(
object obj) {
206 return Equals((SqlNumber) obj);
210 return innerValue.GetHashCode() ^ State.GetHashCode();
214 if (Equals(
this, other))
228 return innerValue.CompareTo(other.
innerValue);
240 throw new ArgumentException(
"Unknown number state.");
255 throw new ArgumentException(
"Unknown number state.");
261 return (State - other.
State);
264 TypeCode IConvertible.GetTypeCode() {
266 return TypeCode.Int32;
268 return TypeCode.Int64;
270 return TypeCode.Object;
273 bool IConvertible.ToBoolean(IFormatProvider provider) {
277 char IConvertible.ToChar(IFormatProvider provider) {
278 throw new InvalidCastException(
"Conversion of NUMERIC to Char is invalid.");
281 sbyte IConvertible.ToSByte(IFormatProvider provider) {
282 throw new NotSupportedException(
"Conversion to Signed Byte numbers not supported yet.");
285 byte IConvertible.ToByte(IFormatProvider provider) {
289 short IConvertible.ToInt16(IFormatProvider provider) {
293 ushort IConvertible.ToUInt16(IFormatProvider provider) {
294 throw new NotSupportedException(
"Conversion to Unsigned numbers not supported yet.");
297 int IConvertible.ToInt32(IFormatProvider provider) {
301 uint IConvertible.ToUInt32(IFormatProvider provider) {
302 throw new NotSupportedException(
"Conversion to Unsigned numbers not supported yet.");
305 long IConvertible.ToInt64(IFormatProvider provider) {
309 ulong IConvertible.ToUInt64(IFormatProvider provider) {
310 throw new NotSupportedException(
"Conversion to Unsigned numbers not supported yet.");
313 float IConvertible.ToSingle(IFormatProvider provider) {
317 double IConvertible.ToDouble(IFormatProvider provider) {
321 decimal IConvertible.ToDecimal(IFormatProvider provider) {
322 throw new NotSupportedException(
"Conversion to Decimal not supported yet.");
325 DateTime IConvertible.ToDateTime(IFormatProvider provider) {
326 throw new InvalidCastException(
"Cannot cast NUMERIC to DateTime automatically.");
329 string IConvertible.ToString(IFormatProvider provider) {
333 object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
334 if (conversionType == typeof (
bool))
336 if (conversionType == typeof (byte))
338 if (conversionType == typeof (
short))
340 if (conversionType == typeof (
int))
342 if (conversionType == typeof (
long))
344 if (conversionType == typeof (
float))
346 if (conversionType == typeof (
double))
349 if (conversionType == typeof (byte[]))
350 return ToByteArray();
352 if (conversionType == typeof (
string))
357 if (conversionType == typeof (
SqlBinary))
359 if (conversionType == typeof (
SqlString))
362 throw new InvalidCastException(
System.String.Format(
"Cannot convert NUMERIC to {0}", conversionType));
367 ? innerValue.MovePointRight(innerValue.Scale).ToBigInteger().ToByteArray()
374 return innerValue.ToString();
382 throw new InvalidCastException(
"Unknown number state");
389 return innerValue.ToDouble();
391 return Double.NegativeInfinity;
393 return Double.PositiveInfinity;
397 throw new InvalidCastException(
"Unknown number state");
404 return innerValue.ToSingle();
406 return Single.NegativeInfinity;
408 return Single.PositiveInfinity;
412 throw new InvalidCastException(
"Unknown number state");
421 return innerValue.ToInt64();
423 return (
long)ToDouble();
429 return (
int)valueAsLong;
432 return innerValue.ToInt32();
434 return (
int)ToDouble();
440 throw new InvalidCastException(
"The value of this numeric is over the maximum Int16.");
442 var value = ToInt32();
443 if (value > Int16.MaxValue ||
444 value < Int16.MinValue)
445 throw new InvalidCastException(
"The value of this numeric is out of range of a short integer.");
452 throw new InvalidCastException(
"The value of this numeric is over the maximum Byte.");
454 var value = ToInt32();
455 if (value > Byte.MaxValue ||
456 value < Byte.MinValue)
457 throw new InvalidCastException(
"The value of this numeric is out of range of a byte.");
468 throw new InvalidCastException(
"The value of this NUMERIC cannot be converted to a boolean.");
475 if (Scale == 0 && value.
Scale == 0) {
476 BigInteger bi1 = innerValue.ToBigInteger();
477 BigInteger bi2 = value.
innerValue.ToBigInteger();
488 if (Scale == 0 && value.
Scale == 0) {
489 BigInteger bi1 = innerValue.ToBigInteger();
490 BigInteger bi2 = value.
innerValue.ToBigInteger();
501 if (Scale == 0 && value.
Scale == 0) {
502 BigInteger bi1 = innerValue.ToBigInteger();
503 BigInteger bi2 = value.
innerValue.ToBigInteger();
513 if (IsNull || value.
IsNull)
528 if (IsNull || value.
IsNull)
542 if (IsNull || value.
IsNull)
557 if (IsNull || value.
IsNull)
561 if (divBy.CompareTo (BigDecimal.Zero) != 0) {
574 if (IsNull || value.
IsNull)
578 if (divBy.CompareTo(BigDecimal.Zero) != 0) {
579 BigDecimal remainder = innerValue.Remainder(divBy);
596 [CLSCompliant(
false)]
599 return new SqlNumber(innerValue.SetScale(scale, mode));
607 return new SqlNumber(innerValue.Negate());
610 return new SqlNumber(InverseState(), null);
620 return new SqlNumber(InverseState(), null);
627 return new SqlNumber(
new BigDecimal(innerValue.ToBigInteger().Not()));
630 return new SqlNumber(InverseState(), null);
637 return new SqlNumber(BigMath.Sqrt(innerValue));
644 return new SqlNumber(BigMath.Root(n, innerValue));
651 return new SqlNumber(BigMath.Sin(innerValue));
658 return new SqlNumber(BigMath.Cos(innerValue));
665 return new SqlNumber(BigMath.Cot(innerValue));
672 return new SqlNumber(BigMath.Tan(innerValue));
686 return new SqlNumber(BigMath.Log(innerValue));
692 return Round(MathContext.Precision);
697 return new SqlNumber(innerValue.Round(
new MathContext(precision, RoundingMode.HalfUp)));
703 if (String.IsNullOrEmpty(s)) {
708 if (
string.Equals(s,
"+Infinity", StringComparison.OrdinalIgnoreCase) ||
709 string.Equals(s,
"+Inf", StringComparison.OrdinalIgnoreCase) ||
710 string.Equals(s,
"Infinity", StringComparison.OrdinalIgnoreCase)) {
711 value = PositiveInfinity;
715 if (
string.Equals(s,
"-Infinity", StringComparison.OrdinalIgnoreCase) ||
716 string.Equals(s,
"-Inf", StringComparison.OrdinalIgnoreCase)) {
717 value = NegativeInfinity;
721 if (
string.Equals(s,
"NaN", StringComparison.OrdinalIgnoreCase) ||
722 string.Equals(s,
"NotANumber", StringComparison.OrdinalIgnoreCase)) {
727 BigDecimal decimalValue;
729 if (!BigDecimal.TryParse(s, out decimalValue)) {
740 if (!TryParse(s, out value))
741 throw new FormatException(
string.Format(
"Cannot parse the string '{0}' to a valid Numeric object.", s));
796 return i == 0 || i > 0;
801 return i == 0 || i < 0;
NumericState
Lists all the possible special states of a number.
NumericState InverseState()
void GetData(SerializeData data)
SqlNumber XOr(SqlNumber value)
bool Equals(SqlNumber other)
SqlNumber(long value, int precision)
The number represents a negative infinity (for example, the result of a division of a negative number...
static bool TryParse(string s, out SqlNumber value)
Implements a BINARY object that handles a limited number of bytes, not exceding MaxLength.
int CompareTo(SqlNumber other)
SqlNumber Modulo(SqlNumber value)
SqlNumber(BigDecimal value)
SqlNumber Pow(SqlNumber exp)
void SetValue(string key, Type type, object value)
readonly BigDecimal innerValue
The number represents a positive infinity (for example, the result of a division of a positive number...
SqlNumber(NumericState state, BigDecimal value)
override int GetHashCode()
SqlNumber(double value, int precision)
Defines the contract for a valid SQL Object
SqlNumber(ObjectData data)
SqlNumber SetScale(int scale, RoundingMode mode)
SqlNumber Round(int precision)
SqlNumber(byte[] bytes, int scale, int precision)
SqlNumber Divide(SqlNumber value)
SqlNumber Multiply(SqlNumber value)
SqlNumber And(SqlNumber value)
bool IsComparableTo(ISqlObject other)
Checks if the current object is comparable with the given one.
override string ToString()
Deveel.Data.Sql.Objects.SqlBoolean SqlBoolean
object GetValue(string key)
SqlNumber Subtract(SqlNumber value)
override bool Equals(object obj)
SqlNumber Or(SqlNumber value)
SqlNumber(int value, int precision)
int IComparable. CompareTo(object obj)
static SqlNumber Parse(string s)
readonly long valueAsLong
SqlNumber(byte[] bytes, int scale)
Deveel.Data.Sql.Objects.SqlString SqlString
SqlNumber Add(SqlNumber value)