BsonDouble.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* Copyright 2010-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using MongoDB.Bson.IO;
  17. namespace MongoDB.Bson
  18. {
  19. /// <summary>
  20. /// Represents a BSON double value.
  21. /// </summary>
  22. /// <seealso cref="MongoDB.Bson.BsonValue" />
  23. [Serializable]
  24. public class BsonDouble : BsonValue, IComparable<BsonDouble>, IEquatable<BsonDouble>
  25. {
  26. #region static
  27. const int __minPrecreatedValue = -100;
  28. const int __maxPrecreatedValue = 100;
  29. private static readonly BsonDouble[] __precreatedInstances = new BsonDouble[__maxPrecreatedValue - __minPrecreatedValue + 1];
  30. static BsonDouble()
  31. {
  32. for (var i = __minPrecreatedValue; i <= __maxPrecreatedValue; i++)
  33. {
  34. var precreatedInstance = new BsonDouble(i);
  35. var index = i - __minPrecreatedValue;
  36. __precreatedInstances[index] = precreatedInstance;
  37. }
  38. }
  39. #endregion
  40. // private fields
  41. private readonly double _value;
  42. // constructors
  43. /// <summary>
  44. /// Initializes a new instance of the BsonDouble class.
  45. /// </summary>
  46. /// <param name="value">The value.</param>
  47. public BsonDouble(double value)
  48. {
  49. _value = value;
  50. }
  51. // public properties
  52. /// <inheritdoc />
  53. public override BsonType BsonType
  54. {
  55. get { return BsonType.Double; }
  56. }
  57. /// <inheritdoc />
  58. [Obsolete("Use Value instead.")]
  59. public override object RawValue
  60. {
  61. get { return _value; }
  62. }
  63. /// <summary>
  64. /// Gets the value of this BsonDouble.
  65. /// </summary>
  66. public double Value
  67. {
  68. get { return _value; }
  69. }
  70. // public operators
  71. /// <summary>
  72. /// Converts a double to a BsonDouble.
  73. /// </summary>
  74. /// <param name="value">A double.</param>
  75. /// <returns>A BsonDouble.</returns>
  76. public static implicit operator BsonDouble(double value)
  77. {
  78. var intValue = (int)value;
  79. if (intValue == value && intValue >= __minPrecreatedValue && intValue <= __maxPrecreatedValue)
  80. {
  81. var index = intValue - __minPrecreatedValue;
  82. return __precreatedInstances[index];
  83. }
  84. return new BsonDouble(value);
  85. }
  86. /// <summary>
  87. /// Compares two BsonDouble values.
  88. /// </summary>
  89. /// <param name="lhs">The first BsonDouble.</param>
  90. /// <param name="rhs">The other BsonDouble.</param>
  91. /// <returns>True if the two BsonDouble values are not equal according to ==.</returns>
  92. public static bool operator !=(BsonDouble lhs, BsonDouble rhs)
  93. {
  94. return !(lhs == rhs);
  95. }
  96. /// <summary>
  97. /// Compares two BsonDouble values.
  98. /// </summary>
  99. /// <param name="lhs">The first BsonDouble.</param>
  100. /// <param name="rhs">The other BsonDouble.</param>
  101. /// <returns>True if the two BsonDouble values are equal according to ==.</returns>
  102. public static bool operator ==(BsonDouble lhs, BsonDouble rhs)
  103. {
  104. if (object.ReferenceEquals(lhs, null)) { return object.ReferenceEquals(rhs, null); }
  105. return lhs.OperatorEqualsImplementation(rhs);
  106. }
  107. // public static methods
  108. /// <summary>
  109. /// Creates a new instance of the BsonDouble class.
  110. /// </summary>
  111. /// <param name="value">An object to be mapped to a BsonDouble.</param>
  112. /// <returns>A BsonDouble.</returns>
  113. public new static BsonDouble Create(object value)
  114. {
  115. if (value == null)
  116. {
  117. throw new ArgumentNullException("value");
  118. }
  119. return (BsonDouble)BsonTypeMapper.MapToBsonValue(value, BsonType.Double);
  120. }
  121. // public methods
  122. /// <summary>
  123. /// Compares this BsonDouble to another BsonDouble.
  124. /// </summary>
  125. /// <param name="other">The other BsonDouble.</param>
  126. /// <returns>A 32-bit signed integer that indicates whether this BsonDouble is less than, equal to, or greather than the other.</returns>
  127. public int CompareTo(BsonDouble other)
  128. {
  129. if (other == null) { return 1; }
  130. return _value.CompareTo(other._value);
  131. }
  132. /// <inheritdoc />
  133. public override int CompareTo(BsonValue other)
  134. {
  135. if (other == null) { return 1; }
  136. var otherDouble = other as BsonDouble;
  137. if (otherDouble != null)
  138. {
  139. return _value.CompareTo(otherDouble._value);
  140. }
  141. var otherInt32 = other as BsonInt32;
  142. if (otherInt32 != null)
  143. {
  144. return _value.CompareTo((double)otherInt32.Value);
  145. }
  146. var otherInt64 = other as BsonInt64;
  147. if (otherInt64 != null)
  148. {
  149. return _value.CompareTo((double)otherInt64.Value);
  150. }
  151. var otherDecimal128 = other as BsonDecimal128;
  152. if (otherDecimal128 != null)
  153. {
  154. return ((Decimal128)_value).CompareTo(otherDecimal128.Value);
  155. }
  156. return CompareTypeTo(other);
  157. }
  158. /// <summary>
  159. /// Compares this BsonDouble to another BsonDouble.
  160. /// </summary>
  161. /// <param name="rhs">The other BsonDouble.</param>
  162. /// <returns>True if the two BsonDouble values are equal.</returns>
  163. public bool Equals(BsonDouble rhs)
  164. {
  165. if (object.ReferenceEquals(rhs, null) || GetType() != rhs.GetType()) { return false; }
  166. return _value.Equals(rhs._value); // use Equals instead of == so NaN is handled correctly
  167. }
  168. /// <inheritdoc />
  169. public override bool Equals(object obj)
  170. {
  171. return Equals(obj as BsonDouble); // works even if obj is null or of a different type
  172. }
  173. /// <inheritdoc />
  174. public override int GetHashCode()
  175. {
  176. // see Effective Java by Joshua Bloch
  177. int hash = 17;
  178. hash = 37 * hash + BsonType.GetHashCode();
  179. hash = 37 * hash + _value.GetHashCode();
  180. return hash;
  181. }
  182. /// <inheritdoc />
  183. public override bool ToBoolean()
  184. {
  185. return !(double.IsNaN(_value) || _value == 0.0);
  186. }
  187. /// <inheritdoc />
  188. public override decimal ToDecimal()
  189. {
  190. return (decimal)_value;
  191. }
  192. /// <inheritdoc />
  193. public override Decimal128 ToDecimal128()
  194. {
  195. return (Decimal128)_value;
  196. }
  197. /// <inheritdoc />
  198. public override double ToDouble()
  199. {
  200. return _value;
  201. }
  202. /// <inheritdoc />
  203. public override int ToInt32()
  204. {
  205. return (int)_value;
  206. }
  207. /// <inheritdoc />
  208. public override long ToInt64()
  209. {
  210. return (long)_value;
  211. }
  212. /// <inheritdoc />
  213. public override string ToString()
  214. {
  215. return JsonConvert.ToString(_value);
  216. }
  217. // protected methods
  218. /// <inheritdoc/>
  219. protected override TypeCode IConvertibleGetTypeCodeImplementation()
  220. {
  221. return TypeCode.Double;
  222. }
  223. /// <inheritdoc/>
  224. protected override bool IConvertibleToBooleanImplementation(IFormatProvider provider)
  225. {
  226. return Convert.ToBoolean(_value, provider);
  227. }
  228. /// <inheritdoc/>
  229. protected override byte IConvertibleToByteImplementation(IFormatProvider provider)
  230. {
  231. return Convert.ToByte(_value, provider);
  232. }
  233. /// <inheritdoc/>
  234. protected override decimal IConvertibleToDecimalImplementation(IFormatProvider provider)
  235. {
  236. return Convert.ToDecimal(_value, provider);
  237. }
  238. /// <inheritdoc/>
  239. protected override double IConvertibleToDoubleImplementation(IFormatProvider provider)
  240. {
  241. return _value;
  242. }
  243. /// <inheritdoc/>
  244. protected override short IConvertibleToInt16Implementation(IFormatProvider provider)
  245. {
  246. return Convert.ToInt16(_value, provider);
  247. }
  248. /// <inheritdoc/>
  249. protected override int IConvertibleToInt32Implementation(IFormatProvider provider)
  250. {
  251. return Convert.ToInt32(_value, provider);
  252. }
  253. /// <inheritdoc/>
  254. protected override long IConvertibleToInt64Implementation(IFormatProvider provider)
  255. {
  256. return Convert.ToInt64(_value, provider);
  257. }
  258. /// <inheritdoc/>
  259. #pragma warning disable 3002
  260. protected override sbyte IConvertibleToSByteImplementation(IFormatProvider provider)
  261. {
  262. return Convert.ToSByte(_value, provider);
  263. }
  264. #pragma warning restore
  265. /// <inheritdoc/>
  266. protected override float IConvertibleToSingleImplementation(IFormatProvider provider)
  267. {
  268. return Convert.ToSingle(_value, provider);
  269. }
  270. /// <inheritdoc/>
  271. protected override string IConvertibleToStringImplementation(IFormatProvider provider)
  272. {
  273. return Convert.ToString(_value, provider);
  274. }
  275. /// <inheritdoc/>
  276. #pragma warning disable 3002
  277. protected override ushort IConvertibleToUInt16Implementation(IFormatProvider provider)
  278. {
  279. return Convert.ToUInt16(_value, provider);
  280. }
  281. #pragma warning restore
  282. /// <inheritdoc/>
  283. #pragma warning disable 3002
  284. protected override uint IConvertibleToUInt32Implementation(IFormatProvider provider)
  285. {
  286. return Convert.ToUInt32(_value, provider);
  287. }
  288. #pragma warning restore
  289. /// <inheritdoc/>
  290. #pragma warning disable 3002
  291. protected override ulong IConvertibleToUInt64Implementation(IFormatProvider provider)
  292. {
  293. return Convert.ToUInt64(_value, provider);
  294. }
  295. #pragma warning restore
  296. /// <inheritdoc/>
  297. protected override bool OperatorEqualsImplementation(BsonValue rhs)
  298. {
  299. var rhsDouble = rhs as BsonDouble;
  300. if (rhsDouble != null)
  301. {
  302. return _value == rhsDouble._value; // use == instead of Equals so NaN is handled correctly
  303. }
  304. var rhsInt32 = rhs as BsonInt32;
  305. if (rhsInt32 != null)
  306. {
  307. return _value == (double)rhsInt32.Value;
  308. }
  309. var rhsInt64 = rhs as BsonInt64;
  310. if (rhsInt64 != null)
  311. {
  312. return _value == (double)rhsInt64.Value;
  313. }
  314. var rhsDecimal128 = rhs as BsonDecimal128;
  315. if (rhsDecimal128 != null)
  316. {
  317. return _value == (double)rhsDecimal128.Value; // use == instead of Equals so NaN is handled correctly
  318. }
  319. return this.Equals(rhs);
  320. }
  321. }
  322. }