File: Utilities\ValueSetFactory.NumericValueSetFactory.cs
Web Access
Project: ..\..\..\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 Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp
{
    using static BinaryOperatorKind;
 
    internal static partial class ValueSetFactory
    {
        /// <summary>
        /// The implementation of a value set factory of any numeric type <typeparamref name="T"/>,
        /// parameterized by a type class
        /// <see cref="INumericTC{T}"/> that provides the primitives for that type.
        /// </summary>
        private sealed class NumericValueSetFactory<T, TTC> : IValueSetFactory<T> where TTC : struct, INumericTC<T>
        {
            public static readonly NumericValueSetFactory<T, TTC> Instance = new NumericValueSetFactory<T, TTC>();
 
            IValueSet IValueSetFactory.AllValues => NumericValueSet<T, TTC>.AllValues;
 
            IValueSet IValueSetFactory.NoValues => NumericValueSet<T, TTC>.NoValues;
 
            private NumericValueSetFactory() { }
 
            public IValueSet<T> Related(BinaryOperatorKind relation, T value)
            {
                TTC tc = default;
                switch (relation)
                {
                    case LessThan:
                        if (tc.Related(LessThanOrEqual, value, tc.MinValue))
                            return NumericValueSet<T, TTC>.NoValues;
                        return new NumericValueSet<T, TTC>(tc.MinValue, tc.Prev(value));
                    case LessThanOrEqual:
                        return new NumericValueSet<T, TTC>(tc.MinValue, value);
                    case GreaterThan:
                        if (tc.Related(GreaterThanOrEqual, value, tc.MaxValue))
                            return NumericValueSet<T, TTC>.NoValues;
                        return new NumericValueSet<T, TTC>(tc.Next(value), tc.MaxValue);
                    case GreaterThanOrEqual:
                        return new NumericValueSet<T, TTC>(value, tc.MaxValue);
                    case Equal:
                        return new NumericValueSet<T, TTC>(value, value);
                    default:
                        throw ExceptionUtilities.UnexpectedValue(relation);
                }
            }
 
            IValueSet IValueSetFactory.Related(BinaryOperatorKind relation, ConstantValue value) =>
                value.IsBad ? NumericValueSet<T, TTC>.AllValues : Related(relation, default(TTC).FromConstantValue(value));
 
            public IValueSet Random(int expectedSize, Random random) =>
                NumericValueSet<T, TTC>.Random(expectedSize, random);
 
            ConstantValue IValueSetFactory.RandomValue(Random random)
            {
                var tc = default(TTC);
                return tc.ToConstantValue(tc.Random(random));
            }
 
            bool IValueSetFactory.Related(BinaryOperatorKind relation, ConstantValue left, ConstantValue right)
            {
                var tc = default(TTC);
                return tc.Related(relation, tc.FromConstantValue(left), tc.FromConstantValue(right));
            }
        }
    }
}