markus / KCOM / WrapPanel / NumericExtensions.cs @ ac4f1e13
이력 | 보기 | 이력해설 | 다운로드 (4.42 KB)
1 |
// (c) Copyright Microsoft Corporation. |
---|---|
2 |
// This source is subject to the Microsoft Public License (Ms-PL). |
3 |
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. |
4 |
// All other rights reserved. |
5 |
|
6 |
using System; |
7 |
using System.Diagnostics.CodeAnalysis; |
8 |
using System.Runtime.InteropServices; |
9 |
|
10 |
namespace System.Windows.Controls |
11 |
{ |
12 |
/// <summary> |
13 |
/// Numeric utility methods used by controls. These methods are similar in |
14 |
/// scope to the WPF DoubleUtil class. |
15 |
/// </summary> |
16 |
internal static class NumericExtensions |
17 |
{ |
18 |
/// <summary> |
19 |
/// NanUnion is a C++ style type union used for efficiently converting |
20 |
/// a double into an unsigned long, whose bits can be easily |
21 |
/// manipulated. |
22 |
/// </summary> |
23 |
[StructLayout(LayoutKind.Explicit)] |
24 |
private struct NanUnion |
25 |
{ |
26 |
/// <summary> |
27 |
/// Floating point representation of the union. |
28 |
/// </summary> |
29 |
[SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "It is accessed through the other member of the union")] |
30 |
[FieldOffset(0)] |
31 |
internal double FloatingValue; |
32 |
|
33 |
/// <summary> |
34 |
/// Integer representation of the union. |
35 |
/// </summary> |
36 |
[FieldOffset(0)] |
37 |
internal ulong IntegerValue; |
38 |
} |
39 |
|
40 |
/// <summary> |
41 |
/// Check if a number is zero. |
42 |
/// </summary> |
43 |
/// <param name="value">The number to check.</param> |
44 |
/// <returns>True if the number is zero, false otherwise.</returns> |
45 |
public static bool IsZero(this double value) |
46 |
{ |
47 |
// We actually consider anything within an order of magnitude of |
48 |
// epsilon to be zero |
49 |
return Math.Abs(value) < 2.2204460492503131E-15; |
50 |
} |
51 |
|
52 |
/// <summary> |
53 |
/// Check if a number isn't really a number. |
54 |
/// </summary> |
55 |
/// <param name="value">The number to check.</param> |
56 |
/// <returns> |
57 |
/// True if the number is not a number, false if it is a number. |
58 |
/// </returns> |
59 |
public static bool IsNaN(this double value) |
60 |
{ |
61 |
// Get the double as an unsigned long |
62 |
NanUnion union = new NanUnion { FloatingValue = value }; |
63 |
|
64 |
// An IEEE 754 double precision floating point number is NaN if its |
65 |
// exponent equals 2047 and it has a non-zero mantissa. |
66 |
ulong exponent = union.IntegerValue & 0xfff0000000000000L; |
67 |
if ((exponent != 0x7ff0000000000000L) && (exponent != 0xfff0000000000000L)) |
68 |
{ |
69 |
return false; |
70 |
} |
71 |
ulong mantissa = union.IntegerValue & 0x000fffffffffffffL; |
72 |
return mantissa != 0L; |
73 |
} |
74 |
|
75 |
/// <summary> |
76 |
/// Determine if one number is greater than another. |
77 |
/// </summary> |
78 |
/// <param name="left">First number.</param> |
79 |
/// <param name="right">Second number.</param> |
80 |
/// <returns> |
81 |
/// True if the first number is greater than the second, false |
82 |
/// otherwise. |
83 |
/// </returns> |
84 |
public static bool IsGreaterThan(double left, double right) |
85 |
{ |
86 |
return (left > right) && !AreClose(left, right); |
87 |
} |
88 |
|
89 |
/// <summary> |
90 |
/// Determine if one number is less than or close to another. |
91 |
/// </summary> |
92 |
/// <param name="left">First number.</param> |
93 |
/// <param name="right">Second number.</param> |
94 |
/// <returns> |
95 |
/// True if the first number is less than or close to the second, false |
96 |
/// otherwise. |
97 |
/// </returns> |
98 |
public static bool IsLessThanOrClose(double left, double right) |
99 |
{ |
100 |
return (left < right) || AreClose(left, right); |
101 |
} |
102 |
|
103 |
/// <summary> |
104 |
/// Determine if two numbers are close in value. |
105 |
/// </summary> |
106 |
/// <param name="left">First number.</param> |
107 |
/// <param name="right">Second number.</param> |
108 |
/// <returns> |
109 |
/// True if the first number is close in value to the second, false |
110 |
/// otherwise. |
111 |
/// </returns> |
112 |
public static bool AreClose(double left, double right) |
113 |
{ |
114 |
if (left == right) |
115 |
{ |
116 |
return true; |
117 |
} |
118 |
|
119 |
double a = (Math.Abs(left) + Math.Abs(right) + 10.0) * 2.2204460492503131E-16; |
120 |
double b = left - right; |
121 |
return (-a < b) && (a > b); |
122 |
} |
123 |
} |
124 |
} |