| File: Utilities\ValueSetFactory.SingleTC.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { using static BinaryOperatorKind; internal static partial class ValueSetFactory { private class SingleTC : FloatingTC<float>, INumericTC<float> { public static readonly SingleTC Instance = new SingleTC(); float INumericTC<float>.MinValue => float.NegativeInfinity; float INumericTC<float>.MaxValue => float.PositiveInfinity; float FloatingTC<float>.NaN => float.NaN; float INumericTC<float>.Zero => 0; /// <summary> /// The implementation of Next depends critically on the internal representation of an IEEE floating-point /// number. Every bit sequence between the representation of 0 and MaxValue represents a distinct /// value, and the integer representations are ordered by value the same as the floating-point numbers they represent. /// </summary> public float Next(float value) { Debug.Assert(!float.IsNaN(value)); Debug.Assert(value != float.PositiveInfinity); if (value == 0) return float.Epsilon; if (value < 0) { if (value == -float.Epsilon) return 0.0f; // skip negative zero if (value == float.NegativeInfinity) return float.MinValue; return -UintAsFloat(FloatAsUint(-value) - 1); } if (value == float.MaxValue) return float.PositiveInfinity; return UintAsFloat(FloatAsUint(value) + 1); } private static unsafe uint FloatAsUint(float d) { if (d == 0) return 0; float* dp = &d; uint* lp = (uint*)dp; return *lp; } private static unsafe float UintAsFloat(uint l) { uint* lp = &l; float* dp = (float*)lp; return *dp; } bool INumericTC<float>.Related(BinaryOperatorKind relation, float left, float right) { switch (relation) { case Equal: return left == right || float.IsNaN(left) && float.IsNaN(right); // for our purposes, NaNs are equal case GreaterThanOrEqual: return left >= right; case GreaterThan: return left > right; case LessThanOrEqual: return left <= right; case LessThan: return left < right; default: throw new ArgumentException("relation"); } } float INumericTC<float>.FromConstantValue(ConstantValue constantValue) => constantValue.IsBad ? 0.0F : constantValue.SingleValue; ConstantValue INumericTC<float>.ToConstantValue(float value) => ConstantValue.Create(value); /// <summary> /// Produce a string for testing purposes that is likely to be the same independent of platform and locale. /// </summary> string INumericTC<float>.ToString(float value) => float.IsNaN(value) ? "NaN" : value == float.NegativeInfinity ? "-Inf" : value == float.PositiveInfinity ? "Inf" : FormattableString.Invariant($"{value:G9}"); float INumericTC<float>.Prev(float value) { return -Next(-value); } float INumericTC<float>.Random(Random random) { return (float)(random.NextDouble() * 100 - 50); } } } }