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 |
||
| 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 | [Serializable, StructLayout(LayoutKind.Sequential)] |
||
| 79 | public struct Half : ISerializable, IComparable<Half>, IFormattable, IEquatable<Half> |
||
| 80 | { |
||
| 81 | #region Internal Field |
||
| 82 | |||
| 83 | UInt16 bits; |
||
| 84 | |||
| 85 | #endregion Internal Field |
||
| 86 | |||
| 87 | #region Properties |
||
| 88 | |||
| 89 | /// <summary>Returns true if the Half is zero.</summary> |
||
| 90 | public bool IsZero { get { return (bits == 0) || (bits == 0x8000); } } |
||
| 91 | |||
| 92 | /// <summary>Returns true if the Half represents Not A Number (NaN)</summary> |
||
| 93 | public bool IsNaN { get { return (((bits & 0x7C00) == 0x7C00) && (bits & 0x03FF) != 0x0000); } } |
||
| 94 | |||
| 95 | /// <summary>Returns true if the Half represents positive infinity.</summary> |
||
| 96 | public bool IsPositiveInfinity { get { return (bits == 31744); } } |
||
| 97 | |||
| 98 | /// <summary>Returns true if the Half represents negative infinity.</summary> |
||
| 99 | public bool IsNegativeInfinity { get { return (bits == 64512); } } |
||
| 100 | |||
| 101 | #endregion Properties |
||
| 102 | |||
| 103 | #region Constructors |
||
| 104 | |||
| 105 | /// <summary> |
||
| 106 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 107 | /// </summary> |
||
| 108 | /// <param name="f">32-bit single-precision floating-point number.</param> |
||
| 109 | public Half(Single f) |
||
| 110 | : this() |
||
| 111 | { |
||
| 112 | unsafe |
||
| 113 | { |
||
| 114 | bits = SingleToHalf(*(int*)&f); |
||
| 115 | } |
||
| 116 | } |
||
| 117 | |||
| 118 | /// <summary> |
||
| 119 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 120 | /// </summary> |
||
| 121 | /// <param name="f">32-bit single-precision floating-point number.</param> |
||
| 122 | /// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param> |
||
| 123 | public Half(Single f, bool throwOnError) |
||
| 124 | : this(f) |
||
| 125 | { |
||
| 126 | if (throwOnError) |
||
| 127 | { |
||
| 128 | // handle cases that cause overflow rather than silently ignoring it |
||
| 129 | if (f > Half.MaxValue) throw new ArithmeticException("Half: Positive maximum value exceeded."); |
||
| 130 | if (f < -Half.MaxValue) throw new ArithmeticException("Half: Negative minimum value exceeded."); |
||
| 131 | |||
| 132 | // handle cases that make no sense |
||
| 133 | if (Single.IsNaN(f)) throw new ArithmeticException("Half: Input is not a number (NaN)."); |
||
| 134 | if (Single.IsPositiveInfinity(f)) throw new ArithmeticException("Half: Input is positive infinity."); |
||
| 135 | if (Single.IsNegativeInfinity(f)) throw new ArithmeticException("Half: Input is negative infinity."); |
||
| 136 | } |
||
| 137 | } |
||
| 138 | |||
| 139 | /// <summary> |
||
| 140 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 141 | /// </summary> |
||
| 142 | /// <param name="d">64-bit double-precision floating-point number.</param> |
||
| 143 | public Half(Double d) : this((Single)d) { } |
||
| 144 | |||
| 145 | /// <summary> |
||
| 146 | /// The new Half instance will convert the parameter into 16-bit half-precision floating-point. |
||
| 147 | /// </summary> |
||
| 148 | /// <param name="d">64-bit double-precision floating-point number.</param> |
||
| 149 | /// <param name="throwOnError">Enable checks that will throw if the conversion result is not meaningful.</param> |
||
| 150 | public Half(Double d, bool throwOnError) : this((Single)d, throwOnError) { } |
||
| 151 | |||
| 152 | #endregion Constructors |
||
| 153 | |||
| 154 | #region Single -> Half |
||
| 155 | |||
| 156 | /// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary> |
||
| 157 | private UInt16 SingleToHalf(Int32 si32) |
||
| 158 | { |
||
| 159 | // Our floating point number, F, is represented by the bit pattern in integer i. |
||
| 160 | // Disassemble that bit pattern into the sign, S, the exponent, E, and the significand, M. |
||
| 161 | // Shift S into the position where it will go in in the resulting half number. |
||
| 162 | // Adjust E, accounting for the different exponent bias of float and half (127 versus 15). |
||
| 163 | |||
| 164 | Int32 sign = (si32 >> 16) & 0x00008000; |
||
| 165 | Int32 exponent = ((si32 >> 23) & 0x000000ff) - (127 - 15); |
||
| 166 | Int32 mantissa = si32 & 0x007fffff; |
||
| 167 | |||
| 168 | // Now reassemble S, E and M into a half: |
||
| 169 | |||
| 170 | if (exponent <= 0) |
||
| 171 | { |
||
| 172 | if (exponent < -10) |
||
| 173 | { |
||
| 174 | // E is less than -10. The absolute value of F is less than Half.MinValue |
||
| 175 | // (F may be a small normalized float, a denormalized float or a zero). |
||
| 176 | // |
||
| 177 | // We convert F to a half zero with the same sign as F. |
||
| 178 | |||
| 179 | return (UInt16)sign; |
||
| 180 | } |
||
| 181 | |||
| 182 | // E is between -10 and 0. F is a normalized float whose magnitude is less than Half.MinNormalizedValue. |
||
| 183 | // |
||
| 184 | // We convert F to a denormalized half. |
||
| 185 | |||
| 186 | // Add an explicit leading 1 to the significand. |
||
| 187 | |||
| 188 | mantissa = mantissa | 0x00800000; |
||
| 189 | |||
| 190 | // 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. |
||
| 191 | // |
||
| 192 | // Rounding may cause the significand to overflow and make our number normalized. Because of the way a half's bits |
||
| 193 | // are laid out, we don't have to treat this case separately; the code below will handle it correctly. |
||
| 194 | |||
| 195 | Int32 t = 14 - exponent; |
||
| 196 | Int32 a = (1 << (t - 1)) - 1; |
||
| 197 | Int32 b = (mantissa >> t) & 1; |
||
| 198 | |||
| 199 | mantissa = (mantissa + a + b) >> t; |
||
| 200 | |||
| 201 | // Assemble the half from S, E (==zero) and M. |
||
| 202 | |||
| 203 | return (UInt16)(sign | mantissa); |
||
| 204 | } |
||
| 205 | else if (exponent == 0xff - (127 - 15)) |
||
| 206 | { |
||
| 207 | if (mantissa == 0) |
||
| 208 | { |
||
| 209 | // F is an infinity; convert F to a half infinity with the same sign as F. |
||
| 210 | |||
| 211 | return (UInt16)(sign | 0x7c00); |
||
| 212 | } |
||
| 213 | else |
||
| 214 | { |
||
| 215 | // F is a NAN; we produce a half NAN that preserves the sign bit and the 10 leftmost bits of the |
||
| 216 | // significand of F, with one exception: If the 10 leftmost bits are all zero, the NAN would turn |
||
| 217 | // into an infinity, so we have to set at least one bit in the significand. |
||
| 218 | |||
| 219 | mantissa >>= 13; |
||
| 220 | return (UInt16)(sign | 0x7c00 | mantissa | ((mantissa == 0) ? 1 : 0)); |
||
| 221 | } |
||
| 222 | } |
||
| 223 | else |
||
| 224 | { |
||
| 225 | // E is greater than zero. F is a normalized float. We try to convert F to a normalized half. |
||
| 226 | |||
| 227 | // Round to M to the nearest 10-bit value. In case of a tie, round to the nearest even value. |
||
| 228 | |||
| 229 | mantissa = mantissa + 0x00000fff + ((mantissa >> 13) & 1); |
||
| 230 | |||
| 231 | if ((mantissa & 0x00800000) == 1) |
||
| 232 | { |
||
| 233 | mantissa = 0; // overflow in significand, |
||
| 234 | exponent += 1; // adjust exponent |
||
| 235 | } |
||
| 236 | |||
| 237 | // exponent overflow |
||
| 238 | if (exponent > 30) throw new ArithmeticException("Half: Hardware floating-point overflow."); |
||
| 239 | |||
| 240 | // Assemble the half from S, E and M. |
||
| 241 | |||
| 242 | return (UInt16)(sign | (exponent << 10) | (mantissa >> 13)); |
||
| 243 | } |
||
| 244 | } |
||
| 245 | |||
| 246 | #endregion Single -> Half |
||
| 247 | |||
| 248 | #region Half -> Single |
||
| 249 | |||
| 250 | /// <summary>Converts the 16-bit half to 32-bit floating-point.</summary> |
||
| 251 | /// <returns>A single-precision floating-point number.</returns> |
||
| 252 | public Single ToSingle() |
||
| 253 | { |
||
| 254 | int i = HalfToFloat(bits); |
||
| 255 | |||
| 256 | unsafe |
||
| 257 | { |
||
| 258 | return *(float*)&i; |
||
| 259 | } |
||
| 260 | } |
||
| 261 | |||
| 262 | /// <summary>Ported from OpenEXR's IlmBase 1.0.1</summary> |
||
| 263 | private Int32 HalfToFloat(UInt16 ui16) |
||
| 264 | { |
||
| 265 | |||
| 266 | Int32 sign = (ui16 >> 15) & 0x00000001; |
||
| 267 | Int32 exponent = (ui16 >> 10) & 0x0000001f; |
||
| 268 | Int32 mantissa = ui16 & 0x000003ff; |
||
| 269 | |||
| 270 | if (exponent == 0) |
||
| 271 | { |
||
| 272 | if (mantissa == 0) |
||
| 273 | { |
||
| 274 | // Plus or minus zero |
||
| 275 | |||
| 276 | return sign << 31; |
||
| 277 | } |
||
| 278 | else |
||
| 279 | { |
||
| 280 | // Denormalized number -- renormalize it |
||
| 281 | |||
| 282 | while ((mantissa & 0x00000400) == 0) |
||
| 283 | { |
||
| 284 | mantissa <<= 1; |
||
| 285 | exponent -= 1; |
||
| 286 | } |
||
| 287 | |||
| 288 | exponent += 1; |
||
| 289 | mantissa &= ~0x00000400; |
||
| 290 | } |
||
| 291 | } |
||
| 292 | else if (exponent == 31) |
||
| 293 | { |
||
| 294 | if (mantissa == 0) |
||
| 295 | { |
||
| 296 | // Positive or negative infinity |
||
| 297 | |||
| 298 | return (sign << 31) | 0x7f800000; |
||
| 299 | } |
||
| 300 | else |
||
| 301 | { |
||
| 302 | // Nan -- preserve sign and significand bits |
||
| 303 | |||
| 304 | return (sign << 31) | 0x7f800000 | (mantissa << 13); |
||
| 305 | } |
||
| 306 | } |
||
| 307 | |||
| 308 | // Normalized number |
||
| 309 | |||
| 310 | exponent = exponent + (127 - 15); |
||
| 311 | mantissa = mantissa << 13; |
||
| 312 | |||
| 313 | // Assemble S, E and M. |
||
| 314 | |||
| 315 | return (sign << 31) | (exponent << 23) | mantissa; |
||
| 316 | } |
||
| 317 | |||
| 318 | #endregion Half -> Single |
||
| 319 | |||
| 320 | #region Conversions |
||
| 321 | |||
| 322 | /// <summary> |
||
| 323 | /// Converts a System.Single to a OpenTK.Half. |
||
| 324 | /// </summary> |
||
| 325 | /// <param name="f">The value to convert. |
||
| 326 | /// A <see cref="System.Single"/> |
||
| 327 | /// </param> |
||
| 328 | /// <returns>The result of the conversion. |
||
| 329 | /// A <see cref="Half"/> |
||
| 330 | /// </returns> |
||
| 331 | public static explicit operator Half(float f) |
||
| 332 | { |
||
| 333 | return new Half(f); |
||
| 334 | } |
||
| 335 | |||
| 336 | /// <summary> |
||
| 337 | /// Converts a System.Double to a OpenTK.Half. |
||
| 338 | /// </summary> |
||
| 339 | /// <param name="d">The value to convert. |
||
| 340 | /// A <see cref="System.Double"/> |
||
| 341 | /// </param> |
||
| 342 | /// <returns>The result of the conversion. |
||
| 343 | /// A <see cref="Half"/> |
||
| 344 | /// </returns> |
||
| 345 | public static explicit operator Half(double d) |
||
| 346 | { |
||
| 347 | return new Half(d); |
||
| 348 | } |
||
| 349 | |||
| 350 | /// <summary> |
||
| 351 | /// Converts a OpenTK.Half to a System.Single. |
||
| 352 | /// </summary> |
||
| 353 | /// <param name="h">The value to convert. |
||
| 354 | /// A <see cref="Half"/> |
||
| 355 | /// </param> |
||
| 356 | /// <returns>The result of the conversion. |
||
| 357 | /// A <see cref="System.Single"/> |
||
| 358 | /// </returns> |
||
| 359 | public static implicit operator float(Half h) |
||
| 360 | { |
||
| 361 | return h.ToSingle(); |
||
| 362 | } |
||
| 363 | |||
| 364 | /// <summary> |
||
| 365 | /// Converts a OpenTK.Half to a System.Double. |
||
| 366 | /// </summary> |
||
| 367 | /// <param name="h">The value to convert. |
||
| 368 | /// A <see cref="Half"/> |
||
| 369 | /// </param> |
||
| 370 | /// <returns>The result of the conversion. |
||
| 371 | /// A <see cref="System.Double"/> |
||
| 372 | /// </returns> |
||
| 373 | public static implicit operator double(Half h) |
||
| 374 | { |
||
| 375 | return (double)h.ToSingle(); |
||
| 376 | } |
||
| 377 | |||
| 378 | #endregion Conversions |
||
| 379 | |||
| 380 | #region Constants |
||
| 381 | |||
| 382 | /// <summary>The size in bytes for an instance of the Half struct.</summary> |
||
| 383 | public static readonly Int32 SizeInBytes = 2; |
||
| 384 | |||
| 385 | /// <summary>Smallest positive half</summary> |
||
| 386 | public static readonly Single MinValue = 5.96046448e-08f; |
||
| 387 | |||
| 388 | /// <summary>Smallest positive normalized half</summary> |
||
| 389 | public static readonly Single MinNormalizedValue = 6.10351562e-05f; |
||
| 390 | |||
| 391 | /// <summary>Largest positive half</summary> |
||
| 392 | public static readonly Single MaxValue = 65504.0f; |
||
| 393 | |||
| 394 | /// <summary>Smallest positive e for which half (1.0 + e) != half (1.0)</summary> |
||
| 395 | public static readonly Single Epsilon = 0.00097656f; |
||
| 396 | |||
| 397 | #endregion Constants |
||
| 398 | |||
| 399 | #region ISerializable |
||
| 400 | |||
| 401 | /// <summary>Constructor used by ISerializable to deserialize the object.</summary> |
||
| 402 | /// <param name="info"></param> |
||
| 403 | /// <param name="context"></param> |
||
| 404 | public Half(SerializationInfo info, StreamingContext context) |
||
| 405 | { |
||
| 406 | this.bits = (ushort)info.GetValue("bits", typeof(ushort)); |
||
| 407 | } |
||
| 408 | |||
| 409 | /// <summary>Used by ISerialize to serialize the object.</summary> |
||
| 410 | /// <param name="info"></param> |
||
| 411 | /// <param name="context"></param> |
||
| 412 | public void GetObjectData(SerializationInfo info, StreamingContext context) |
||
| 413 | { |
||
| 414 | info.AddValue("bits", this.bits); |
||
| 415 | } |
||
| 416 | |||
| 417 | #endregion ISerializable |
||
| 418 | |||
| 419 | #region Binary dump |
||
| 420 | |||
| 421 | /// <summary>Updates the Half by reading from a Stream.</summary> |
||
| 422 | /// <param name="bin">A BinaryReader instance associated with an open Stream.</param> |
||
| 423 | public void FromBinaryStream(BinaryReader bin) |
||
| 424 | { |
||
| 425 | this.bits = bin.ReadUInt16(); |
||
| 426 | |||
| 427 | } |
||
| 428 | |||
| 429 | /// <summary>Writes the Half into a Stream.</summary> |
||
| 430 | /// <param name="bin">A BinaryWriter instance associated with an open Stream.</param> |
||
| 431 | public void ToBinaryStream(BinaryWriter bin) |
||
| 432 | { |
||
| 433 | bin.Write(this.bits); |
||
| 434 | } |
||
| 435 | |||
| 436 | #endregion Binary dump |
||
| 437 | |||
| 438 | #region IEquatable<Half> Members |
||
| 439 | |||
| 440 | const int maxUlps = 1; |
||
| 441 | |||
| 442 | /// <summary> |
||
| 443 | /// Returns a value indicating whether this instance is equal to a specified OpenTK.Half value. |
||
| 444 | /// </summary> |
||
| 445 | /// <param name="other">OpenTK.Half object to compare to this instance..</param> |
||
| 446 | /// <returns>True, if other is equal to this instance; false otherwise.</returns> |
||
| 447 | public bool Equals(Half other) |
||
| 448 | { |
||
| 449 | short aInt, bInt; |
||
| 450 | unchecked { aInt = (short)other.bits; } |
||
| 451 | unchecked { bInt = (short)this.bits; } |
||
| 452 | |||
| 453 | // Make aInt lexicographically ordered as a twos-complement int |
||
| 454 | if (aInt < 0) |
||
| 455 | aInt = (short)(0x8000 - aInt); |
||
| 456 | |||
| 457 | // Make bInt lexicographically ordered as a twos-complement int |
||
| 458 | if (bInt < 0) |
||
| 459 | bInt = (short)(0x8000 - bInt); |
||
| 460 | |||
| 461 | short intDiff = System.Math.Abs((short)(aInt - bInt)); |
||
| 462 | |||
| 463 | if (intDiff <= maxUlps) |
||
| 464 | return true; |
||
| 465 | |||
| 466 | return false; |
||
| 467 | } |
||
| 468 | |||
| 469 | #endregion |
||
| 470 | |||
| 471 | #region IComparable<Half> Members |
||
| 472 | |||
| 473 | /// <summary> |
||
| 474 | /// Compares this instance to a specified half-precision floating-point number |
||
| 475 | /// and returns an integer that indicates whether the value of this instance |
||
| 476 | /// is less than, equal to, or greater than the value of the specified half-precision |
||
| 477 | /// floating-point number. |
||
| 478 | /// </summary> |
||
| 479 | /// <param name="other">A half-precision floating-point number to compare.</param> |
||
| 480 | /// <returns> |
||
| 481 | /// A signed number indicating the relative values of this instance and value. If the number is: |
||
| 482 | /// <para>Less than zero, then this instance is less than other, or this instance is not a number |
||
| 483 | /// (OpenTK.Half.NaN) and other is a number.</para> |
||
| 484 | /// <para>Zero: this instance is equal to value, or both this instance and other |
||
| 485 | /// are not a number (OpenTK.Half.NaN), OpenTK.Half.PositiveInfinity, or |
||
| 486 | /// OpenTK.Half.NegativeInfinity.</para> |
||
| 487 | /// <para>Greater than zero: this instance is greater than othrs, or this instance is a number |
||
| 488 | /// and other is not a number (OpenTK.Half.NaN).</para> |
||
| 489 | /// </returns> |
||
| 490 | public int CompareTo(Half other) |
||
| 491 | { |
||
| 492 | return ((float)this).CompareTo((float)other); |
||
| 493 | } |
||
| 494 | |||
| 495 | #endregion IComparable<Half> Members |
||
| 496 | |||
| 497 | #region IFormattable Members |
||
| 498 | |||
| 499 | /// <summary>Converts this Half into a human-legible string representation.</summary> |
||
| 500 | /// <returns>The string representation of this instance.</returns> |
||
| 501 | public override string ToString() |
||
| 502 | { |
||
| 503 | return this.ToSingle().ToString(); |
||
| 504 | } |
||
| 505 | |||
| 506 | /// <summary>Converts this Half into a human-legible string representation.</summary> |
||
| 507 | /// <param name="format">Formatting for the output string.</param> |
||
| 508 | /// <param name="formatProvider">Culture-specific formatting information.</param> |
||
| 509 | /// <returns>The string representation of this instance.</returns> |
||
| 510 | public string ToString(string format, IFormatProvider formatProvider) |
||
| 511 | { |
||
| 512 | return this.ToSingle().ToString(format, formatProvider); |
||
| 513 | } |
||
| 514 | |||
| 515 | #endregion IFormattable Members |
||
| 516 | |||
| 517 | #region String -> Half |
||
| 518 | |||
| 519 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent.</summary> |
||
| 520 | /// <param name="s">String representation of the number to convert.</param> |
||
| 521 | /// <returns>A new Half instance.</returns> |
||
| 522 | public static Half Parse(string s) |
||
| 523 | { |
||
| 524 | return (Half)Single.Parse(s); |
||
| 525 | } |
||
| 526 | |||
| 527 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent.</summary> |
||
| 528 | /// <param name="s">String representation of the number to convert.</param> |
||
| 529 | /// <param name="style">Specifies the format of s.</param> |
||
| 530 | /// <param name="provider">Culture-specific formatting information.</param> |
||
| 531 | /// <returns>A new Half instance.</returns> |
||
| 532 | public static Half Parse(string s, System.Globalization.NumberStyles style, IFormatProvider provider) |
||
| 533 | { |
||
| 534 | return (Half)Single.Parse(s, style, provider); |
||
| 535 | } |
||
| 536 | |||
| 537 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent. Returns success.</summary> |
||
| 538 | /// <param name="s">String representation of the number to convert.</param> |
||
| 539 | /// <param name="result">The Half instance to write to.</param> |
||
| 540 | /// <returns>Success.</returns> |
||
| 541 | public static bool TryParse(string s, out Half result) |
||
| 542 | { |
||
| 543 | float f; |
||
| 544 | bool b = Single.TryParse(s, out f); |
||
| 545 | result = (Half)f; |
||
| 546 | return b; |
||
| 547 | } |
||
| 548 | |||
| 549 | /// <summary>Converts the string representation of a number to a half-precision floating-point equivalent. Returns success.</summary> |
||
| 550 | /// <param name="s">String representation of the number to convert.</param> |
||
| 551 | /// <param name="style">Specifies the format of s.</param> |
||
| 552 | /// <param name="provider">Culture-specific formatting information.</param> |
||
| 553 | /// <param name="result">The Half instance to write to.</param> |
||
| 554 | /// <returns>Success.</returns> |
||
| 555 | public static bool TryParse(string s, System.Globalization.NumberStyles style, IFormatProvider provider, out Half result) |
||
| 556 | { |
||
| 557 | float f; |
||
| 558 | bool b = Single.TryParse(s, style, provider, out f); |
||
| 559 | result = (Half)f; |
||
| 560 | return b; |
||
| 561 | } |
||
| 562 | |||
| 563 | #endregion String -> Half |
||
| 564 | |||
| 565 | #region BitConverter |
||
| 566 | |||
| 567 | /// <summary>Returns the Half as an array of bytes.</summary> |
||
| 568 | /// <param name="h">The Half to convert.</param> |
||
| 569 | /// <returns>The input as byte array.</returns> |
||
| 570 | public static byte[] GetBytes(Half h) |
||
| 571 | { |
||
| 572 | return BitConverter.GetBytes(h.bits); |
||
| 573 | } |
||
| 574 | |||
| 575 | /// <summary>Converts an array of bytes into Half.</summary> |
||
| 576 | /// <param name="value">A Half in it's byte[] representation.</param> |
||
| 577 | /// <param name="startIndex">The starting position within value.</param> |
||
| 578 | /// <returns>A new Half instance.</returns> |
||
| 579 | public static Half FromBytes(byte[] value, int startIndex) |
||
| 580 | { |
||
| 581 | Half h; |
||
| 582 | h.bits = BitConverter.ToUInt16(value, startIndex); |
||
| 583 | return h; |
||
| 584 | } |
||
| 585 | |||
| 586 | #endregion BitConverter |
||
| 587 | } |
||
| 588 | } |