Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1452 | chris | 1 | #region --- License --- |
| 2 | /* |
||
| 3 | Copyright (c) 2006 - 2008 The Open Toolkit library. |
||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
||
| 6 | this software and associated documentation files (the "Software"), to deal in |
||
| 7 | the Software without restriction, including without limitation the rights to |
||
| 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
||
| 9 | of the Software, and to permit persons to whom the Software is furnished to do |
||
| 10 | so, subject to the following conditions: |
||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in all |
||
| 13 | copies or substantial portions of the Software. |
||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
| 21 | SOFTWARE. |
||
| 22 | */ |
||
| 23 | /* |
||
| 24 | The conversion functions are derived from OpenEXR's implementation and are |
||
| 25 | governed by the following license: |
||
| 26 | |||
| 27 | Copyright (c) 2002, Industrial Light & Magic, a division of Lucas |
||
| 28 | Digital Ltd. LLC |
||
| 29 | |||
| 30 | All rights reserved. |
||
| 31 | |||
| 32 | Redistribution and use in source and binary forms, with or without |
||
| 33 | modification, are permitted provided that the following conditions are |
||
| 34 | met: |
||
| 35 | * Redistributions of source code must retain the above copyright |
||
| 36 | notice, this list of conditions and the following disclaimer. |
||
| 37 | * Redistributions in binary form must reproduce the above |
||
| 38 | copyright notice, this list of conditions and the following disclaimer |
||
| 39 | in the documentation and/or other materials provided with the |
||
| 40 | distribution. |
||
| 41 | * Neither the name of Industrial Light & Magic nor the names of |
||
| 42 | its contributors may be used to endorse or promote products derived |
||
| 43 | from this software without specific prior written permission. |
||
| 44 | |||
| 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
| 46 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
| 47 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
| 48 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
| 49 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
| 50 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
| 51 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
| 52 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
| 53 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
| 54 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
| 55 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
| 56 | */ |
||
| 57 | #endregion --- License --- |
||
| 58 | |||
| 59 | using System; |
||
| 60 | using System.IO; |
||
| 61 | using System.Runtime.InteropServices; |
||
| 62 | using System.Runtime.Serialization; |
||
| 63 | |||
| 64 | namespace OpenTK.Math |
||
| 65 | { |
||
| 66 | |||
| 67 | /// <summary> |
||
| 68 | /// The name Half is derived from half-precision floating-point number. |
||
| 69 | /// It occupies only 16 bits, which are split into 1 Sign bit, 5 Exponent bits and 10 Mantissa bits. |
||
| 70 | /// </summary> |
||
| 71 | /// <remarks> |
||
| 72 | /// Quote from ARB_half_float_pixel specification: |
||
| 73 | /// Any representable 16-bit floating-point value is legal as input to a GL command that accepts 16-bit floating-point data. The |
||
| 74 | /// result of providing a value that is not a floating-point number (such as infinity or NaN) to such a command is unspecified, |
||
| 75 | /// but must not lead to GL interruption or termination. Providing a denormalized number or negative zero to GL must yield |
||
| 76 | /// predictable results. |
||
| 77 | /// </remarks> |
||
| 78 | [Obsolete("OpenTK.Math functions have been moved to the root OpenTK namespace (reason: XNA compatibility")] |
||
| 79 | [Serializable, StructLayout(LayoutKind.Sequential)] |
||
| 80 | public struct Half : ISerializable, IComparable<Half>, IFormattable, IEquatable<Half> |
||
| 81 | { |
||
| 82 | #region Internal Field |
||
| 83 | |||
| 84 | UInt16 bits; |
||
| 85 | |||
| 86 | #endregion Internal Field |
||
| 87 | |||
| 88 | #region Properties |
||
| 89 | |||
| 90 | /// <summary>Returns true if the Half is zero.</summary> |
||
| 91 | public bool IsZero { get { return (bits == 0) || (bits == 0x8000); } } |
||
| 92 | |||
| 93 | /// <summary>Returns true if the Half represents Not A Number (NaN)</summary> |
||
| 94 | public bool IsNaN { get { return (((bits & 0x7C00) == 0x7C00) && (bits & 0x03FF) != 0x0000); } } |
||
| 95 | |||
| 96 | /// <summary>Returns true if the Half represents positive infinity.</summary> |
||
| 97 | public bool IsPositiveInfinity { get { return (bits == 31744); } } |
||
| 98 | |||
| 99 | /// <summary>Returns true if the Half represents negative infinity.</summary> |
||
| 100 | public bool IsNegativeInfinity { get { return (bits == 64512); } } |
||
| 101 | |||
| 102 | #endregion Properties |
||
| 103 | |||
| 104 | #region Constructors |
||
| 105 | |||
| 106 | /// <summary> |
||
| 107 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 108 | /// </summary> |
||
| 109 | /// <param name="f">32-bit single-precision floating-point number.</param> |
||
| 110 | public Half(Single f) |
||
| 111 | : this() |
||
| 112 | { |
||
| 113 | unsafe |
||
| 114 | { |
||
| 115 | bits = SingleToHalf(*(int*)&f); |
||
| 116 | } |
||
| 117 | } |
||
| 118 | |||
| 119 | /// <summary> |
||
| 120 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 121 | /// </summary> |
||
| 122 | /// <param name="f">32-bit single-precision floating-point number.</param> |
||
| 123 | /// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param> |
||
| 124 | public Half(Single f, bool throwOnError) |
||
| 125 | : this(f) |
||
| 126 | { |
||
| 127 | if (throwOnError) |
||
| 128 | { |
||
| 129 | // handle cases that cause overflow rather than silently ignoring it |
||
| 130 | if (f > Half.MaxValue) throw new ArithmeticException("Half: Positive maximum value exceeded."); |
||
| 131 | if (f < -Half.MaxValue) throw new ArithmeticException("Half: Negative minimum value exceeded."); |
||
| 132 | |||
| 133 | // handle cases that make no sense |
||
| 134 | if (Single.IsNaN(f)) throw new ArithmeticException("Half: Input is not a number (NaN)."); |
||
| 135 | if (Single.IsPositiveInfinity(f)) throw new ArithmeticException("Half: Input is positive infinity."); |
||
| 136 | if (Single.IsNegativeInfinity(f)) throw new ArithmeticException("Half: Input is negative infinity."); |
||
| 137 | } |
||
| 138 | } |
||
| 139 | |||
| 140 | /// <summary> |
||
| 141 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 142 | /// </summary> |
||
| 143 | /// <param name="d">64-bit double-precision floating-point number.</param> |
||
| 144 | public Half(Double d) : this((Single)d) { } |
||
| 145 | |||
| 146 | /// <summary> |
||
| 147 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 148 | /// </summary> |
||
| 149 | /// <param name="d">64-bit double-precision floating-point number.</param> |
||
| 150 | /// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param> |
||
| 151 | public Half(Double d, bool throwOnError) : this((Single)d, throwOnError) { } |
||
| 152 | |||
| 153 | #endregion Constructors |
||
| 154 | |||
| 155 | #region Single -> Half |
||
| 156 | |||
| 157 | /// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary> |
||
| 158 | private UInt16 SingleToHalf(Int32 si32) |
||
| 159 | { |
||
| 160 | // Our floating point number, F, is represented by the bit pattern in integer i. |
||
| 161 | // Disassemble that bit pattern into the sign, S, the exponent, E, and the significand, M. |
||
| 162 | // Shift S into the position where it will go in in the resulting half number. |
||
| 163 | // Adjust E, accounting for the different exponent bias of float and half (127 versus 15). |
||
| 164 | |||
| 165 | Int32 sign = (si32 >> 16) & 0x00008000; |
||
| 166 | Int32 exponent = ((si32 >> 23) & 0x000000ff) - (127 - 15); |
||
| 167 | Int32 mantissa = si32 & 0x007fffff; |
||
| 168 | |||
| 169 | // Now reassemble S, E and M into a half: |
||
| 170 | |||
| 171 | if (exponent <= 0) |
||
| 172 | { |
||
| 173 | if (exponent < -10) |
||
| 174 | { |
||
| 175 | // E is less than -10. The absolute value of F is less than Half.MinValue |
||
| 176 | // (F may be a small normalized float, a denormalized float or a zero). |
||
| 177 | // |
||
| 178 | // We convert F to a half zero with the same sign as F. |
||
| 179 | |||
| 180 | return (UInt16)sign; |
||
| 181 | } |
||
| 182 | |||
| 183 | // E is between -10 and 0. F is a normalized float whose magnitude is less than Half.MinNormalizedValue. |
||
| 184 | // |
||
| 185 | // We convert F to a denormalized half. |
||
| 186 | |||
| 187 | // Add an explicit leading 1 to the significand. |
||
| 188 | |||
| 189 | mantissa = mantissa | 0x00800000; |
||
| 190 | |||
| 191 | // Round to M to the nearest (10+E)-bit value (with E between -10 and 0); in case of a tie, round to the nearest even value. |
||
| 192 | // |
||
| 193 | // Rounding may cause the significand to overflow and make our number normalized. Because of the way a half's bits |
||
| 194 | // are laid out, we don't have to treat this case separately; the code below will handle it correctly. |
||
| 195 | |||
| 196 | Int32 t = 14 - exponent; |
||
| 197 | Int32 a = (1 << (t - 1)) - 1; |
||
| 198 | Int32 b = (mantissa >> t) & 1; |
||
| 199 | |||
| 200 | mantissa = (mantissa + a + b) >> t; |
||
| 201 | |||
| 202 | // Assemble the half from S, E (==zero) and M. |
||
| 203 | |||
| 204 | return (UInt16)(sign | mantissa); |
||
| 205 | } |
||
| 206 | else if (exponent == 0xff - (127 - 15)) |
||
| 207 | { |
||
| 208 | if (mantissa == 0) |
||
| 209 | { |
||
| 210 | // F is an infinity; convert F to a half infinity with the same sign as F. |
||
| 211 | |||
| 212 | return (UInt16)(sign | 0x7c00); |
||
| 213 | } |
||
| 214 | else |
||
| 215 | { |
||
| 216 | // F is a NAN; we produce a half NAN that preserves the sign bit and the 10 leftmost bits of the |
||
| 217 | // significand of F, with one exception: If the 10 leftmost bits are all zero, the NAN would turn |
||
| 218 | // into an infinity, so we have to set at least one bit in the significand. |
||
| 219 | |||
| 220 | mantissa >>= 13; |
||
| 221 | return (UInt16)(sign | 0x7c00 | mantissa | ((mantissa == 0) ? 1 : 0)); |
||
| 222 | } |
||
| 223 | } |
||
| 224 | else |
||
| 225 | { |
||
| 226 | // E is greater than zero. F is a normalized float. We try to convert F to a normalized half. |
||
| 227 | |||
| 228 | // Round to M to the nearest 10-bit value. In case of a tie, round to the nearest even value. |
||
| 229 | |||
| 230 | mantissa = mantissa + 0x00000fff + ((mantissa >> 13) & 1); |
||
| 231 | |||
| 232 | if ((mantissa & 0x00800000) == 1) |
||
| 233 | { |
||
| 234 | mantissa = 0; // overflow in significand, |
||
| 235 | exponent += 1; // adjust exponent |
||
| 236 | } |
||
| 237 | |||
| 238 | // exponent overflow |
||
| 239 | if (exponent > 30) throw new ArithmeticException("Half: Hardware floating-point overflow."); |
||
| 240 | |||
| 241 | // Assemble the half from S, E and M. |
||
| 242 | |||
| 243 | return (UInt16)(sign | (exponent << 10) | (mantissa >> 13)); |
||
| 244 | } |
||
| 245 | } |
||
| 246 | |||
| 247 | #endregion Single -> Half |
||
| 248 | |||
| 249 | #region Half -> Single |
||
| 250 | |||
| 251 | /// <summary>Converts the 16-bit half to 32-bit floating-point.</summary> |
||
| 252 | /// <returns>A single-precision floating-point number.</returns> |
||
| 253 | public Single ToSingle() |
||
| 254 | { |
||
| 255 | int i = HalfToFloat(bits); |
||
| 256 | |||
| 257 | unsafe |
||
| 258 | { |
||
| 259 | return *(float*)&i; |
||
| 260 | } |
||
| 261 | } |
||
| 262 | |||
| 263 | /// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary> |
||
| 264 | private Int32 HalfToFloat(UInt16 ui16) |
||
| 265 | { |
||
| 266 | |||
| 267 | Int32 sign = (ui16 >> 15) & 0x00000001; |
||
| 268 | Int32 exponent = (ui16 >> 10) & 0x0000001f; |
||
| 269 | Int32 mantissa = ui16 & 0x000003ff; |
||
| 270 | |||
| 271 | if (exponent == 0) |
||
| 272 | { |
||
| 273 | if (mantissa == 0) |
||
| 274 | { |
||
| 275 | // Plus or minus zero |
||
| 276 | |||
| 277 | return sign << 31; |
||
| 278 | } |
||
| 279 | else |
||
| 280 | { |
||
| 281 | // Denormalized number -- renormalize it |
||
| 282 | |||
| 283 | while ((mantissa & 0x00000400) == 0) |
||
| 284 | { |
||
| 285 | mantissa <<= 1; |
||
| 286 | exponent -= 1; |
||
| 287 | } |
||
| 288 | |||
| 289 | exponent += 1; |
||
| 290 | mantissa &= ~0x00000400; |
||
| 291 | } |
||
| 292 | } |
||
| 293 | else if (exponent == 31) |
||
| 294 | { |
||
| 295 | if (mantissa == 0) |
||
| 296 | { |
||
| 297 | // Positive or negative infinity |
||
| 298 | |||
| 299 | return (sign << 31) | 0x7f800000; |
||
| 300 | } |
||
| 301 | else |
||
| 302 | { |
||
| 303 | // Nan -- preserve sign and significand bits |
||
| 304 | |||
| 305 | return (sign << 31) | 0x7f800000 | (mantissa << 13); |
||
| 306 | } |
||
| 307 | } |
||
| 308 | |||
| 309 | // Normalized number |
||
| 310 | |||
| 311 | exponent = exponent + (127 - 15); |
||
| 312 | mantissa = mantissa << 13; |
||
| 313 | |||
| 314 | // Assemble S, E and M. |
||
| 315 | |||
| 316 | return (sign << 31) | (exponent << 23) | mantissa; |
||
| 317 | } |
||
| 318 | |||
| 319 | #endregion Half -> Single |
||
| 320 | |||
| 321 | #region Conversions |
||
| 322 | |||
| 323 | /// <summary> |
||
| 324 | /// Converts a System.Single to a OpenTK.Half. |
||
| 325 | /// </summary> |
||
| 326 | /// <param name="f">The value to convert. |
||
| 327 | /// A <see cref="System.Single"/> |
||
| 328 | /// </param> |
||
| 329 | /// <returns>The result of the conversion. |
||
| 330 | /// A <see cref="Half"/> |
||
| 331 | /// </returns> |
||
| 332 | public static explicit operator Half(float f) |
||
| 333 | { |
||
| 334 | return new Half(f); |
||
| 335 | } |
||
| 336 | |||
| 337 | /// <summary> |
||
| 338 | /// Converts a System.Double to a OpenTK.Half. |
||
| 339 | /// </summary> |
||
| 340 | /// <param name="d">The value to convert. |
||
| 341 | /// A <see cref="System.Double"/> |
||
| 342 | /// </param> |
||
| 343 | /// <returns>The result of the conversion. |
||
| 344 | /// A <see cref="Half"/> |
||
| 345 | /// </returns> |
||
| 346 | public static explicit operator Half(double d) |
||
| 347 | { |
||
| 348 | return new Half(d); |
||
| 349 | } |
||
| 350 | |||
| 351 | /// <summary> |
||
| 352 | /// Converts a OpenTK.Half to a System.Single. |
||
| 353 | /// </summary> |
||
| 354 | /// <param name="h">The value to convert. |
||
| 355 | /// A <see cref="Half"/> |
||
| 356 | /// </param> |
||
| 357 | /// <returns>The result of the conversion. |
||
| 358 | /// A <see cref="System.Single"/> |
||
| 359 | /// </returns> |
||
| 360 | public static implicit operator float(Half h) |
||
| 361 | { |
||
| 362 | return h.ToSingle(); |
||
| 363 | } |
||
| 364 | |||
| 365 | /// <summary> |
||
| 366 | /// Converts a OpenTK.Half to a System.Double. |
||
| 367 | /// </summary> |
||
| 368 | /// <param name="h">The value to convert. |
||
| 369 | /// A <see cref="Half"/> |
||
| 370 | /// </param> |
||
| 371 | /// <returns>The result of the conversion. |
||
| 372 | /// A <see cref="System.Double"/> |
||
| 373 | /// </returns> |
||
| 374 | public static implicit operator double(Half h) |
||
| 375 | { |
||
| 376 | return (double)h.ToSingle(); |
||
| 377 | } |
||
| 378 | |||
| 379 | #endregion Conversions |
||
| 380 | |||
| 381 | #region Constants |
||
| 382 | |||
| 383 | /// <summary>The size in bytes for an instance of the Half struct.</summary> |
||
| 384 | public static readonly Int32 SizeInBytes = 2; |
||
| 385 | |||
| 386 | /// <summary>Smallest positive half</summary> |
||
| 387 | public static readonly Single MinValue = 5.96046448e-08f; |
||
| 388 | |||
| 389 | /// <summary>Smallest positive normalized half</summary> |
||
| 390 | public static readonly Single MinNormalizedValue = 6.10351562e-05f; |
||
| 391 | |||
| 392 | /// <summary>Largest positive half</summary> |
||
| 393 | public static readonly Single MaxValue = 65504.0f; |
||
| 394 | |||
| 395 | /// <summary>Smallest positive e for which half (1.0 + e) != half (1.0)</summary> |
||
| 396 | public static readonly Single Epsilon = 0.00097656f; |
||
| 397 | |||
| 398 | #endregion Constants |
||
| 399 | |||
| 400 | #region ISerializable |
||
| 401 | |||
| 402 | /// <summary>Constructor used by ISerializable to deserialize the object.</summary> |
||
| 403 | /// <param name="info"></param> |
||
| 404 | /// <param name="context"></param> |
||
| 405 | public Half(SerializationInfo info, StreamingContext context) |
||
| 406 | { |
||
| 407 | this.bits = (ushort)info.GetValue("bits", typeof(ushort)); |
||
| 408 | } |
||
| 409 | |||
| 410 | /// <summary>Used by ISerialize to serialize the object.</summary> |
||
| 411 | /// <param name="info"></param> |
||
| 412 | /// <param name="context"></param> |
||
| 413 | public void GetObjectData(SerializationInfo info, StreamingContext context) |
||
| 414 | { |
||
| 415 | info.AddValue("bits", this.bits); |
||
| 416 | } |
||
| 417 | |||
| 418 | #endregion ISerializable |
||
| 419 | |||
| 420 | #region Binary dump |
||
| 421 | |||
| 422 | /// <summary>Updates the Half by reading from a Stream.</summary> |
||
| 423 | /// <param name="bin">A BinaryReader instance associated with an open Stream.</param> |
||
| 424 | public void FromBinaryStream(BinaryReader bin) |
||
| 425 | { |
||
| 426 | this.bits = bin.ReadUInt16(); |
||
| 427 | |||
| 428 | } |
||
| 429 | |||
| 430 | /// <summary>Writes the Half into a Stream.</summary> |
||
| 431 | /// <param name="bin">A BinaryWriter instance associated with an open Stream.</param> |
||
| 432 | public void ToBinaryStream(BinaryWriter bin) |
||
| 433 | { |
||
| 434 | bin.Write(this.bits); |
||
| 435 | } |
||
| 436 | |||
| 437 | #endregion Binary dump |
||
| 438 | |||
| 439 | #region IEquatable<Half> Members |
||
| 440 | |||
| 441 | const int maxUlps = 1; |
||
| 442 | |||
| 443 | /// <summary> |
||
| 444 | /// Returns a value indicating whether this instance is equal to a specified OpenTK.Half value. |
||
| 445 | /// </summary> |
||
| 446 | /// <param name="other">OpenTK.Half object to compare to this instance..</param> |
||
| 447 | /// <returns>True, if other is equal to this instance; false otherwise.</returns> |
||
| 448 | public bool Equals(Half other) |
||
| 449 | { |
||
| 450 | short aInt, bInt; |
||
| 451 | unchecked { aInt = (short)other.bits; } |
||
| 452 | unchecked { bInt = (short)this.bits; } |
||
| 453 | |||
| 454 | // Make aInt lexicographically ordered as a twos-complement int |
||
| 455 | if (aInt < 0) |
||
| 456 | aInt = (short)(0x8000 - aInt); |
||
| 457 | |||
| 458 | // Make bInt lexicographically ordered as a twos-complement int |
||
| 459 | if (bInt < 0) |
||
| 460 | bInt = (short)(0x8000 - bInt); |
||
| 461 | |||
| 462 | short intDiff = System.Math.Abs((short)(aInt - bInt)); |
||
| 463 | |||
| 464 | if (intDiff <= maxUlps) |
||
| 465 | return true; |
||
| 466 | |||
| 467 | return false; |
||
| 468 | } |
||
| 469 | |||
| 470 | #endregion |
||
| 471 | |||
| 472 | #region IComparable<Half> Members |
||
| 473 | |||
| 474 | /// <summary> |
||
| 475 | /// Compares this instance to a specified half-precision floating-point number |
||
| 476 | /// and returns an integer that indicates whether the value of this instance |
||
| 477 | /// is less than, equal to, or greater than the value of the specified half-precision |
||
| 478 | /// floating-point number. |
||
| 479 | /// </summary> |
||
| 480 | /// <param name="other">A half-precision floating-point number to compare.</param> |
||
| 481 | /// <returns> |
||
| 482 | /// A signed number indicating the relative values of this instance and value. If the number is: |
||
| 483 | /// <para>Less than zero, then this instance is less than other, or this instance is not a number |
||
| 484 | /// (OpenTK.Half.NaN) and other is a number.</para> |
||
| 485 | /// <para>Zero: this instance is equal to value, or both this instance and other |
||
| 486 | /// are not a number (OpenTK.Half.NaN), OpenTK.Half.PositiveInfinity, or |
||
| 487 | /// OpenTK.Half.NegativeInfinity.</para> |
||
| 488 | /// <para>Greater than zero: this instance is greater than othrs, or this instance is a number |
||
| 489 | /// and other is not a number (OpenTK.Half.NaN).</para> |
||
| 490 | /// </returns> |
||
| 491 | public int CompareTo(Half other) |
||
| 492 | { |
||
| 493 | return ((float)this).CompareTo((float)other); |
||
| 494 | } |
||
| 495 | |||
| 496 | #endregion IComparable<Half> Members |
||
| 497 | |||
| 498 | #region IFormattable Members |
||
| 499 | |||
| 500 | /// <summary>Converts this Half into a human-legible string representation.</summary> |
||
| 501 | /// <returns>The string representation of this instance.</returns> |
||
| 502 | public override string ToString() |
||
| 503 | { |
||
| 504 | return this.ToSingle().ToString(); |
||
| 505 | } |
||
| 506 | |||
| 507 | /// <summary>Converts this Half into a human-legible string representation.</summary> |
||
| 508 | /// <param name="format">Formatting for the output string.</param> |
||
| 509 | /// <param name="formatProvider">Culture-specific formatting information.</param> |
||
| 510 | /// <returns>The string representation of this instance.</returns> |
||
| 511 | public string ToString(string format, IFormatProvider formatProvider) |
||
| 512 | { |
||
| 513 | return this.ToSingle().ToString(format, formatProvider); |
||
| 514 | } |
||
| 515 | |||
| 516 | #endregion IFormattable Members |
||
| 517 | |||
| 518 | #region String -> Half |
||
| 519 | |||
| 520 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent.</summary> |
||
| 521 | /// <param name="s">String representation of the number to convert.</param> |
||
| 522 | /// <returns>A new Half instance.</returns> |
||
| 523 | public static Half Parse(string s) |
||
| 524 | { |
||
| 525 | return (Half)Single.Parse(s); |
||
| 526 | } |
||
| 527 | |||
| 528 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent.</summary> |
||
| 529 | /// <param name="s">String representation of the number to convert.</param> |
||
| 530 | /// <param name="style">Specifies the format of s.</param> |
||
| 531 | /// <param name="provider">Culture-specific formatting information.</param> |
||
| 532 | /// <returns>A new Half instance.</returns> |
||
| 533 | public static Half Parse(string s, System.Globalization.NumberStyles style, IFormatProvider provider) |
||
| 534 | { |
||
| 535 | return (Half)Single.Parse(s, style, provider); |
||
| 536 | } |
||
| 537 | |||
| 538 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent. Returns success.</summary> |
||
| 539 | /// <param name="s">String representation of the number to convert.</param> |
||
| 540 | /// <param name="result">The Half instance to write to.</param> |
||
| 541 | /// <returns>Success.</returns> |
||
| 542 | public static bool TryParse(string s, out Half result) |
||
| 543 | { |
||
| 544 | float f; |
||
| 545 | bool b = Single.TryParse(s, out f); |
||
| 546 | result = (Half)f; |
||
| 547 | return b; |
||
| 548 | } |
||
| 549 | |||
| 550 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent. Returns success.</summary> |
||
| 551 | /// <param name="s">string representation of the number to convert.</param> |
||
| 552 | /// <param name="style">specifies the format of s.</param> |
||
| 553 | /// <param name="provider">Culture-specific formatting information.</param> |
||
| 554 | /// <param name="result">The Half instance to write to.</param> |
||
| 555 | /// <returns>Success.</returns> |
||
| 556 | public static bool TryParse(string s, System.Globalization.NumberStyles style, IFormatProvider provider, out Half result) |
||
| 557 | { |
||
| 558 | float f; |
||
| 559 | bool b = Single.TryParse(s, style, provider, out f); |
||
| 560 | result = (Half)f; |
||
| 561 | return b; |
||
| 562 | } |
||
| 563 | |||
| 564 | #endregion String -> Half |
||
| 565 | |||
| 566 | #region BitConverter |
||
| 567 | |||
| 568 | /// <summary>Returns the Half as an array of bytes.</summary> |
||
| 569 | /// <param name="h">The Half to convert.</param> |
||
| 570 | /// <returns>The input as byte array.</returns> |
||
| 571 | public static byte[] GetBytes(Half h) |
||
| 572 | { |
||
| 573 | return BitConverter.GetBytes(h.bits); |
||
| 574 | } |
||
| 575 | |||
| 576 | /// <summary>Converts an array of bytes into Half.</summary> |
||
| 577 | /// <param name="value">A Half in it's byte[] representation.</param> |
||
| 578 | /// <param name="startIndex">The starting position within value.</param> |
||
| 579 | /// <returns>A new Half instance.</returns> |
||
| 580 | public static Half FromBytes(byte[] value, int startIndex) |
||
| 581 | { |
||
| 582 | Half h; |
||
| 583 | h.bits = BitConverter.ToUInt16(value, startIndex); |
||
| 584 | return h; |
||
| 585 | } |
||
| 586 | |||
| 587 | #endregion BitConverter |
||
| 588 | } |
||
| 589 | } |